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
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
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
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
00140
00141 set.getEdges().clear();
00142 }
00143 }
00144
00145 HashMap<Node, VisNode> nodes=new HashMap<Node,VisNode>();
00146
00148 public void update(Node set){
00149
00150 for(Node n: set.getFromNodes())
00151 if(!nodes.containsKey(n) && !n.type.equals("Set")){
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
00160
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){
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);
00179 if (tmp.x>CUTOFF_DISTANCE || tmp.x<-CUTOFF_DISTANCE ||
00180 tmp.y>CUTOFF_DISTANCE || tmp.y<-CUTOFF_DISTANCE ||
00181 tmp.z>CUTOFF_DISTANCE || tmp.z<-CUTOFF_DISTANCE ) return;
00182
00183
00184
00185 float l=tmp.length();
00186
00187 l=Math.max(1,l);
00188
00189 tmp.scale(REPELL/l/l/l);
00190
00191 Vector3f.add(p2, tmp, p2);
00192 Vector3f.sub(p1, tmp, p1);
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;
00212
00213
00214 for(VisNode n : children){
00215 n.position=new DeltaVector3f(n.position);
00216
00217
00218 n.position.y*=.9998f;
00219 n.position.scale(.9999f);
00220 }
00221
00222
00223 Partition part=new Partition(children, CUTOFF_DISTANCE);
00224
00225
00226 for (Map.Entry<Partition.Triple,List<VisNode>> entry: part.entrySet()){
00227 Partition.Triple triple=entry.getKey();
00228 List<VisNode>cell=entry.getValue();
00229
00230
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
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
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);
00261 Vector3f.sub(n1.position, tmp, n1.position);
00262 }
00263
00264 float maxspeed=0;
00265
00266
00267
00268
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
00285 for (VisEdge e: edges.values())
00286 e.renderSelf();
00287 }
00288
00289 }