VisClient/org/hfbk/vis/visnode/VisSet.java

Go to the documentation of this file.
00001 package org.hfbk.vis.visnode;
00002 
00003 import java.awt.AWTEvent;
00004 import java.util.HashMap;
00005 import java.util.List;
00006 import java.util.Map;
00007 
00008 import org.dronus.gl.GLTextPanel;
00009 import org.dronus.gl.GLUtil;
00010 import org.dronus.graph.Edge;
00011 import org.dronus.graph.ForceEdge;
00012 import org.dronus.graph.Node;
00013 import org.hfbk.vis.Partition;
00014 import org.hfbk.vis.Prefs;
00015 import org.lwjgl.opengl.GL11;
00016 import org.lwjgl.util.vector.Vector3f;
00017 
00038 public class VisSet extends VisNodeDraggable {
00039 
00041         final float CUTOFF_DISTANCE=30;
00042         //final float CUTOFF_DISTANCE=10;
00043         
00045         final float ATTRACT=.025f;
00046         
00047         final float REPELL=20;
00048         
00055         class VisEdge{
00056                 VisNode from, to;
00057                 String type;
00058                 
00059                 GLTextPanel  textP;
00060                 
00061                 float force=1;
00062                 
00063                 public VisEdge(VisNode from, VisNode to, String type, float force) {
00064                         this.from=from;
00065                         this.to=to;
00066                         this.type=type;
00067                         this.force=force;
00068                         //textP=new GLTextPanel(type,0,0);
00069                 }               
00070                 
00073                 public boolean equals(Object obj) {
00074                         return (obj instanceof VisEdge
00075                                         && ((VisEdge)obj).from==from
00076                                         && ((VisEdge)obj).to  ==to
00077                         );
00078                 }
00079                 public int hashCode() { return from.hashCode()^to.hashCode();   }
00080                 
00085                 void renderSelf() {
00086                         Vector3f p1=new Vector3f(from.position);
00087                         Vector3f p2=new Vector3f(  to.position);
00088                         
00089                         GL11.glBegin(GL11.GL_LINES);
00090                         GL11.glColor3f(1,1,1);
00091                         GL11.glVertex3f(p1.x,p1.y,p1.z);
00092                         //GL11.glColor3f(.2f,1,.5f);
00093                         GL11.glColor4f(1,1,1,.5f);
00094                         GL11.glVertex3f(p2.x,p2.y,p2.z);
00095                         GL11.glEnd();
00096                         
00097                         p1.scale(.5f); p2.scale(.5f);
00098                         Vector3f mid=Vector3f.add(p1,p2,null);
00099         
00100                         if (textP!=null){
00101                                 GL11.glPushMatrix();
00102                                 GL11.glTranslatef(mid.x,mid.y,mid.z);
00103                                 GLUtil.alignDirection(Vector3f.sub(from.position,to.position,null));
00104                 
00105                                 textP.render();
00106                                 GL11.glDisable(GL11.GL_TEXTURE_2D);
00107                                 GL11.glPopMatrix();
00108                         }
00109                 }
00110         }
00111         
00113         HashMap<Edge,VisEdge> edges=new HashMap<Edge,VisEdge>(); 
00114         
00121         VisNode create(Node node, Vector3f pos){
00122                 return new VisKeyword(new Node(node.text+" ("+node.type+")"), pos);
00123         }
00124         
00134         public VisSet(Node set, Vector3f pos) {
00135                 super(set, pos);
00136 
00137                 if (set!=null) {
00138                         update(set);
00139                         //dirty: remove edges to prevent the graph parser from 
00140                         //visualizing nodes that are part of this set
00141                         set.getEdges().clear();
00142                 }
00143         }
00144 
00145         HashMap<Node, VisNode> nodes=new HashMap<Node,VisNode>();
00146 
00148         public void update(Node set){
00149                 //build visible nodes
00150                 for(Node n: set.getFromNodes())                 
00151                         if(!nodes.containsKey(n) && !n.type.equals("Set")){ //filter out subsets                                
00152                                 float x=(float)Math.random()*100, y=(float)Math.random()*10, z=(float)Math.random()*100;
00153                                 VisNode vn=create(n, new Vector3f(x,y,z));
00154                                 add(vn);
00155                                 nodes.put(n,vn);
00156                                 layoutLocked=false;
00157                         }
00158                         
00159                 //build visible edges. as every edge is refered by two nodes,
00160                 //we use a HashSet <i>edges</i> to filter out the doubles.  
00161                 for (Node n: nodes.keySet())
00162                         for (Edge e: n.getEdges())
00163                                 if (!edges.containsKey(e)){                             
00164                                         VisNode from=nodes.get(e.getFrom()), to=nodes.get(e.getTo());
00165                                         if(from!=null && to!=null){ //root set and subset edges have no VisNodes
00166                                                 float force=1;
00167                                                 if (e instanceof ForceEdge)
00168                                                         force=((ForceEdge)e).force;
00169                                                 edges.put(e, new VisEdge(from, to, e.type, force));
00170                                                 layoutLocked=false;
00171                                         }
00172                                 }
00173         }
00174 
00175         Vector3f tmp=new Vector3f();
00176         void repell(DeltaVector3f p1, DeltaVector3f p2){
00177                 
00178                 Vector3f.sub(p2.old, p1.old, tmp); //relative position
00179                 if (tmp.x>CUTOFF_DISTANCE || tmp.x<-CUTOFF_DISTANCE ||   //early cutoff if far away  
00180                         tmp.y>CUTOFF_DISTANCE || tmp.y<-CUTOFF_DISTANCE ||
00181                         tmp.z>CUTOFF_DISTANCE || tmp.z<-CUTOFF_DISTANCE ) return;
00182                 
00183                 
00184                 //float l=tmp.lengthSquared(); //square of distance
00185                 float l=tmp.length(); //square of distance
00186                 
00187                 l=Math.max(1,l); //prevent desasters on singularities (nodes on same position)
00188                 
00189                 tmp.scale(REPELL/l/l/l); //force computed as relative postition divided by 
00190                 
00191                 Vector3f.add(p2, tmp, p2); //move both nodes away from
00192                 Vector3f.sub(p1, tmp, p1); //their common center
00193         }
00194         
00195         public void render(List<AWTEvent> events) {
00196                 GL11.glDisable(GL11.GL_TEXTURE_2D);
00197                 super.render(events);
00198         }
00199         
00200         
00201         class DeltaVector3f extends Vector3f{
00202                 public DeltaVector3f(Vector3f v) {
00203                         super(v);
00204                         old=new Vector3f(v);
00205                 }
00206                 Vector3f old; 
00207         }
00208         
00209         void layout(){
00210                 
00211                 int checks=0; //stats
00212 
00213                 
00214                 for(VisNode n : children){
00215                         n.position=new DeltaVector3f(n.position);
00216                         //n.position.y*=.998f;  
00217                         //n.position.scale(.999f);                      
00218                         n.position.y*=.9998f;  
00219                         n.position.scale(.9999f);
00220                 }
00221                 
00222                 //build space partition of children
00223                 Partition part=new Partition(children, CUTOFF_DISTANCE);
00224 
00225                 //do repellant forces
00226                 for (Map.Entry<Partition.Triple,List<VisNode>>  entry: part.entrySet()){ //all cells in the partition
00227                         Partition.Triple triple=entry.getKey();
00228                         List<VisNode>cell=entry.getValue();                     
00229                         
00230                         //each node pair in this cell
00231                         int n=cell.size();                      
00232                         for(int i=0; i<n; i++){                         
00233                                 VisNode n1=cell.get(i);                         
00234                                 for (int j=0; j<i; j++){
00235                                         VisNode n2=cell.get(j);
00236                                         repell((DeltaVector3f)n1.position,(DeltaVector3f)n2.position);
00237                                         checks++;                                       
00238                                 }               
00239                         }
00240                         
00241                         //each node paired with one in the neigbouring cell
00242                         for (List<VisNode> otherCell: part.getHalfNeighbourhood(triple)){ 
00243                                 if(otherCell==null) continue;
00244                                 for (VisNode n1: cell){                         
00245                                         for (VisNode n2: otherCell){
00246                                                 repell((DeltaVector3f)n1.position,(DeltaVector3f)n2.position);
00247                                                 checks++;
00248                                         }               
00249                                 }
00250                         }
00251                 }
00252                 
00253                 //do attracting spring forces (by edges)
00254                 for (VisEdge e: edges.values()){
00255                 
00256                         VisNode n1=e.from, n2=e.to;
00257                         Vector3f.sub(((DeltaVector3f)n2.position).old, ((DeltaVector3f)n1.position).old, tmp);
00258                         
00259                         tmp.scale(-ATTRACT*e.force); 
00260                         Vector3f.add(n2.position, tmp, n2.position); //pull nodes to common center
00261                         Vector3f.sub(n1.position, tmp, n1.position);                            
00262                 }       
00263 
00264                 float maxspeed=0;
00265 //              for (VisNode n: children)                       
00266         //              maxspeed=Math.max(maxspeed, Vector3f.sub(n.position, ((DeltaVector3f)n.position).old,null).length());
00267                 
00268                 //if (maxspeed<0.05f) layoutLocked=true;
00269                 
00270                 if (Prefs.current.debug) {
00271                         int n=children.size();
00272                         System.out.println("#nodes:"+n+" #cells:"+part.size()+" mean #nodes:"+part.getMeanCount()+" #pairs:"+checks+" of "+n*n/2+" speed:"+maxspeed);                   
00273                 }
00274         }
00275         
00280         void renderSelf() {
00281         
00282                 if (!layoutLocked) layout();
00283                 
00284                 //draw edges.           
00285                 for (VisEdge e: edges.values())
00286                         e.renderSelf();
00287         }
00288         
00289 }

Generated on Tue Apr 7 17:57:22 2009 for visclient by  doxygen 1.5.1