]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.g2d/src/org/simantics/g2d/routing/algorithm2/Router3.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / routing / algorithm2 / Router3.java
index 1bceae469d210b1b6171f93777de098a3ce9568d..7ee89a20f00704415b6084013eb7b4f38a002a44 100644 (file)
-/*******************************************************************************\r
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- *     VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.g2d.routing.algorithm2;\r
-\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-\r
-import java.awt.geom.AffineTransform;\r
-import java.awt.geom.Path2D;\r
-import java.awt.geom.PathIterator;\r
-import java.awt.geom.Rectangle2D;\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-\r
-import org.simantics.g2d.routing.Constants;\r
-import org.simantics.g2d.routing.IConnection;\r
-import org.simantics.g2d.routing.IConnection.Connector;\r
-import org.simantics.g2d.routing.IRouter2;\r
-\r
-public class Router3 implements IRouter2 {\r
-\r
-    LocalRouter localRouter;\r
-\r
-    public Router3(boolean roundCorners) {\r
-        this.localRouter = new LocalRouter(roundCorners);\r
-    }\r
-\r
-    private Path2D route(double beginX, double beginY, int sDir, Rectangle2D beginObstacle,\r
-            double endX, double endY, int tDir, Rectangle2D endObstacle) {\r
-        localRouter.sx = beginX;\r
-        localRouter.sy = beginY;\r
-        if(beginObstacle == null) {\r
-            localRouter.aMinX = beginX;\r
-            localRouter.aMinY = beginY;\r
-            localRouter.aMaxX = beginX;\r
-            localRouter.aMaxY = beginY;\r
-        }\r
-        else {\r
-            localRouter.aMinX = beginObstacle.getMinX();\r
-            localRouter.aMinY = beginObstacle.getMinY();\r
-            localRouter.aMaxX = beginObstacle.getMaxX();\r
-            localRouter.aMaxY = beginObstacle.getMaxY();\r
-        }\r
-        localRouter.sourceDirection = sDir;\r
-\r
-        localRouter.tx = endX;\r
-        localRouter.ty = endY;\r
-        if(endObstacle == null) {\r
-            localRouter.bMinX = endX;\r
-            localRouter.bMinY = endY;\r
-            localRouter.bMaxX = endX;\r
-            localRouter.bMaxY = endY;\r
-        }\r
-        else {\r
-            localRouter.bMinX = endObstacle.getMinX();\r
-            localRouter.bMinY = endObstacle.getMinY();\r
-            localRouter.bMaxX = endObstacle.getMaxX();\r
-            localRouter.bMaxY = endObstacle.getMaxY();\r
-        }\r
-        localRouter.targetDirection = tDir;\r
-\r
-        localRouter.route();\r
-\r
-        return localRouter.path;\r
-    }\r
-\r
-    @Override\r
-    public void route(IConnection connection) {\r
-//        System.out.println("route");\r
-\r
-        Collection<?> segments = connection.getSegments();\r
-        if(segments.size() == 1)\r
-            for(Object seg : segments) {\r
-                Connector begin = connection.getBegin(seg);\r
-                Connector end = connection.getEnd(seg);\r
-\r
-                double bestLength = Double.POSITIVE_INFINITY;\r
-                Path2D bestPath = null;\r
-\r
-                for(int sDir : Constants.POSSIBLE_DIRECTIONS[begin.allowedDirections])\r
-                    for(int tDir : Constants.POSSIBLE_DIRECTIONS[end.allowedDirections]) {\r
-                        Path2D path = route(begin.x, begin.y, sDir, begin.parentObstacle,\r
-                                end.x, end.y, tDir, end.parentObstacle);\r
-\r
-                        double length = pathCost(path);\r
-                        if(length < bestLength) {\r
-                            bestLength = length;\r
-                            bestPath = localRouter.path;\r
-                        }\r
-                    }\r
-\r
-                if(bestPath != null)\r
-                    connection.setPath(seg, bestPath);\r
-            }\r
-        else {\r
-\r
-            SegmentInfo[] sInfos = new SegmentInfo[segments.size()];\r
-            TObjectIntHashMap<Connector> connectorIds = new TObjectIntHashMap<Connector>();\r
-            int sId = 0;\r
-            int cId = 0;\r
-            for(Object seg : segments) {\r
-                Connector begin = connection.getBegin(seg);\r
-                Connector end = connection.getEnd(seg);\r
-\r
-                SegmentInfo sInfo = new SegmentInfo();\r
-                sInfo.segment = seg;\r
-                if(connectorIds.contains(begin))\r
-                    sInfo.begin = connectorIds.get(begin);\r
-                else {\r
-                    sInfo.begin = cId;\r
-                    connectorIds.put(begin, cId);\r
-                    cId += 4;\r
-                }\r
-                if(connectorIds.contains(end))\r
-                    sInfo.end = connectorIds.get(end);\r
-                else {\r
-                    sInfo.end = cId;\r
-                    connectorIds.put(end, cId);\r
-                    cId += 4;\r
-                }\r
-\r
-                for(int sDir : Constants.POSSIBLE_DIRECTIONS[begin.allowedDirections])\r
-                    for(int tDir : Constants.POSSIBLE_DIRECTIONS[end.allowedDirections]) {\r
-                        Path2D path = route(begin.x, begin.y, sDir, begin.parentObstacle,\r
-                                end.x, end.y, tDir, end.parentObstacle);\r
-\r
-                        sInfo.candidates.add(new SegmentCandidate(\r
-                                path, pathCost(path),\r
-                                sDir, tDir\r
-                        ));\r
-                    }\r
-\r
-                sInfos[sId++] = sInfo;\r
-            }\r
-\r
-            bestCost = Double.POSITIVE_INFINITY;\r
-            bestPaths = new Path2D[sId];\r
-            findBestCandidate(0, sInfos, new Path2D[sId], new int[cId], 0.0);\r
-            //System.out.println("cost: " + bestCost);\r
-            for(int i=0;i<sId;++i) {\r
-                connection.setPath(sInfos[i].segment, bestPaths[i]);\r
-            }\r
-        }\r
-    }\r
-\r
-    double bestCost;\r
-    Path2D[] bestPaths;\r
-\r
-    void findBestCandidate(int seg, SegmentInfo[] sInfos, Path2D[] chosen, int[] dirCounts, double cost) {\r
-        if(cost >= bestCost)\r
-            return;\r
-        if(seg < sInfos.length) {\r
-            for(SegmentCandidate sCand : sInfos[seg].candidates) {\r
-                chosen[seg] = sCand.path;\r
-                int sId = sInfos[seg].begin + sCand.sDir;\r
-                int tId = sInfos[seg].end + sCand.tDir;\r
-                double nCost = cost + sCand.localCost;\r
-                if(++dirCounts[sId] > 1)\r
-                    nCost += 10.0;\r
-                nCost += 2.0 * (dirCounts[sId ^ 1] + dirCounts[sId ^ 3]);\r
-                if(++dirCounts[tId] > 1)\r
-                    nCost += 10.0;\r
-                nCost += 2.0 * (dirCounts[tId ^ 1] + dirCounts[tId ^ 3]);\r
-                for(int i=0;i<seg;++i)\r
-                    nCost += 10.0*intersections(chosen[i], sCand.path);\r
-                findBestCandidate(seg+1, sInfos, chosen, dirCounts, nCost);\r
-                --dirCounts[sId];\r
-                --dirCounts[tId];\r
-            }\r
-        }\r
-        else {\r
-            bestCost = cost;\r
-            System.arraycopy(chosen, 0, bestPaths, 0, seg);\r
-        }\r
-    }\r
-\r
-    static class SegmentInfo {\r
-        Object segment;\r
-        int begin;\r
-        int end;\r
-        ArrayList<SegmentCandidate> candidates = new ArrayList<SegmentCandidate>(4);\r
-    }\r
-\r
-    static class SegmentCandidate {\r
-        Path2D path;\r
-        double localCost;\r
-        int sDir;\r
-        int tDir;\r
-\r
-        public SegmentCandidate(Path2D path, double localCost, int sDir, int tDir) {\r
-            this.path = path;\r
-            this.localCost = localCost;\r
-            this.sDir = sDir;\r
-            this.tDir = tDir;\r
-        }\r
-\r
-    }\r
-\r
-    final static AffineTransform identity = new AffineTransform();\r
-\r
-    static int intersections(Path2D path1, Path2D path2) {\r
-        int count = 0;\r
-        PathIterator it1 = path1.getPathIterator(identity);\r
-        double begin1X = 0.0, begin1Y = 0.0, end1X = 0.0, end1Y = 0.0;\r
-        double begin2X = 0.0, begin2Y = 0.0, end2X = 0.0, end2Y = 0.0;\r
-        double[] temp = new double[6];\r
-        while(!it1.isDone()) {\r
-            int t1 = it1.currentSegment(temp);\r
-            if(t1 == PathIterator.SEG_MOVETO) {\r
-                end1X = temp[0];\r
-                end1Y = temp[1];\r
-            }\r
-            else if(t1 == PathIterator.SEG_LINETO) {\r
-                begin1X = end1X;\r
-                begin1Y = end1Y;\r
-                end1X = temp[0];\r
-                end1Y = temp[1];\r
-\r
-                double min1X, min1Y, max1X, max1Y;\r
-                if(begin1X < end1X) { min1X = begin1X; max1X = end1X; }\r
-                else                { max1X = begin1X; min1X = end1X; }\r
-                if(begin1Y < end1Y) { min1Y = begin1Y; max1Y = end1Y; }\r
-                else                { max1Y = begin1Y; min1Y = end1Y; }\r
-\r
-                PathIterator it2 = path2.getPathIterator(identity);\r
-                while(!it2.isDone()) {\r
-                    int t2 = it2.currentSegment(temp);\r
-                    if(t2 == PathIterator.SEG_MOVETO) {\r
-                        end2X = temp[0];\r
-                        end2Y = temp[1];\r
-                    }\r
-                    else if(t2 == PathIterator.SEG_LINETO) {\r
-                        begin2X = end2X;\r
-                        begin2Y = end2Y;\r
-                        end2X = temp[0];\r
-                        end2Y = temp[1];\r
-\r
-                        double min2X, min2Y, max2X, max2Y;\r
-                        if(begin2X < end2X) { min2X = begin2X; max2X = end2X; }\r
-                        else                { max2X = begin2X; min2X = end2X; }\r
-                        if(begin2Y < end2Y) { min2Y = begin2Y; max2Y = end2Y; }\r
-                        else                { max2Y = begin2Y; min2Y = end2Y; }\r
-\r
-                        if( ((min1X < min2X && max2X < max1X) || (min2X < min1X && max1X < max2X)) &&\r
-                                ((min1Y < min2Y && max2Y < max1Y) || (min2Y < min1Y && max1Y < max2Y)) )\r
-                            ++ count;\r
-                    }\r
-                    it2.next();\r
-                }\r
-            }\r
-            it1.next();\r
-        }\r
-        return count;\r
-    }\r
-\r
-    final static AffineTransform IDENTITY = new AffineTransform();\r
-\r
-    static double pathCost(Path2D path) {\r
-        double length = 0.0;\r
-        PathIterator it = path.getPathIterator(IDENTITY);\r
-        double[] temp = new double[6];\r
-        double x=0.0, y=0.0;\r
-        double bendCount = 0.0;\r
-        while(!it.isDone()) {\r
-            bendCount += 1.0;\r
-            if(it.currentSegment(temp) != PathIterator.SEG_MOVETO)\r
-                length += Math.abs(x - temp[0] + y - temp[1]);\r
-            x = temp[0];\r
-            y = temp[1];\r
-            it.next();\r
-        }\r
-        //return length * (6.0 + bendCount);\r
-        return bendCount - 1.0 / length;\r
-    }\r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.g2d.routing.algorithm2;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Path2D;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Rectangle2D;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.simantics.g2d.routing.Constants;
+import org.simantics.g2d.routing.IConnection;
+import org.simantics.g2d.routing.IConnection.Connector;
+import org.simantics.g2d.routing.IRouter2;
+
+public class Router3 implements IRouter2 {
+
+    LocalRouter localRouter;
+
+    public Router3(boolean roundCorners) {
+        this.localRouter = new LocalRouter(roundCorners);
+    }
+
+    private Path2D route(double beginX, double beginY, int sDir, Rectangle2D beginObstacle,
+            double endX, double endY, int tDir, Rectangle2D endObstacle) {
+        localRouter.sx = beginX;
+        localRouter.sy = beginY;
+        if(beginObstacle == null) {
+            localRouter.aMinX = beginX;
+            localRouter.aMinY = beginY;
+            localRouter.aMaxX = beginX;
+            localRouter.aMaxY = beginY;
+        }
+        else {
+            localRouter.aMinX = beginObstacle.getMinX();
+            localRouter.aMinY = beginObstacle.getMinY();
+            localRouter.aMaxX = beginObstacle.getMaxX();
+            localRouter.aMaxY = beginObstacle.getMaxY();
+        }
+        localRouter.sourceDirection = sDir;
+
+        localRouter.tx = endX;
+        localRouter.ty = endY;
+        if(endObstacle == null) {
+            localRouter.bMinX = endX;
+            localRouter.bMinY = endY;
+            localRouter.bMaxX = endX;
+            localRouter.bMaxY = endY;
+        }
+        else {
+            localRouter.bMinX = endObstacle.getMinX();
+            localRouter.bMinY = endObstacle.getMinY();
+            localRouter.bMaxX = endObstacle.getMaxX();
+            localRouter.bMaxY = endObstacle.getMaxY();
+        }
+        localRouter.targetDirection = tDir;
+
+        localRouter.route();
+
+        return localRouter.path;
+    }
+
+    @Override
+    public void route(IConnection connection) {
+//        System.out.println("route");
+
+        Collection<?> segments = connection.getSegments();
+        if(segments.size() == 1)
+            for(Object seg : segments) {
+                Connector begin = connection.getBegin(seg);
+                Connector end = connection.getEnd(seg);
+
+                double bestLength = Double.POSITIVE_INFINITY;
+                Path2D bestPath = null;
+
+                for(int sDir : Constants.POSSIBLE_DIRECTIONS[begin.allowedDirections])
+                    for(int tDir : Constants.POSSIBLE_DIRECTIONS[end.allowedDirections]) {
+                        Path2D path = route(begin.x, begin.y, sDir, begin.parentObstacle,
+                                end.x, end.y, tDir, end.parentObstacle);
+
+                        double length = pathCost(path);
+                        if(length < bestLength) {
+                            bestLength = length;
+                            bestPath = localRouter.path;
+                        }
+                    }
+
+                if(bestPath != null)
+                    connection.setPath(seg, bestPath);
+            }
+        else {
+
+            SegmentInfo[] sInfos = new SegmentInfo[segments.size()];
+            TObjectIntHashMap<Connector> connectorIds = new TObjectIntHashMap<Connector>();
+            int sId = 0;
+            int cId = 0;
+            for(Object seg : segments) {
+                Connector begin = connection.getBegin(seg);
+                Connector end = connection.getEnd(seg);
+
+                SegmentInfo sInfo = new SegmentInfo();
+                sInfo.segment = seg;
+                if(connectorIds.contains(begin))
+                    sInfo.begin = connectorIds.get(begin);
+                else {
+                    sInfo.begin = cId;
+                    connectorIds.put(begin, cId);
+                    cId += 4;
+                }
+                if(connectorIds.contains(end))
+                    sInfo.end = connectorIds.get(end);
+                else {
+                    sInfo.end = cId;
+                    connectorIds.put(end, cId);
+                    cId += 4;
+                }
+
+                for(int sDir : Constants.POSSIBLE_DIRECTIONS[begin.allowedDirections])
+                    for(int tDir : Constants.POSSIBLE_DIRECTIONS[end.allowedDirections]) {
+                        Path2D path = route(begin.x, begin.y, sDir, begin.parentObstacle,
+                                end.x, end.y, tDir, end.parentObstacle);
+
+                        sInfo.candidates.add(new SegmentCandidate(
+                                path, pathCost(path),
+                                sDir, tDir
+                        ));
+                    }
+
+                sInfos[sId++] = sInfo;
+            }
+
+            bestCost = Double.POSITIVE_INFINITY;
+            bestPaths = new Path2D[sId];
+            findBestCandidate(0, sInfos, new Path2D[sId], new int[cId], 0.0);
+            //System.out.println("cost: " + bestCost);
+            for(int i=0;i<sId;++i) {
+                connection.setPath(sInfos[i].segment, bestPaths[i]);
+            }
+        }
+    }
+
+    double bestCost;
+    Path2D[] bestPaths;
+
+    void findBestCandidate(int seg, SegmentInfo[] sInfos, Path2D[] chosen, int[] dirCounts, double cost) {
+        if(cost >= bestCost)
+            return;
+        if(seg < sInfos.length) {
+            for(SegmentCandidate sCand : sInfos[seg].candidates) {
+                chosen[seg] = sCand.path;
+                int sId = sInfos[seg].begin + sCand.sDir;
+                int tId = sInfos[seg].end + sCand.tDir;
+                double nCost = cost + sCand.localCost;
+                if(++dirCounts[sId] > 1)
+                    nCost += 10.0;
+                nCost += 2.0 * (dirCounts[sId ^ 1] + dirCounts[sId ^ 3]);
+                if(++dirCounts[tId] > 1)
+                    nCost += 10.0;
+                nCost += 2.0 * (dirCounts[tId ^ 1] + dirCounts[tId ^ 3]);
+                for(int i=0;i<seg;++i)
+                    nCost += 10.0*intersections(chosen[i], sCand.path);
+                findBestCandidate(seg+1, sInfos, chosen, dirCounts, nCost);
+                --dirCounts[sId];
+                --dirCounts[tId];
+            }
+        }
+        else {
+            bestCost = cost;
+            System.arraycopy(chosen, 0, bestPaths, 0, seg);
+        }
+    }
+
+    static class SegmentInfo {
+        Object segment;
+        int begin;
+        int end;
+        ArrayList<SegmentCandidate> candidates = new ArrayList<SegmentCandidate>(4);
+    }
+
+    static class SegmentCandidate {
+        Path2D path;
+        double localCost;
+        int sDir;
+        int tDir;
+
+        public SegmentCandidate(Path2D path, double localCost, int sDir, int tDir) {
+            this.path = path;
+            this.localCost = localCost;
+            this.sDir = sDir;
+            this.tDir = tDir;
+        }
+
+    }
+
+    final static AffineTransform identity = new AffineTransform();
+
+    static int intersections(Path2D path1, Path2D path2) {
+        int count = 0;
+        PathIterator it1 = path1.getPathIterator(identity);
+        double begin1X = 0.0, begin1Y = 0.0, end1X = 0.0, end1Y = 0.0;
+        double begin2X = 0.0, begin2Y = 0.0, end2X = 0.0, end2Y = 0.0;
+        double[] temp = new double[6];
+        while(!it1.isDone()) {
+            int t1 = it1.currentSegment(temp);
+            if(t1 == PathIterator.SEG_MOVETO) {
+                end1X = temp[0];
+                end1Y = temp[1];
+            }
+            else if(t1 == PathIterator.SEG_LINETO) {
+                begin1X = end1X;
+                begin1Y = end1Y;
+                end1X = temp[0];
+                end1Y = temp[1];
+
+                double min1X, min1Y, max1X, max1Y;
+                if(begin1X < end1X) { min1X = begin1X; max1X = end1X; }
+                else                { max1X = begin1X; min1X = end1X; }
+                if(begin1Y < end1Y) { min1Y = begin1Y; max1Y = end1Y; }
+                else                { max1Y = begin1Y; min1Y = end1Y; }
+
+                PathIterator it2 = path2.getPathIterator(identity);
+                while(!it2.isDone()) {
+                    int t2 = it2.currentSegment(temp);
+                    if(t2 == PathIterator.SEG_MOVETO) {
+                        end2X = temp[0];
+                        end2Y = temp[1];
+                    }
+                    else if(t2 == PathIterator.SEG_LINETO) {
+                        begin2X = end2X;
+                        begin2Y = end2Y;
+                        end2X = temp[0];
+                        end2Y = temp[1];
+
+                        double min2X, min2Y, max2X, max2Y;
+                        if(begin2X < end2X) { min2X = begin2X; max2X = end2X; }
+                        else                { max2X = begin2X; min2X = end2X; }
+                        if(begin2Y < end2Y) { min2Y = begin2Y; max2Y = end2Y; }
+                        else                { max2Y = begin2Y; min2Y = end2Y; }
+
+                        if( ((min1X < min2X && max2X < max1X) || (min2X < min1X && max1X < max2X)) &&
+                                ((min1Y < min2Y && max2Y < max1Y) || (min2Y < min1Y && max1Y < max2Y)) )
+                            ++ count;
+                    }
+                    it2.next();
+                }
+            }
+            it1.next();
+        }
+        return count;
+    }
+
+    final static AffineTransform IDENTITY = new AffineTransform();
+
+    static double pathCost(Path2D path) {
+        double length = 0.0;
+        PathIterator it = path.getPathIterator(IDENTITY);
+        double[] temp = new double[6];
+        double x=0.0, y=0.0;
+        double bendCount = 0.0;
+        while(!it.isDone()) {
+            bendCount += 1.0;
+            if(it.currentSegment(temp) != PathIterator.SEG_MOVETO)
+                length += Math.abs(x - temp[0] + y - temp[1]);
+            x = temp[0];
+            y = temp[1];
+            it.next();
+        }
+        //return length * (6.0 + bendCount);
+        return bendCount - 1.0 / length;
+    }
+}