Package prolog3d

Source Code of prolog3d.LayoutEngine

package prolog3d;
import prolog.core.IEdge;
import prolog.core.IVertex;
import prolog.core.IGraph;
import prolog.core.Cat;
import prolog.core.RankedData; //?!

import javax.media.j3d.*;
import javax.vecmath.*;

abstract public class LayoutEngine extends IGraph {
  private final Prolog3D jworld;
  protected int radius;
  int edgeLength;
 
  public boolean running;
 
  public LayoutEngine(Prolog3D jworld,Cat RG,int radius,boolean addVertex) {
    super(RG,RG.getIFilter()); // passing Cat's IFilter
    this.jworld=jworld;
    this.radius=radius;
    getCenter();
    //R.setSeed(99);
    running=true;
    //boolean addVertex=!(RG instanceof Cat);
    addGraph(RG,addVertex);
    //Prolog3D.pp("!here: "+RG);
  }

  public int setShape(RankedData RD,IVertex V) {
    int shape;
    switch(RD.hyper) {
      case 1:shape=Shape.CUBE; break;
      case 2:shape=Shape.POINT;break;
      case 3:shape=Shape.TETRA;break;
      case 4:shape=Shape.CCUBE; break;
      case 5:shape=Shape.TEXT2D;break;
      case 6:shape=Shape.TEXT3D;break;
      default: shape=Shape.SPHERE; // also 0
    }
    return shape;
  }

  public void initPosition(IVertex V,MobilePoint N) {
    Point3f RP=Params.rs(0.75f*radius);
    N.setX((double)RP.x);
    N.setY((double)RP.y);
    N.setZ((double)RP.z);
  }

  public void addGraph(Cat RG,boolean add) {
    for(int i=0;i<size();i++) {
      IVertex V=vertices[i];
  
      RankedData RD=(RankedData)RG.rawVertexData(V.key);
      //Object RS=RG.getSelected(V.key);
      Object RS=getIFilter().filterVertex(RD);
      // V = key + data
      Vertex3D GV;

      int shape=setShape(RD,V);
      Color3f color=comp2col(RD.component,RD.hyper);
 
      if(add) {
        if(shape<Shape.maxSimple)
          GV=jworld.addVertex(shape,color,V);
        else {
          Shape dataShape=new Shape(color);
          GV=jworld.addVertex(dataShape.toNode(shape,RS),RS); //$$
        }
      }
      else GV=(Vertex3D)(V.key);
     
      MobilePoint N=new MobilePoint(RS,RD,GV,radius,size());
      V.data=N; // V contains N && N contains V - careful with toString!!!

      initPosition(V,N);
    }
    for(int i=0;i<size();i++) {
      IVertex F=vertices[i];
    
      MobilePoint MFrom=(MobilePoint)(F.data);
      Vertex3D From=MFrom.V;
      
      IEdge[] es=F.outLinks;
      for(int j=0;j<es.length;j++) {
        IEdge E=es[j];
        IVertex T=vertices[E.to];
        MobilePoint MTo=(MobilePoint)(T.data);
        Vertex3D To=MTo.V;
        if(add) E.data=jworld.addEdge(From,To,E.data); //$$
      }
    }
  }
  
  public void refresh(int radius) {
    this.radius=radius;
    getCenter();
  }
 
  public void getCenter() {
    edgeLength=(int)(Math.PI*radius/size());
    edgeLength=Math.min(140,Math.max(100,edgeLength));
    //pp("edgeLength="+edgeLength+" rad="+radius);
  }
 
 
  static public void pp(Object O) {
    Prolog3D.pp(O.toString());
  }
   
  MobilePoint getPoint(int i) {
    return (MobilePoint)vertices[i].data;
  }
 
  public static Color3f comp2col(int c,int hyper) {
    c=Math.max(0,c);
    float red=(hyper>0)?0:(float)(1/(1+Math.log(1+c)));
    float green=1-red;
    float blue=0;
    //Prolog3D.pp("ranked color: c="+c+".h="+hyper+",r="+red+",g="+green+",b="+blue);
    Color3f col=new Color3f(red,green,blue);
    return col;
  }

