--- /dev/null
+package org.simantics.debug.graphical.layout;\r
+\r
+public class LayoutAlgorithm {\r
+\r
+ final double OPTIMAL_DISTANCE = 150.0; \r
+ final double C = 0.1;\r
+ final double K = C / OPTIMAL_DISTANCE;\r
+ final double G = K;\r
+ final double Q = C * OPTIMAL_DISTANCE * OPTIMAL_DISTANCE;\r
+ final double TOLERANCE = 1e-3;\r
+ final int MAX_ITERATIONS = 10000;\r
+ final double MAX_MOVE2 = 40000.0;\r
+ \r
+ int size;\r
+ double[] posX;\r
+ double[] posY;\r
+ double[] forceX;\r
+ double[] forceY;\r
+ \r
+ int[][] neighbors;\r
+ \r
+ public LayoutAlgorithm(int[][] neighbors) {\r
+ this.size = neighbors.length;\r
+ this.neighbors = neighbors;\r
+ this.posX = new double[size];\r
+ this.posY = new double[size];\r
+ this.forceX = new double[size];\r
+ this.forceY = new double[size];\r
+ }\r
+ \r
+ public double[] getPosX() {\r
+ return posX;\r
+ }\r
+ \r
+ public double[] getPosY() {\r
+ return posY;\r
+ }\r
+ \r
+ private void computeForces() {\r
+ for(int i=0;i<size;++i) {\r
+ double x = posX[i];\r
+ double y = posY[i];\r
+ double fx = -G * x;\r
+ double fy = -G * y;\r
+ \r
+ for(int j=0;j<size;++j)\r
+ if(j != i) {\r
+ double dx = posX[j] - x;\r
+ double dy = posY[j] - y;\r
+ double l2 = dx*dx + dy*dy;\r
+ /*double l = Math.sqrt(l2);\r
+ double l3 = l*l2;*/\r
+ fx -= Q * dx / l2;\r
+ fy -= Q * dy / l2;\r
+ }\r
+ \r
+ for(int j : neighbors[i]) {\r
+ double dx = posX[j] - x;\r
+ double dy = posY[j] - y; \r
+ double l2 = dx*dx + dy*dy;\r
+ double l = Math.sqrt(l2);\r
+ fx += K * l * dx;\r
+ fy += K * l * dy;\r
+ }\r
+ \r
+ forceX[i] = fx;\r
+ forceY[i] = fy;\r
+ }\r
+ }\r
+ \r
+ private boolean converged() {\r
+ for(int i=0;i<size;++i) {\r
+ double fx = forceX[i];\r
+ double fy = forceY[i];\r
+ double f2 = fx*fx + fy*fy;\r
+ if(f2 > TOLERANCE)\r
+ return false;\r
+ }\r
+ return true;\r
+ }\r
+ \r
+ private void moveAll() {\r
+ for(int i=0;i<size;++i) {\r
+ double fx = forceX[i];\r
+ double fy = forceY[i];\r
+ double f2 = fx*fx + fy*fy;\r
+ if(f2 > MAX_MOVE2) {\r
+ double s = Math.sqrt(MAX_MOVE2 / f2);\r
+ fx *= s;\r
+ fy *= s;\r
+ }\r
+ posX[i] += fx;\r
+ posY[i] += fy;\r
+ }\r
+ computeForces();\r
+ }\r
+ \r
+ public void optimize() {\r
+ computeForces();\r
+ \r
+ for(int iter=0;iter<MAX_ITERATIONS;++iter) {\r
+ if(converged())\r
+ break;\r
+ moveAll();\r
+ }\r
+ }\r
+}\r