]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.debug.graphical/src/org/simantics/debug/graphical/layout/LayoutAlgorithm.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.debug.graphical / src / org / simantics / debug / graphical / layout / LayoutAlgorithm.java
diff --git a/bundles/org.simantics.debug.graphical/src/org/simantics/debug/graphical/layout/LayoutAlgorithm.java b/bundles/org.simantics.debug.graphical/src/org/simantics/debug/graphical/layout/LayoutAlgorithm.java
new file mode 100644 (file)
index 0000000..1fe13a4
--- /dev/null
@@ -0,0 +1,107 @@
+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