  /**
   O(E) spring elasticity on edges
   */
  abstract public void edgeFun(int i,MobilePoint n,IEdge e,int j);
 
  /**
   O(N^2) action on vertices
   */
  abstract public void vertexStep(int i,MobilePoint n);
 
  abstract public void PointFun(DataPoint P,MobilePoint n1,MobilePoint n2);
 
  void edgeStep(int i,MobilePoint n,IEdge[] es) {
    for(int j=0; j<es.length; j++) {
      if(!running) break;
      edgeFun(i,n,es[j],j);
    }   
  }
 
  boolean trace=false;
  boolean isStable() {
    if(trace)pp("oldenergy="+oldenergy);
    stepCount++;
    if(trace)pp("energy="+energy);
    double dynamism=Math.abs(energy-oldenergy)/oldenergy-0.001*Math.log(size());
    if(trace)pp("dynamism="+dynamism);
    long smallsize=size();
    if(smallsize>200) smallsize=200;
    double youth=2*smallsize*Math.log(size())-stepCount;
    if(trace)pp("youth="+youth);
    if(trace)pp("");
    if(!running) return true;
    return dynamism<0 && youth<0;
  }
 
  long stepCount=0;
  //int sleepCount=0;
 
  long getSleepTime() {
    return Params.layoutSleep;
  }

 
  final static int maxd=5;
 
  final public double moderate(double d) {
    if(d<-maxd) d=-maxd;
    else if(d>maxd) d=maxd;
    return d;
  }
 
  double applyDelta(MobilePoint n,double energy) {
    if(!n.fixed) {
      n.dx /= 2;n.dy /= 2;n.dz /= 2;
      double dx = moderate(n.dx);
      double dy = moderate(n.dy);
      double dz = moderate(n.dz);
      double x=n.getX();
      double y=n.getY();
      double z=n.getZ();
      n.incX(dx);
      n.incY(dy);
      n.incZ(dz);
      if(!borderFun(n)) {n.setX(x);n.setY(y);n.setZ(y);n.dx=0;n.dy=0;n.dz=0;}
      energy+=(dx*dx+dy*dy+dz*dz);
    }
    return energy;
  }
 
  public boolean borderFun(MobilePoint n) { 
    float d=radius-50f;
    double x=n.getX();
    double y=n.getY();
    double z=n.getZ();
    double l=d;
    double max=10.0;
    double m=1/max;
    if (!n.fixed) {
      int i=0;
      for(;i<max;i++) {
        l=Math.sqrt(x*x+y*y+z*z);
        if(l>d) {
          x-=x*m;
          y-=y*m;
          z-=z*m;
        }
        else
          break;
      }
      if(i>0) {
        n.setX(x);
        n.setY(y);
        n.setZ(z);
        n.dx=0;
        n.dy=0;
        n.dz=0;
      }
    }
    return true;
  }

  public void stop() {
    Prolog3D.pp("layout stopping");
    running=false;
  }

  double energy=0;
  double oldenergy=size();
 
  /**
   main O(N^2+E) iteration step
   */
  synchronized void step() {
    if(Params.stopAll) running=false;
    if(energy>0) oldenergy=energy;
    energy=0;
    for (int i=0;i<size();i++) {
      if(!running) break;
      IVertex V=vertices[i];
      MobilePoint n = getPoint(i);
      vertexStep(i,n);   
      edgeStep(i,n,V.outLinks);
      energy=applyDelta(n,energy);
    }
    energy=energy/(size()*size());  
    if(isStable()) {
      if(stepCount>0) {
        double st=Math.log(stepCount);
        double si=Math.log(size());
        //pp("steps="+st);
        //pp("si="+si);
        pp("size="+size()+", steps="+stepCount+
          ", O(N^"+ (1+st/si)+ ")");
      }
      running=false;
    }
  }
 
  public void run() {
    for(;;) {
      step();
      if(!running) break;
      if(Params.layoutSleep>0) {
        Params.sleep(getSleepTime());
     
    }
    if(Params.layoutSleep==0) Params.sleep(1000);
    Prolog3D.pp("layout finished");
  }
 
}
TOP

Related Classes of prolog3d.LayoutEngine

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.