]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.g2d/src/org/simantics/g2d/routing/algorithm2/LocalRouter.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / routing / algorithm2 / LocalRouter.java
index 90d3e6d01f6ee9aa43124aaf6445257c6b5131f4..e9063e0b19213424984b545eab29bae58a1c136e 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 java.awt.geom.Path2D;\r
-\r
-import org.simantics.g2d.routing.Constants;\r
-\r
-public class LocalRouter {\r
-\r
-    static final double   CORNER_SIZE = 1.0;\r
-\r
-    boolean roundCorners;\r
-\r
-    double aMinX;\r
-    double aMinY;\r
-    double aMaxX;\r
-    double aMaxY;\r
-\r
-    double bMinX;\r
-    double bMinY;\r
-    double bMaxX;\r
-    double bMaxY;\r
-\r
-    double sx;\r
-    double sy;\r
-\r
-    double tx;\r
-    double ty;\r
-\r
-    int sourceDirection;\r
-    int targetDirection;\r
-\r
-    Path2D path;\r
-\r
-    public LocalRouter(boolean roundCorners) {\r
-        this.roundCorners = roundCorners;\r
-    }\r
-\r
-    /**\r
-     * Case where both source and target connection directions\r
-     * are to east.\r
-     */\r
-    void routeEast() {\r
-        if(bMinX >= aMaxX || tx >= 0 && !(bMaxY < aMinY || aMaxY < bMinY)) {\r
-            if(ty != 0.0) {\r
-                /*  ______           ______\r
-                 * |      |         |      |\r
-                 * |      |----\    |      |\r
-                 * |      |    \--->|      |\r
-                 * |______|         |______|\r
-                 */\r
-                double mx = 0.5 * (aMaxX + bMinX);\r
-                point(mx, 0.0);\r
-                point(mx, ty);\r
-            }\r
-            else\r
-                ; // Just a straight line\r
-        }\r
-        else {\r
-            double x0 = bMinX;\r
-            double x1 = aMaxX;\r
-            double my;\r
-            /*      ______\r
-             *     |      |\r
-             *     |      |\r
-             *  /->|      |\r
-             *  |  |______|\r
-             *  |\r
-             *  \-------------\\r
-             *        ______  |\r
-             *       |      | |\r
-             *       |      |-/\r
-             *       |      |\r
-             *       |______|\r
-             * \r
-             * If the elements are separated in Y-direction,\r
-             * route between the elements (this is always the shortest path).\r
-             */\r
-            if(bMaxY < aMinY)      my = 0.5 * (aMinY + bMaxY);\r
-            else if(aMaxY < bMinY) my = 0.5 * (aMaxY + bMinY);\r
-            else {\r
-                /*\r
-                 *  /------------------------\\r
-                 *  |   ______      ______   |\r
-                 *  |  |      |    |      |  |\r
-                 *  |  |      |    |      |--+\r
-                 *  +->|      |    |      |  |\r
-                 *  |  |______|    |______|  |\r
-                 *  |                        |\r
-                 *  \------------------------/\r
-                 * \r
-                 * or\r
-                 * \r
-                 *    /-----------\\r
-                 *    |   ______  |\r
-                 *    |  |      | |\r
-                 *    |  |      | |\r
-                 * /--+->|      | |\r
-                 * |  ___|______| |\r
-                 * | |      |     |\r
-                 * | |      |-+---/\r
-                 * | |      | |\r
-                 * | |______| |\r
-                 * |          |\r
-                 * \----------/\r
-                 * \r
-                 * We may choose either lower or upper path.\r
-                 */\r
-                double upperX0 = bMinX;\r
-                double upperX1 = aMaxX;\r
-                double lowerX0 = bMinX;\r
-                double lowerX1 = aMaxX;\r
-                double upperY = Math.min(aMinY, bMinY);\r
-                double lowerY = Math.max(aMaxY, bMaxY);\r
-\r
-                if(aMinX < bMinX) {\r
-                    if(ty < 0.5 * (aMinY + aMaxY))\r
-                        lowerX0 = aMinX;\r
-                    else\r
-                        upperX0 = aMinX;\r
-                }\r
-\r
-                if(bMaxX > aMaxX) {\r
-                    if(ty < 0.5 * (aMinY + aMaxY))\r
-                        upperX1 = bMaxX;\r
-                    else\r
-                        lowerX1 = bMaxX;\r
-                }\r
-\r
-                double upperLength = upperX1 - upperY + (upperX1 - upperX0) + (ty - upperY) + (tx - upperX0);\r
-                double lowerLength = lowerX1 + lowerY + (lowerX1 - lowerX0) + (lowerY - ty) + (tx - lowerX0);\r
-\r
-                if(upperLength < lowerLength) {\r
-                    x0 = upperX0;\r
-                    x1 = upperX1;\r
-                    my = upperY;\r
-                }\r
-                else {\r
-                    x0 = lowerX0;\r
-                    x1 = lowerX1;\r
-                    my = lowerY;\r
-                }\r
-            }\r
-            point(x1, 0.0);\r
-            point(x1, my);\r
-            point(x0, my);\r
-            point(x0, ty);\r
-        }\r
-    }\r
-\r
-    void routeWest() {\r
-        if(tx >= 0.0) {\r
-            double fx = Math.max(aMaxX, bMaxX);\r
-            double mx = 0.5 * (aMaxX + bMinX);\r
-            if(bMinY >= 0.0 || bMaxY <= 0.0 || mx < 0.0) {\r
-                /*                   ______\r
-                 *                  |      |\r
-                 *                  |      |\r
-                 *                  |      |<-\\r
-                 *  ______          |______|  |\r
-                 * |      |                   |\r
-                 * |      |-------------------/\r
-                 * |      |\r
-                 * |______|\r
-                 */\r
-                point(fx, 0.0);\r
-            }\r
-            else {\r
-                /*             /-------------\\r
-                 *             |    ______   |\r
-                 *             |   |      |  |\r
-                 *  ______     |   |      |  |\r
-                 * |      |    |   |      |<-+\r
-                 * |      |----+   |______|  |\r
-                 * |      |    |             |\r
-                 * |______|    \-------------/\r
-                 * \r
-                 * We may choose either upper or lower path\r
-                 * by the path length.\r
-                 */\r
-                double my =\r
-                    Math.abs(bMinY) + Math.abs(ty - bMinY)\r
-                    < Math.abs(bMaxY) + Math.abs(ty - bMaxY)\r
-                    ? bMinY : bMaxY;\r
-                point(mx, 0.0);\r
-                point(mx, my);\r
-                point(fx, my);\r
-            }\r
-            point(fx, ty);\r
-        }\r
-        else {\r
-            double fx = Math.max(aMaxX, bMaxX);\r
-            double mx = 0.5 * (aMinX + bMaxX);\r
-            point(fx, 0.0);\r
-            if(ty <= aMinY || ty >= aMaxY || (tx >= mx && ty >= aMinY && ty <= aMaxY)) {\r
-                /*                   ______\r
-                 *                  |      |\r
-                 *                  |      |\r
-                 *                  |      |--\\r
-                 *  ______          |______|  |\r
-                 * |      |                   |\r
-                 * |      |<------------------/\r
-                 * |      |\r
-                 * |______|\r
-                 */\r
-                point(fx, ty);\r
-            }\r
-            else {\r
-                /*             /-------------\\r
-                 *             |    ______   |\r
-                 *             |   |      |  |\r
-                 *  ______     |   |      |  |\r
-                 * |      |    |   |      |--+\r
-                 * |      |<---+   |______|  |\r
-                 * |      |    |             |\r
-                 * |______|    \-------------/\r
-                 * \r
-                 * We may choose either upper or lower path\r
-                 * by the path length.\r
-                 */\r
-                double my =\r
-                    Math.abs(aMinY) + Math.abs(ty - aMinY)\r
-                    < Math.abs(aMaxY) + Math.abs(ty - aMaxY)\r
-                    ? aMinY : aMaxY;\r
-                point(fx, my);\r
-                point(mx, my);\r
-                point(mx, ty);\r
-            }\r
-        }\r
-    }\r
-\r
-    void routeSouth() {\r
-        if(tx > 0.0 && (bMinY >= 0.0 || (ty > 0.0 && bMinX <= aMaxX)))\r
-            point(tx, 0.0);\r
-        else if(bMinX > aMaxX) {\r
-            double mx = 0.5 * (aMaxX + bMinX);\r
-            point(mx, 0.0);\r
-            point(mx, bMinY);\r
-            point(tx, bMinY);\r
-        }\r
-        else {\r
-            double fx = aMaxX;\r
-            double my = 0.5 * (aMaxY + bMinY);\r
-            if(my < aMaxY && (tx < aMinX || ty < aMinY)) {\r
-                my = Math.min(aMinY, bMinY);\r
-                if(bMaxX > aMaxX)\r
-                    fx = bMaxX;\r
-            }\r
-            point(fx, 0.0);\r
-            point(fx, my);\r
-            point(tx, my);\r
-        }\r
-    }\r
-\r
-    double xx, xy, yx, yy;\r
-    void point(double x, double y) {\r
-        if (roundCorners) {\r
-            continuePath(x*xx + y*yx + sx, x*xy + y*yy + sy);\r
-        } else {\r
-            path.lineTo(x*xx + y*yx + sx, x*xy + y*yy + sy);\r
-        }\r
-    }\r
-\r
-    double prevX, prevY, curX, curY, nextX, nextY;\r
-    boolean first;\r
-    void beginPath(double x, double y) {\r
-        path.moveTo(x, y);\r
-        nextX = x;\r
-        nextY = y;\r
-        first = true;\r
-    }\r
-\r
-    static double dd(double d) {\r
-        if(Math.abs(d) < CORNER_SIZE*2.0)\r
-            return d*0.5;\r
-        else\r
-            return Math.signum(d)*CORNER_SIZE;\r
-    }\r
-\r
-    void continuePath(double x, double y) {\r
-        prevX = curX;\r
-        prevY = curY;\r
-        curX = nextX;\r
-        curY = nextY;\r
-        nextX = x;\r
-        nextY = y;\r
-\r
-        if(first)\r
-            first = false;\r
-        else {\r
-            double prevDeltaX = dd(prevX - curX);\r
-            double prevDeltaY = dd(prevY - curY);\r
-            double nextDeltaX = dd(nextX - curX);\r
-            double nextDeltaY = dd(nextY - curY);\r
-\r
-\r
-            path.lineTo(curX+prevDeltaX, curY+prevDeltaY);\r
-            path.quadTo(\r
-                    curX, curY,\r
-                    curX+nextDeltaX, curY+nextDeltaY);\r
-            //path.lineTo(curX+nextDeltaX, curY+nextDeltaY);\r
-\r
-            //path.lineTo(curX, curY);\r
-        }\r
-    }\r
-\r
-    void endPath() {\r
-        path.lineTo(nextX, nextY);\r
-    }\r
-\r
-    void rotate() {\r
-        double temp;\r
-\r
-        temp = tx;\r
-        tx = ty;\r
-        ty = -temp;\r
-\r
-        temp = aMinX;\r
-        aMinX = aMinY;\r
-        aMinY = -aMaxX;\r
-        aMaxX = aMaxY;\r
-        aMaxY = -temp;\r
-\r
-        temp = bMinX;\r
-        bMinX = bMinY;\r
-        bMinY = -bMaxX;\r
-        bMaxX = bMaxY;\r
-        bMaxY = -temp;\r
-\r
-        temp = xx;\r
-        xx = -xy;\r
-        xy = temp;\r
-\r
-        temp = yx;\r
-        yx = -yy;\r
-        yy = temp;\r
-\r
-        --targetDirection;\r
-        if(targetDirection < 0)\r
-            targetDirection += 4;\r
-        --sourceDirection;\r
-    }\r
-\r
-    void flip() {\r
-        double temp;\r
-\r
-        ty = -ty;\r
-\r
-        temp = aMinY;\r
-        aMinY = -aMaxY;\r
-        aMaxY = -temp;\r
-\r
-        temp = bMinY;\r
-        bMinY = -bMaxY;\r
-        bMaxY = -temp;\r
-\r
-        yx = -yx;\r
-        yy = -yy;\r
-\r
-        targetDirection = (targetDirection + 2) % 4;\r
-    }\r
-\r
-    /*\r
-     * Puts source terminal to origo and rotates the situation\r
-     * so that the connection leaves to east. Finally, the\r
-     * case where target direction is to south is eliminated\r
-     * by optionally flipping the situation.\r
-     */\r
-    void canonicalize() {\r
-        aMinX -= sx;\r
-        aMinY -= sy;\r
-        aMaxX -= sx;\r
-        aMaxY -= sy;\r
-        bMinX -= sx;\r
-        bMinY -= sy;\r
-        bMaxX -= sx;\r
-        bMaxY -= sy;\r
-        tx -= sx;\r
-        ty -= sy;\r
-        xx = yy = 1.0;\r
-        xy = yx = 0.0;\r
-        while(sourceDirection > 0)\r
-            rotate();\r
-\r
-        if(targetDirection == Constants.SOUTH)\r
-            flip();\r
-    }\r
-\r
-    public void route() {\r
-        //System.out.println("route");\r
-        //System.out.println(sourceDirection + " " + targetDirection);\r
-\r
-        path = new Path2D.Double();\r
-\r
-        if (roundCorners) {\r
-            \r
-            beginPath(sx, sy);\r
-            \r
-            if(bMinX < sx && sx < bMaxX && bMinY < sy && sy < bMaxY)\r
-                targetDirection = (targetDirection+2)&3;\r
-            if(aMinX < tx && tx < aMaxX && aMinY < ty && ty < aMaxY)\r
-                sourceDirection = (sourceDirection+2)&3;\r
-\r
-//            // Vertical and horizontal cases\r
-//            if(Math.abs(sx - tx) < 1e-5 || Math.abs(sy - ty) < 1e-5) {\r
-//                path.lineTo(tx, ty);\r
-//                return;\r
-//            }\r
-            \r
-        } else {\r
-            \r
-            path.moveTo(sx, sy);\r
-            \r
-            // Vertical and horizontal cases\r
-            // TODO Removed this seemingly incorrect code (they were already disabled in roundCorners case\r
-            /*if(Math.abs(sx - tx) < 1e-5 || Math.abs(sy - ty) < 1e-5) {\r
-                path.lineTo(tx, ty);\r
-                return;\r
-            }*/\r
-            \r
-        }\r
-\r
-        canonicalize();\r
-        switch(targetDirection) {\r
-            case Constants.EAST: routeWest(); break;\r
-            case Constants.WEST: routeEast(); break;\r
-            case Constants.NORTH: routeSouth(); break;\r
-        }\r
-        point(tx, ty);\r
-\r
-        if (roundCorners) {\r
-            endPath();\r
-        }\r
-        //System.out.println(sourceDirection + " " + targetDirection);\r
-    }\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 java.awt.geom.Path2D;
+
+import org.simantics.g2d.routing.Constants;
+
+public class LocalRouter {
+
+    static final double   CORNER_SIZE = 1.0;
+
+    boolean roundCorners;
+
+    double aMinX;
+    double aMinY;
+    double aMaxX;
+    double aMaxY;
+
+    double bMinX;
+    double bMinY;
+    double bMaxX;
+    double bMaxY;
+
+    double sx;
+    double sy;
+
+    double tx;
+    double ty;
+
+    int sourceDirection;
+    int targetDirection;
+
+    Path2D path;
+
+    public LocalRouter(boolean roundCorners) {
+        this.roundCorners = roundCorners;
+    }
+
+    /**
+     * Case where both source and target connection directions
+     * are to east.
+     */
+    void routeEast() {
+        if(bMinX >= aMaxX || tx >= 0 && !(bMaxY < aMinY || aMaxY < bMinY)) {
+            if(ty != 0.0) {
+                /*  ______           ______
+                 * |      |         |      |
+                 * |      |----\    |      |
+                 * |      |    \--->|      |
+                 * |______|         |______|
+                 */
+                double mx = 0.5 * (aMaxX + bMinX);
+                point(mx, 0.0);
+                point(mx, ty);
+            }
+            else
+                ; // Just a straight line
+        }
+        else {
+            double x0 = bMinX;
+            double x1 = aMaxX;
+            double my;
+            /*      ______
+             *     |      |
+             *     |      |
+             *  /->|      |
+             *  |  |______|
+             *  |
+             *  \-------------\
+             *        ______  |
+             *       |      | |
+             *       |      |-/
+             *       |      |
+             *       |______|
+             * 
+             * If the elements are separated in Y-direction,
+             * route between the elements (this is always the shortest path).
+             */
+            if(bMaxY < aMinY)      my = 0.5 * (aMinY + bMaxY);
+            else if(aMaxY < bMinY) my = 0.5 * (aMaxY + bMinY);
+            else {
+                /*
+                 *  /------------------------\
+                 *  |   ______      ______   |
+                 *  |  |      |    |      |  |
+                 *  |  |      |    |      |--+
+                 *  +->|      |    |      |  |
+                 *  |  |______|    |______|  |
+                 *  |                        |
+                 *  \------------------------/
+                 * 
+                 * or
+                 * 
+                 *    /-----------\
+                 *    |   ______  |
+                 *    |  |      | |
+                 *    |  |      | |
+                 * /--+->|      | |
+                 * |  ___|______| |
+                 * | |      |     |
+                 * | |      |-+---/
+                 * | |      | |
+                 * | |______| |
+                 * |          |
+                 * \----------/
+                 * 
+                 * We may choose either lower or upper path.
+                 */
+                double upperX0 = bMinX;
+                double upperX1 = aMaxX;
+                double lowerX0 = bMinX;
+                double lowerX1 = aMaxX;
+                double upperY = Math.min(aMinY, bMinY);
+                double lowerY = Math.max(aMaxY, bMaxY);
+
+                if(aMinX < bMinX) {
+                    if(ty < 0.5 * (aMinY + aMaxY))
+                        lowerX0 = aMinX;
+                    else
+                        upperX0 = aMinX;
+                }
+
+                if(bMaxX > aMaxX) {
+                    if(ty < 0.5 * (aMinY + aMaxY))
+                        upperX1 = bMaxX;
+                    else
+                        lowerX1 = bMaxX;
+                }
+
+                double upperLength = upperX1 - upperY + (upperX1 - upperX0) + (ty - upperY) + (tx - upperX0);
+                double lowerLength = lowerX1 + lowerY + (lowerX1 - lowerX0) + (lowerY - ty) + (tx - lowerX0);
+
+                if(upperLength < lowerLength) {
+                    x0 = upperX0;
+                    x1 = upperX1;
+                    my = upperY;
+                }
+                else {
+                    x0 = lowerX0;
+                    x1 = lowerX1;
+                    my = lowerY;
+                }
+            }
+            point(x1, 0.0);
+            point(x1, my);
+            point(x0, my);
+            point(x0, ty);
+        }
+    }
+
+    void routeWest() {
+        if(tx >= 0.0) {
+            double fx = Math.max(aMaxX, bMaxX);
+            double mx = 0.5 * (aMaxX + bMinX);
+            if(bMinY >= 0.0 || bMaxY <= 0.0 || mx < 0.0) {
+                /*                   ______
+                 *                  |      |
+                 *                  |      |
+                 *                  |      |<-\
+                 *  ______          |______|  |
+                 * |      |                   |
+                 * |      |-------------------/
+                 * |      |
+                 * |______|
+                 */
+                point(fx, 0.0);
+            }
+            else {
+                /*             /-------------\
+                 *             |    ______   |
+                 *             |   |      |  |
+                 *  ______     |   |      |  |
+                 * |      |    |   |      |<-+
+                 * |      |----+   |______|  |
+                 * |      |    |             |
+                 * |______|    \-------------/
+                 * 
+                 * We may choose either upper or lower path
+                 * by the path length.
+                 */
+                double my =
+                    Math.abs(bMinY) + Math.abs(ty - bMinY)
+                    < Math.abs(bMaxY) + Math.abs(ty - bMaxY)
+                    ? bMinY : bMaxY;
+                point(mx, 0.0);
+                point(mx, my);
+                point(fx, my);
+            }
+            point(fx, ty);
+        }
+        else {
+            double fx = Math.max(aMaxX, bMaxX);
+            double mx = 0.5 * (aMinX + bMaxX);
+            point(fx, 0.0);
+            if(ty <= aMinY || ty >= aMaxY || (tx >= mx && ty >= aMinY && ty <= aMaxY)) {
+                /*                   ______
+                 *                  |      |
+                 *                  |      |
+                 *                  |      |--\
+                 *  ______          |______|  |
+                 * |      |                   |
+                 * |      |<------------------/
+                 * |      |
+                 * |______|
+                 */
+                point(fx, ty);
+            }
+            else {
+                /*             /-------------\
+                 *             |    ______   |
+                 *             |   |      |  |
+                 *  ______     |   |      |  |
+                 * |      |    |   |      |--+
+                 * |      |<---+   |______|  |
+                 * |      |    |             |
+                 * |______|    \-------------/
+                 * 
+                 * We may choose either upper or lower path
+                 * by the path length.
+                 */
+                double my =
+                    Math.abs(aMinY) + Math.abs(ty - aMinY)
+                    < Math.abs(aMaxY) + Math.abs(ty - aMaxY)
+                    ? aMinY : aMaxY;
+                point(fx, my);
+                point(mx, my);
+                point(mx, ty);
+            }
+        }
+    }
+
+    void routeSouth() {
+        if(tx > 0.0 && (bMinY >= 0.0 || (ty > 0.0 && bMinX <= aMaxX)))
+            point(tx, 0.0);
+        else if(bMinX > aMaxX) {
+            double mx = 0.5 * (aMaxX + bMinX);
+            point(mx, 0.0);
+            point(mx, bMinY);
+            point(tx, bMinY);
+        }
+        else {
+            double fx = aMaxX;
+            double my = 0.5 * (aMaxY + bMinY);
+            if(my < aMaxY && (tx < aMinX || ty < aMinY)) {
+                my = Math.min(aMinY, bMinY);
+                if(bMaxX > aMaxX)
+                    fx = bMaxX;
+            }
+            point(fx, 0.0);
+            point(fx, my);
+            point(tx, my);
+        }
+    }
+
+    double xx, xy, yx, yy;
+    void point(double x, double y) {
+        if (roundCorners) {
+            continuePath(x*xx + y*yx + sx, x*xy + y*yy + sy);
+        } else {
+            path.lineTo(x*xx + y*yx + sx, x*xy + y*yy + sy);
+        }
+    }
+
+    double prevX, prevY, curX, curY, nextX, nextY;
+    boolean first;
+    void beginPath(double x, double y) {
+        path.moveTo(x, y);
+        nextX = x;
+        nextY = y;
+        first = true;
+    }
+
+    static double dd(double d) {
+        if(Math.abs(d) < CORNER_SIZE*2.0)
+            return d*0.5;
+        else
+            return Math.signum(d)*CORNER_SIZE;
+    }
+
+    void continuePath(double x, double y) {
+        prevX = curX;
+        prevY = curY;
+        curX = nextX;
+        curY = nextY;
+        nextX = x;
+        nextY = y;
+
+        if(first)
+            first = false;
+        else {
+            double prevDeltaX = dd(prevX - curX);
+            double prevDeltaY = dd(prevY - curY);
+            double nextDeltaX = dd(nextX - curX);
+            double nextDeltaY = dd(nextY - curY);
+
+
+            path.lineTo(curX+prevDeltaX, curY+prevDeltaY);
+            path.quadTo(
+                    curX, curY,
+                    curX+nextDeltaX, curY+nextDeltaY);
+            //path.lineTo(curX+nextDeltaX, curY+nextDeltaY);
+
+            //path.lineTo(curX, curY);
+        }
+    }
+
+    void endPath() {
+        path.lineTo(nextX, nextY);
+    }
+
+    void rotate() {
+        double temp;
+
+        temp = tx;
+        tx = ty;
+        ty = -temp;
+
+        temp = aMinX;
+        aMinX = aMinY;
+        aMinY = -aMaxX;
+        aMaxX = aMaxY;
+        aMaxY = -temp;
+
+        temp = bMinX;
+        bMinX = bMinY;
+        bMinY = -bMaxX;
+        bMaxX = bMaxY;
+        bMaxY = -temp;
+
+        temp = xx;
+        xx = -xy;
+        xy = temp;
+
+        temp = yx;
+        yx = -yy;
+        yy = temp;
+
+        --targetDirection;
+        if(targetDirection < 0)
+            targetDirection += 4;
+        --sourceDirection;
+    }
+
+    void flip() {
+        double temp;
+
+        ty = -ty;
+
+        temp = aMinY;
+        aMinY = -aMaxY;
+        aMaxY = -temp;
+
+        temp = bMinY;
+        bMinY = -bMaxY;
+        bMaxY = -temp;
+
+        yx = -yx;
+        yy = -yy;
+
+        targetDirection = (targetDirection + 2) % 4;
+    }
+
+    /*
+     * Puts source terminal to origo and rotates the situation
+     * so that the connection leaves to east. Finally, the
+     * case where target direction is to south is eliminated
+     * by optionally flipping the situation.
+     */
+    void canonicalize() {
+        aMinX -= sx;
+        aMinY -= sy;
+        aMaxX -= sx;
+        aMaxY -= sy;
+        bMinX -= sx;
+        bMinY -= sy;
+        bMaxX -= sx;
+        bMaxY -= sy;
+        tx -= sx;
+        ty -= sy;
+        xx = yy = 1.0;
+        xy = yx = 0.0;
+        while(sourceDirection > 0)
+            rotate();
+
+        if(targetDirection == Constants.SOUTH)
+            flip();
+    }
+
+    public void route() {
+        //System.out.println("route");
+        //System.out.println(sourceDirection + " " + targetDirection);
+
+        path = new Path2D.Double();
+
+        if (roundCorners) {
+            
+            beginPath(sx, sy);
+            
+            if(bMinX < sx && sx < bMaxX && bMinY < sy && sy < bMaxY)
+                targetDirection = (targetDirection+2)&3;
+            if(aMinX < tx && tx < aMaxX && aMinY < ty && ty < aMaxY)
+                sourceDirection = (sourceDirection+2)&3;
+
+//            // Vertical and horizontal cases
+//            if(Math.abs(sx - tx) < 1e-5 || Math.abs(sy - ty) < 1e-5) {
+//                path.lineTo(tx, ty);
+//                return;
+//            }
+            
+        } else {
+            
+            path.moveTo(sx, sy);
+            
+            // Vertical and horizontal cases
+            // TODO Removed this seemingly incorrect code (they were already disabled in roundCorners case
+            /*if(Math.abs(sx - tx) < 1e-5 || Math.abs(sy - ty) < 1e-5) {
+                path.lineTo(tx, ty);
+                return;
+            }*/
+            
+        }
+
+        canonicalize();
+        switch(targetDirection) {
+            case Constants.EAST: routeWest(); break;
+            case Constants.WEST: routeEast(); break;
+            case Constants.NORTH: routeSouth(); break;
+        }
+        point(tx, ty);
+
+        if (roundCorners) {
+            endPath();
+        }
+        //System.out.println(sourceDirection + " " + targetDirection);
+    }
+
+}