]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.diagram.connection/tests/org/simantics/diagram/connection/tests/ConnectionRoutingTests.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.diagram.connection / tests / org / simantics / diagram / connection / tests / ConnectionRoutingTests.java
index 2a8395ac085267bea37ae601a8ee019353096d86..3df272a5282c447a403706bb27b0d117e4d02e0a 100644 (file)
-/*******************************************************************************\r
- * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
- * 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.diagram.connection.tests;\r
-\r
-import gnu.trove.map.hash.THashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-\r
-import java.awt.Color;\r
-import java.awt.Graphics2D;\r
-import java.awt.RenderingHints;\r
-import java.awt.image.BufferedImage;\r
-import java.io.ByteArrayInputStream;\r
-import java.io.ByteArrayOutputStream;\r
-import java.io.IOException;\r
-import java.io.ObjectInputStream;\r
-import java.io.ObjectOutputStream;\r
-import java.util.Arrays;\r
-\r
-import org.junit.Assert;\r
-import org.junit.Test;\r
-import org.simantics.diagram.connection.RouteGraph;\r
-import org.simantics.diagram.connection.RouteLine;\r
-import org.simantics.diagram.connection.RouteLink;\r
-import org.simantics.diagram.connection.RoutePoint;\r
-import org.simantics.diagram.connection.RouteTerminal;\r
-import org.simantics.diagram.connection.delta.RouteGraphDelta;\r
-import org.simantics.diagram.connection.rendering.ExampleConnectionStyle;\r
-import org.simantics.diagram.connection.rendering.IRouteGraphRenderer;\r
-import org.simantics.diagram.connection.rendering.StyledRouteGraphRenderer;\r
-import org.simantics.diagram.connection.rendering.arrows.ArrowExampleLineEndStyle;\r
-import org.simantics.diagram.connection.rendering.arrows.ILineEndStyle;\r
-import org.simantics.diagram.connection.rendering.arrows.PlainExampleLineEndStyle;\r
-import org.simantics.diagram.connection.rendering.arrows.PlainLineEndStyle;\r
-\r
-public class ConnectionRoutingTests {\r
-\r
-    public static final double TOLERANCE = 1e-4;\r
-    \r
-    public RouteTerminal addTerminal(RouteGraph rg, double x, double y, int ad) {\r
-        return rg.addTerminal(x, y, x-1, y-1, x+1, y+1, ad);\r
-    }\r
-       \r
-    public RouteTerminal addTerminal(RouteGraph rg, double x, double y, int ad, ILineEndStyle style) {\r
-        return rg.addTerminal(x, y, x-1, y-1, x+1, y+1, ad, style);\r
-    }\r
-    \r
-    private double[] routeSimpleConnection(double x, double y, int ad1, int ad2) {\r
-        RouteGraph rg = new RouteGraph();\r
-        RouteTerminal a = addTerminal(rg, 0, 0, ad1);\r
-        RouteTerminal b = addTerminal(rg, x, y, ad2);\r
-        rg.link(a, b);\r
-        return rg.getLineLengths(a);\r
-    }\r
-    \r
-    public void testRoute(double x, double y, int ad, double[] expected) {\r
-        Assert.assertArrayEquals(expected, routeSimpleConnection(x, y, 1, ad), TOLERANCE);\r
-    }\r
-    \r
-    @Test\r
-    public void testRoutingConsistency() {\r
-        for(double x = -2.5;x <= 2.5;x += 1.0) {\r
-            for(double y = -2.5;y <= 2.5;y += 1.0) {\r
-                if(Math.abs(x) > 2.0 || Math.abs(y) > 2.0) {\r
-                    for(int dir = 0;dir < 4;++dir)\r
-                        if(dir != 2 || x != -2.5 || Math.abs(y) > 1.5) // cannot be consistent\r
-                            testRoutingConsistency(x, y, dir);\r
-                }\r
-            }   \r
-        }\r
-    }\r
-    \r
-    private static final boolean DEBUG_ROUTING_CONSISTENCY = false;\r
-    private void testRoutingConsistency(double origX, double origY, int origDir) {\r
-        double[] expected = routeSimpleConnection(origX, origY, 1, 1<<origDir);\r
-        \r
-        if(DEBUG_ROUTING_CONSISTENCY)\r
-            System.out.println("(" + origX + "," + origY + ") dir" + origDir + ": " + \r
-                    Arrays.toString(expected));\r
-        \r
-        for(int rotation=0;rotation<4;++rotation)\r
-            for(int mirror=0;mirror<2;++mirror) {\r
-                double x = origX;\r
-                double y = mirror==1 ? -origY : origY;\r
-                int dir = origDir;\r
-                if(mirror == 1) {\r
-                    if(dir == 1)\r
-                        dir = 3;\r
-                    else if(dir == 3)\r
-                        dir = 1;\r
-                }\r
-                for(int i=0;i<rotation;++i) {\r
-                    double temp = x;\r
-                    x = -y;\r
-                    y = temp;\r
-                }\r
-                \r
-                double[] actual = routeSimpleConnection(x, y, 1<<rotation, 1<<((dir+rotation)%4));\r
-                if(DEBUG_ROUTING_CONSISTENCY)\r
-                    System.out.println(mirror + " " + rotation + " -- " + \r
-                            Arrays.toString(actual));\r
-                Assert.assertArrayEquals(expected, actual, TOLERANCE);\r
-            }\r
-    }\r
-\r
-    @Test\r
-    public void testSimpleConnection1() {\r
-        \r
-        final double X = -0.5;\r
-        final double Y = -2.5;\r
-        testRoute(X, Y, 1, new double[] {1, 2.5, 1.5});\r
-        testRoute(X, Y, 2, new double[] {1, 1.25, 1.5, 1.25});\r
-        testRoute(X, Y, 4, new double[] {1, 1.25, 2.5, 1.25, 1});\r
-        testRoute(X, Y, 8, new double[] {1, 3.5, 1.5, 1});\r
-        \r
-    }\r
-    \r
-    @Test\r
-    public void testSimpleConnection2() {\r
-        \r
-        final double X = 0.5;\r
-        final double Y = -4;\r
-        testRoute(X, Y, 1, new double[] {1.5, 4, 1});\r
-        testRoute(X, Y, 2, new double[] {1, 2, 0.5, 2});\r
-        testRoute(X, Y, 4, new double[] {1, 2, 1.5, 2, 1});\r
-        testRoute(X, Y, 8, new double[] {1.5, 5, 1, 1});\r
-        \r
-    }\r
-    \r
-    @Test\r
-    public void testSimpleConnection3() {\r
-        \r
-        final double X = -3;\r
-        final double Y = 0;\r
-        testRoute(X, Y, 1, new double[] {1, 1, 2.5, 1, 1.5});\r
-        testRoute(X, Y, 2, new double[] {1, 1, 4, 1});\r
-        testRoute(X, Y, 4, new double[] {1, 1, 5, 1, 1});\r
-        testRoute(X, Y, 8, new double[] {1, 1, 4, 1});\r
-        \r
-    }\r
-    \r
-    @Test\r
-    public void testSimpleConnection4() {\r
-        \r
-        final double X = 3;\r
-        final double Y = 0;\r
-        testRoute(X, Y, 1, new double[] {1.5, 1, 2.5, 1, 1});\r
-        testRoute(X, Y, 2, new double[] {1.5, 1, 1.5, 1});\r
-        testRoute(X, Y, 4, new double[] {3});\r
-        testRoute(X, Y, 8, new double[] {1.5, 1, 1.5, 1});\r
-        \r
-    }\r
-    \r
-    @Test\r
-    public void testSimpleConnection5() {\r
-        \r
-        final double X = -4;\r
-        final double Y = 0.5;\r
-        testRoute(X, Y, 1, new double[] {1, 1, 3, 0.5, 2});\r
-        testRoute(X, Y, 2, new double[] {1, 1.5, 5, 1});\r
-        // testRoute(X, Y, 4, ); // not consistent\r
-        testRoute(X, Y, 8, new double[] {1, 1, 5, 1.5});\r
-        \r
-    }\r
-    \r
-    @Test\r
-    public void testSimpleConnection6() {        \r
-        final double X = 4;\r
-        final double Y = 3;\r
-        testRoute(X, Y, 1, new double[] {5, 3, 1});\r
-        testRoute(X, Y, 2, new double[] {2, 4, 2, 1});\r
-        testRoute(X, Y, 4, new double[] {2, 3, 2});\r
-        testRoute(X, Y, 8, new double[] {4, 3});\r
-        \r
-    }\r
-    \r
-    @Test\r
-    public void testSimpleConnection7() {        \r
-        final double X = -4;\r
-        final double Y = 3;\r
-        testRoute(X, Y, 1, new double[] {1, 3, 5});\r
-        testRoute(X, Y, 2, new double[] {1, 4, 5, 1});\r
-        testRoute(X, Y, 4, new double[] {1, 1.5, 6, 1.5, 1});\r
-        testRoute(X, Y, 8, new double[] {1, 1.5, 5, 1.5});        \r
-    }\r
-    \r
-    static class Line {\r
-               double x1, y1, x2, y2;\r
-               \r
-               public Line(double x1, double y1, double x2, double y2) {\r
-                       this.x1 = x1;\r
-                       this.y1 = y1;\r
-                       this.x2 = x2;\r
-                       this.y2 = y2;\r
-               }\r
-\r
-               public Line(RoutePoint a, RoutePoint b) {\r
-                       this.x1 = a.getX();\r
-                       this.y1 = a.getY();\r
-                       this.x2 = b.getX();\r
-                       this.y2 = b.getY();\r
-               }\r
-\r
-               public Line(RouteLine line) {\r
-                       this(line.getBegin(), line.getEnd());\r
-               }\r
-               \r
-               @Override\r
-               public int hashCode() {\r
-                       final int prime = 31;\r
-                       int result = 1;\r
-                       long temp;\r
-                       temp = Double.doubleToLongBits(x1);\r
-                       result = prime * result + (int) (temp ^ (temp >>> 32));\r
-                       temp = Double.doubleToLongBits(x2);\r
-                       result = prime * result + (int) (temp ^ (temp >>> 32));\r
-                       temp = Double.doubleToLongBits(y1);\r
-                       result = prime * result + (int) (temp ^ (temp >>> 32));\r
-                       temp = Double.doubleToLongBits(y2);\r
-                       result = prime * result + (int) (temp ^ (temp >>> 32));\r
-                       return result;\r
-               }\r
-\r
-               @Override\r
-               public boolean equals(Object obj) {\r
-                       if (this == obj)\r
-                               return true;\r
-                       if (obj == null)\r
-                               return false;\r
-                       if (getClass() != obj.getClass())\r
-                               return false;\r
-                       Line other = (Line) obj;\r
-                       if (Double.doubleToLongBits(x1) != Double\r
-                                       .doubleToLongBits(other.x1))\r
-                               return false;\r
-                       if (Double.doubleToLongBits(x2) != Double\r
-                                       .doubleToLongBits(other.x2))\r
-                               return false;\r
-                       if (Double.doubleToLongBits(y1) != Double\r
-                                       .doubleToLongBits(other.y1))\r
-                               return false;\r
-                       if (Double.doubleToLongBits(y2) != Double\r
-                                       .doubleToLongBits(other.y2))\r
-                               return false;\r
-                       return true;\r
-               }\r
-       }\r
-    \r
-    public static THashSet<Line> lineDiff(RouteGraph rg1, RouteGraph rg2) {\r
-       THashSet<Line> lines = new THashSet<Line>();\r
-       \r
-       for(RouteLine line : rg1.getAllLines())\r
-               lines.add(new Line(line));\r
-       for(RouteLine line : rg2.getAllLines())\r
-           lines.remove(new Line(line));\r
-                       \r
-       return lines;\r
-    }\r
-    \r
-    private void genericSplitTest(RouteGraph rg, RouteLine lineToSplit) {\r
-       THashMap<Object, Object> map = new THashMap<Object, Object>(); \r
-       RouteGraph rgCopy = rg.copy(map);\r
-       RouteLine lineToSplitCopy = (RouteLine)map.get(lineToSplit);\r
-       \r
-       double x1 = lineToSplit.getBegin().getX();\r
-       double y1 = lineToSplit.getBegin().getY();\r
-       double x2 = lineToSplit.getEnd().getX();\r
-       double y2 = lineToSplit.getEnd().getY();\r
-       double mx = 0.5 * (x1 + x2);\r
-       double my = 0.5 * (y1 + y2);\r
-                       \r
-       rgCopy.split(lineToSplitCopy, lineToSplit.isHorizontal() ? mx : my);\r
-       THashSet<Line> diff1 = lineDiff(rg, rgCopy);\r
-       THashSet<Line> diff2 = lineDiff(rgCopy, rg);\r
-       \r
-       Assert.assertArrayEquals(new Object[] { new Line(lineToSplit) }, diff1.toArray());\r
-       Assert.assertEquals(diff2.size(), 3);           \r
-       Assert.assertTrue(diff2.contains(new Line(x1, y1, mx, my)));\r
-       Assert.assertTrue(diff2.contains(new Line(mx, my, mx, my)));\r
-       Assert.assertTrue(diff2.contains(new Line(mx, my, x2, y2)));\r
-       Assert.assertTrue(rgCopy.isTree());\r
-    }\r
-    \r
-    private void genericSplitTest(RouteGraph rg) {\r
-       Assert.assertTrue(rg.isTree());         \r
-       for(RouteLine line : rg.getAllLines())\r
-               genericSplitTest(rg, line);\r
-    }\r
-    \r
-    @Test\r
-    public void testSplit1() {\r
-        RouteGraph rg = new RouteGraph();\r
-        rg.link(\r
-                       addTerminal(rg, -10, 0, 1),\r
-                       addTerminal(rg, 10, 0, 4));\r
-        genericSplitTest(rg);\r
-    } \r
-    \r
-    @Test\r
-    public void testSplit2() {\r
-        RouteGraph rg = new RouteGraph();      \r
-        rg.link(\r
-                       addTerminal(rg, -20, -20, 1), \r
-                       addTerminal(rg, 20, 20, 4));\r
-        genericSplitTest(rg);\r
-    }\r
-    \r
-    @Test\r
-    public void testSplit3() {\r
-        RouteGraph rg = new RouteGraph();      \r
-        rg.link(\r
-                       addTerminal(rg, -20, -20, 1), \r
-                       addTerminal(rg, 20, 20, 8));\r
-        genericSplitTest(rg);\r
-    }\r
-    \r
-    @Test\r
-    public void testSplit4() {\r
-        RouteGraph rg = new RouteGraph();   \r
-        rg.link(\r
-                       addTerminal(rg, -20, -20, 1), \r
-                       rg.addLine(false, 0.0), \r
-                       addTerminal(rg, 20, 20, 4));\r
-        genericSplitTest(rg);\r
-    }\r
-    \r
-    @Test\r
-    public void testSplit5() {\r
-        RouteGraph rg = new RouteGraph();\r
-        RouteLine v = rg.addLine(false, 0.0); \r
-        rg.link(\r
-                addTerminal(rg, -20, -20, 1), \r
-                v);\r
-        rg.link(\r
-                addTerminal(rg, 20, 20, 4),\r
-                v);\r
-        rg.link(\r
-                addTerminal(rg, -20, 0, 1),\r
-                v);\r
-        genericSplitTest(rg);\r
-    }  \r
-    \r
-    @Test\r
-    public void testMerge1() {\r
-        RouteGraph rg = new RouteGraph();\r
-        RouteTerminal a = addTerminal(rg, -20, -20, 1);\r
-        RouteLine l1 = rg.addLine(false, -10);\r
-        RouteLine l2 = rg.addLine(true, 0);\r
-        RouteLine l3 = rg.addLine(false, 10);\r
-        RouteTerminal b = addTerminal(rg, 20, 20, 4);        \r
-        rg.link(a, l1, l2, l3, b);\r
-        rg.merge(l2, 0.0);\r
-        Assert.assertArrayEquals(new double[] {20,40,20}, rg.getLineLengths(a), TOLERANCE);        \r
-    }\r
-    \r
-    @Test\r
-    public void testMerge2() {\r
-        RouteGraph rg = new RouteGraph();\r
-        RouteTerminal a = addTerminal(rg, -20, -20, 1);\r
-        RouteLine l = rg.addLine(false, -10);\r
-        RouteTerminal b = addTerminal(rg, 20, 20, 4);          \r
-        rg.link(a, l, b);\r
-        rg.merge(l, 0.0);\r
-        Assert.assertArrayEquals(new double[] {20,40,20}, rg.getLineLengths(a), TOLERANCE);        \r
-    }\r
-    \r
-    @Test\r
-    public void testMerge3() {\r
-        RouteGraph rg = new RouteGraph();\r
-        RouteTerminal a = addTerminal(rg, -20, -20, 1);\r
-        RouteTerminal b = addTerminal(rg, 20, 20, 4);        \r
-        rg.link(a, b);\r
-        rg.merge((RouteLine)rg.pick(0,0), 0.0);\r
-        Assert.assertArrayEquals(new double[] {20,40,20}, rg.getLineLengths(a), TOLERANCE);        \r
-    }\r
-    \r
-    @Test\r
-    public void testDeleteCorner1() {\r
-        RouteGraph rg = new RouteGraph();\r
-        RouteTerminal a = addTerminal(rg, -20, 0, 1);\r
-        RouteLine l1 = rg.addLine(false, -10);\r
-        RouteLine l2 = rg.addLine(true, 10);\r
-        RouteLine l3 = rg.addLine(false, 10);\r
-        RouteTerminal b = addTerminal(rg, 20, 0, 4);\r
-        rg.link(a, l1, l2, l3, b);\r
-        rg.deleteCorner((RouteLink)rg.pick(10, 10));\r
-        Assert.assertArrayEquals(new double[] {10,0,30}, rg.getLineLengths(a), TOLERANCE);\r
-    }\r
-    \r
-    @Test\r
-    public void testRendering1() {\r
-        RouteGraph rg = new RouteGraph();\r
-        RouteLine l = rg.addLine(false, 0);\r
-        rg.link(addTerminal(rg, -20, -20, 1, ArrowExampleLineEndStyle.INSTANCE), l);\r
-        rg.link(addTerminal(rg, 20, 20, 4, PlainExampleLineEndStyle.INSTANCE), l);\r
-        rg.link(addTerminal(rg, -40, 0, 2, PlainLineEndStyle.INSTANCE), l);\r
-        \r
-        BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);\r
-        Graphics2D g = image.createGraphics();\r
-        g.setColor(Color.BLACK);\r
-        g.setBackground(Color.WHITE);\r
-        g.clearRect(0, 0, 200, 200);\r
-        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);\r
-        g.translate(100, 100);\r
-        new StyledRouteGraphRenderer(new ExampleConnectionStyle()).render(g, rg);\r
-                \r
-        //ImageViewer.run(image);\r
-    }\r
-    \r
-    @Test\r
-    public void testRendering2() {\r
-        RouteGraph rg = new RouteGraph();\r
-        rg.link(addTerminal(rg, -20, 0, 1), addTerminal(rg, 20, 1, 4));\r
-        \r
-        BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);\r
-        Graphics2D g = image.createGraphics();\r
-        g.setColor(Color.BLACK);\r
-        g.setBackground(Color.WHITE);\r
-        g.clearRect(0, 0, 200, 200);\r
-        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);\r
-        g.translate(100, 100);\r
-        new StyledRouteGraphRenderer(new ExampleConnectionStyle()).render(g, rg);\r
-                \r
-        //ImageViewer.run(image);\r
-    }\r
-    \r
-    @Test\r
-    public void testRendering3() {\r
-        RouteGraph rg = new RouteGraph();\r
-        rg.link(addTerminal(rg, 0, -20, 2), addTerminal(rg, 1, 20, 8));\r
-        \r
-        BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);\r
-        Graphics2D g = image.createGraphics();\r
-        g.setColor(Color.BLACK);\r
-        g.setBackground(Color.WHITE);\r
-        g.clearRect(0, 0, 200, 200);\r
-        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);\r
-        g.translate(100, 100);\r
-        new StyledRouteGraphRenderer(new ExampleConnectionStyle()).render(g, rg);\r
-                \r
-        //ImageViewer.run(image);\r
-    }\r
-    \r
-    @Test\r
-    public void testPickingLineHalves() {\r
-        RouteGraph rg = new RouteGraph();\r
-        RouteLine l = rg.addLine(false, 0);\r
-        RouteTerminal t1 = addTerminal(rg, -20, -20, 1);\r
-        /*RouteTerminal t2 = addTerminal(rg, 20, 20, 1);\r
-        RouteTerminal t3 = addTerminal(rg, -40, 0, 1);\r
-        */\r
-        rg.link(t1, l);\r
-        rg.link(addTerminal(rg, 20, 20, 1), l);\r
-        rg.link(addTerminal(rg, -40, 0, 1), l);\r
\r
-        Assert.assertEquals(t1, rg.pickLineHalf(-1, -20, 0).getLine().getTerminal());\r
-        Assert.assertEquals(null, rg.pickLineHalf(-18, -20, 0));\r
-        Assert.assertEquals(null, rg.pickLineHalf(0, -18, 0));\r
-    }\r
-    \r
-    @Test\r
-    public void testCopy() {\r
-        RouteGraph rg = new RouteGraph();\r
-        RouteLine l = rg.addLine(false, 0.0);\r
-        RouteTerminal a = addTerminal(rg, -20, -20, 1);\r
-        RouteTerminal b = addTerminal(rg, 20, 20, 4);        \r
-        rg.link(a, l, b);\r
-        \r
-        RouteGraph rgc = rg.copy();        \r
-        rgc.split((RouteLine)rgc.pick(-10, -20), -10.0);\r
-        \r
-        Assert.assertArrayEquals(new double[] {20,40,20}, rg.getLineLengths(a), TOLERANCE);        \r
-    }\r
-    \r
-    @Test\r
-    public void testConnecting1() {\r
-        RouteGraph rg = new RouteGraph();\r
-        RouteTerminal a = addTerminal(rg, -10, 0, 1);\r
-        RouteTerminal b = addTerminal(rg, 10, 0, 4);\r
-        rg.link(a, b);\r
-        rg.connectTerminal(addTerminal(rg, -10, 10, 1), 0.0, 0.0, 0.1);\r
-        Assert.assertTrue(rg.isTree());\r
-    }\r
-    \r
-    @Test\r
-    public void testConnecting2() {\r
-        RouteGraph rg = new RouteGraph();\r
-        RouteTerminal a = addTerminal(rg, -10, -10, 1);\r
-        RouteTerminal b = addTerminal(rg, 10, 10, 4);\r
-        rg.link(a, b);\r
-        rg.connectTerminal(addTerminal(rg, -10, 0, 1), 0.0, 0.0, 0.1);\r
-        Assert.assertTrue(rg.isTree());\r
-    }\r
-    \r
-    @Test\r
-    public void testDiff1() {\r
-        RouteGraph rg = new RouteGraph();\r
-        RouteTerminal a = addTerminal(rg, -10, -10, 1);\r
-        a.setData(1);\r
-        RouteLine l = rg.addLine(false, 0);\r
-        l.setData(2);\r
-        RouteTerminal b = addTerminal(rg, 10, 10, 4);\r
-        b.setData(3);\r
-        rg.link(a, l, b);\r
-        \r
-        RouteGraph rgc = rg.copy();\r
-        rgc.split(rgc.getLines().iterator().next(), 0);\r
-        \r
-        new RouteGraphDelta(rg, rgc).print();\r
-    }\r
-    \r
-    @Test\r
-    public void testSerialize1() throws IOException, ClassNotFoundException {\r
-        RouteGraph rg = new RouteGraph();\r
-        RouteTerminal a = addTerminal(rg, -10, -10, 1);\r
-        a.setData(1);\r
-        RouteLine l = rg.addLine(false, 0);\r
-        l.setData(2);\r
-        RouteTerminal b = addTerminal(rg, 10, 10, 4);\r
-        b.setData(3);\r
-        rg.link(a, l, b);\r
-\r
-        IRouteGraphRenderer renderer = new StyledRouteGraphRenderer(new ExampleConnectionStyle());\r
-\r
-        ByteArrayOutputStream bos = new ByteArrayOutputStream();\r
-        ObjectOutputStream oos = new ObjectOutputStream(bos);\r
-        oos.writeObject(rg);\r
-        oos.writeObject(renderer);\r
-\r
-        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());\r
-        ObjectInputStream ois = new ObjectInputStream(bis);\r
-        RouteGraph rgc = (RouteGraph) ois.readObject(); \r
-        //IRouteGraphRenderer rendererc = (IRouteGraphRenderer) ois.readObject();\r
-\r
-        new RouteGraphDelta(rg, rgc).print();\r
-    }\r
-    \r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2011 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.diagram.connection.tests;
+
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.set.hash.THashSet;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Arrays;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.simantics.diagram.connection.RouteGraph;
+import org.simantics.diagram.connection.RouteLine;
+import org.simantics.diagram.connection.RouteLink;
+import org.simantics.diagram.connection.RoutePoint;
+import org.simantics.diagram.connection.RouteTerminal;
+import org.simantics.diagram.connection.delta.RouteGraphDelta;
+import org.simantics.diagram.connection.rendering.ExampleConnectionStyle;
+import org.simantics.diagram.connection.rendering.IRouteGraphRenderer;
+import org.simantics.diagram.connection.rendering.StyledRouteGraphRenderer;
+import org.simantics.diagram.connection.rendering.arrows.ArrowExampleLineEndStyle;
+import org.simantics.diagram.connection.rendering.arrows.ILineEndStyle;
+import org.simantics.diagram.connection.rendering.arrows.PlainExampleLineEndStyle;
+import org.simantics.diagram.connection.rendering.arrows.PlainLineEndStyle;
+
+public class ConnectionRoutingTests {
+
+    public static final double TOLERANCE = 1e-4;
+    
+    public RouteTerminal addTerminal(RouteGraph rg, double x, double y, int ad) {
+        return rg.addTerminal(x, y, x-1, y-1, x+1, y+1, ad);
+    }
+       
+    public RouteTerminal addTerminal(RouteGraph rg, double x, double y, int ad, ILineEndStyle style) {
+        return rg.addTerminal(x, y, x-1, y-1, x+1, y+1, ad, style);
+    }
+    
+    private double[] routeSimpleConnection(double x, double y, int ad1, int ad2) {
+        RouteGraph rg = new RouteGraph();
+        RouteTerminal a = addTerminal(rg, 0, 0, ad1);
+        RouteTerminal b = addTerminal(rg, x, y, ad2);
+        rg.link(a, b);
+        return rg.getLineLengths(a);
+    }
+    
+    public void testRoute(double x, double y, int ad, double[] expected) {
+        Assert.assertArrayEquals(expected, routeSimpleConnection(x, y, 1, ad), TOLERANCE);
+    }
+    
+    @Test
+    public void testRoutingConsistency() {
+        for(double x = -2.5;x <= 2.5;x += 1.0) {
+            for(double y = -2.5;y <= 2.5;y += 1.0) {
+                if(Math.abs(x) > 2.0 || Math.abs(y) > 2.0) {
+                    for(int dir = 0;dir < 4;++dir)
+                        if(dir != 2 || x != -2.5 || Math.abs(y) > 1.5) // cannot be consistent
+                            testRoutingConsistency(x, y, dir);
+                }
+            }   
+        }
+    }
+    
+    private static final boolean DEBUG_ROUTING_CONSISTENCY = false;
+    private void testRoutingConsistency(double origX, double origY, int origDir) {
+        double[] expected = routeSimpleConnection(origX, origY, 1, 1<<origDir);
+        
+        if(DEBUG_ROUTING_CONSISTENCY)
+            System.out.println("(" + origX + "," + origY + ") dir" + origDir + ": " + 
+                    Arrays.toString(expected));
+        
+        for(int rotation=0;rotation<4;++rotation)
+            for(int mirror=0;mirror<2;++mirror) {
+                double x = origX;
+                double y = mirror==1 ? -origY : origY;
+                int dir = origDir;
+                if(mirror == 1) {
+                    if(dir == 1)
+                        dir = 3;
+                    else if(dir == 3)
+                        dir = 1;
+                }
+                for(int i=0;i<rotation;++i) {
+                    double temp = x;
+                    x = -y;
+                    y = temp;
+                }
+                
+                double[] actual = routeSimpleConnection(x, y, 1<<rotation, 1<<((dir+rotation)%4));
+                if(DEBUG_ROUTING_CONSISTENCY)
+                    System.out.println(mirror + " " + rotation + " -- " + 
+                            Arrays.toString(actual));
+                Assert.assertArrayEquals(expected, actual, TOLERANCE);
+            }
+    }
+
+    @Test
+    public void testSimpleConnection1() {
+        
+        final double X = -0.5;
+        final double Y = -2.5;
+        testRoute(X, Y, 1, new double[] {1, 2.5, 1.5});
+        testRoute(X, Y, 2, new double[] {1, 1.25, 1.5, 1.25});
+        testRoute(X, Y, 4, new double[] {1, 1.25, 2.5, 1.25, 1});
+        testRoute(X, Y, 8, new double[] {1, 3.5, 1.5, 1});
+        
+    }
+    
+    @Test
+    public void testSimpleConnection2() {
+        
+        final double X = 0.5;
+        final double Y = -4;
+        testRoute(X, Y, 1, new double[] {1.5, 4, 1});
+        testRoute(X, Y, 2, new double[] {1, 2, 0.5, 2});
+        testRoute(X, Y, 4, new double[] {1, 2, 1.5, 2, 1});
+        testRoute(X, Y, 8, new double[] {1.5, 5, 1, 1});
+        
+    }
+    
+    @Test
+    public void testSimpleConnection3() {
+        
+        final double X = -3;
+        final double Y = 0;
+        testRoute(X, Y, 1, new double[] {1, 1, 2.5, 1, 1.5});
+        testRoute(X, Y, 2, new double[] {1, 1, 4, 1});
+        testRoute(X, Y, 4, new double[] {1, 1, 5, 1, 1});
+        testRoute(X, Y, 8, new double[] {1, 1, 4, 1});
+        
+    }
+    
+    @Test
+    public void testSimpleConnection4() {
+        
+        final double X = 3;
+        final double Y = 0;
+        testRoute(X, Y, 1, new double[] {1.5, 1, 2.5, 1, 1});
+        testRoute(X, Y, 2, new double[] {1.5, 1, 1.5, 1});
+        testRoute(X, Y, 4, new double[] {3});
+        testRoute(X, Y, 8, new double[] {1.5, 1, 1.5, 1});
+        
+    }
+    
+    @Test
+    public void testSimpleConnection5() {
+        
+        final double X = -4;
+        final double Y = 0.5;
+        testRoute(X, Y, 1, new double[] {1, 1, 3, 0.5, 2});
+        testRoute(X, Y, 2, new double[] {1, 1.5, 5, 1});
+        // testRoute(X, Y, 4, ); // not consistent
+        testRoute(X, Y, 8, new double[] {1, 1, 5, 1.5});
+        
+    }
+    
+    @Test
+    public void testSimpleConnection6() {        
+        final double X = 4;
+        final double Y = 3;
+        testRoute(X, Y, 1, new double[] {5, 3, 1});
+        testRoute(X, Y, 2, new double[] {2, 4, 2, 1});
+        testRoute(X, Y, 4, new double[] {2, 3, 2});
+        testRoute(X, Y, 8, new double[] {4, 3});
+        
+    }
+    
+    @Test
+    public void testSimpleConnection7() {        
+        final double X = -4;
+        final double Y = 3;
+        testRoute(X, Y, 1, new double[] {1, 3, 5});
+        testRoute(X, Y, 2, new double[] {1, 4, 5, 1});
+        testRoute(X, Y, 4, new double[] {1, 1.5, 6, 1.5, 1});
+        testRoute(X, Y, 8, new double[] {1, 1.5, 5, 1.5});        
+    }
+    
+    static class Line {
+               double x1, y1, x2, y2;
+               
+               public Line(double x1, double y1, double x2, double y2) {
+                       this.x1 = x1;
+                       this.y1 = y1;
+                       this.x2 = x2;
+                       this.y2 = y2;
+               }
+
+               public Line(RoutePoint a, RoutePoint b) {
+                       this.x1 = a.getX();
+                       this.y1 = a.getY();
+                       this.x2 = b.getX();
+                       this.y2 = b.getY();
+               }
+
+               public Line(RouteLine line) {
+                       this(line.getBegin(), line.getEnd());
+               }
+               
+               @Override
+               public int hashCode() {
+                       final int prime = 31;
+                       int result = 1;
+                       long temp;
+                       temp = Double.doubleToLongBits(x1);
+                       result = prime * result + (int) (temp ^ (temp >>> 32));
+                       temp = Double.doubleToLongBits(x2);
+                       result = prime * result + (int) (temp ^ (temp >>> 32));
+                       temp = Double.doubleToLongBits(y1);
+                       result = prime * result + (int) (temp ^ (temp >>> 32));
+                       temp = Double.doubleToLongBits(y2);
+                       result = prime * result + (int) (temp ^ (temp >>> 32));
+                       return result;
+               }
+
+               @Override
+               public boolean equals(Object obj) {
+                       if (this == obj)
+                               return true;
+                       if (obj == null)
+                               return false;
+                       if (getClass() != obj.getClass())
+                               return false;
+                       Line other = (Line) obj;
+                       if (Double.doubleToLongBits(x1) != Double
+                                       .doubleToLongBits(other.x1))
+                               return false;
+                       if (Double.doubleToLongBits(x2) != Double
+                                       .doubleToLongBits(other.x2))
+                               return false;
+                       if (Double.doubleToLongBits(y1) != Double
+                                       .doubleToLongBits(other.y1))
+                               return false;
+                       if (Double.doubleToLongBits(y2) != Double
+                                       .doubleToLongBits(other.y2))
+                               return false;
+                       return true;
+               }
+       }
+    
+    public static THashSet<Line> lineDiff(RouteGraph rg1, RouteGraph rg2) {
+       THashSet<Line> lines = new THashSet<Line>();
+       
+       for(RouteLine line : rg1.getAllLines())
+               lines.add(new Line(line));
+       for(RouteLine line : rg2.getAllLines())
+           lines.remove(new Line(line));
+                       
+       return lines;
+    }
+    
+    private void genericSplitTest(RouteGraph rg, RouteLine lineToSplit) {
+       THashMap<Object, Object> map = new THashMap<Object, Object>(); 
+       RouteGraph rgCopy = rg.copy(map);
+       RouteLine lineToSplitCopy = (RouteLine)map.get(lineToSplit);
+       
+       double x1 = lineToSplit.getBegin().getX();
+       double y1 = lineToSplit.getBegin().getY();
+       double x2 = lineToSplit.getEnd().getX();
+       double y2 = lineToSplit.getEnd().getY();
+       double mx = 0.5 * (x1 + x2);
+       double my = 0.5 * (y1 + y2);
+                       
+       rgCopy.split(lineToSplitCopy, lineToSplit.isHorizontal() ? mx : my);
+       THashSet<Line> diff1 = lineDiff(rg, rgCopy);
+       THashSet<Line> diff2 = lineDiff(rgCopy, rg);
+       
+       Assert.assertArrayEquals(new Object[] { new Line(lineToSplit) }, diff1.toArray());
+       Assert.assertEquals(diff2.size(), 3);           
+       Assert.assertTrue(diff2.contains(new Line(x1, y1, mx, my)));
+       Assert.assertTrue(diff2.contains(new Line(mx, my, mx, my)));
+       Assert.assertTrue(diff2.contains(new Line(mx, my, x2, y2)));
+       Assert.assertTrue(rgCopy.isTree());
+    }
+    
+    private void genericSplitTest(RouteGraph rg) {
+       Assert.assertTrue(rg.isTree());         
+       for(RouteLine line : rg.getAllLines())
+               genericSplitTest(rg, line);
+    }
+    
+    @Test
+    public void testSplit1() {
+        RouteGraph rg = new RouteGraph();
+        rg.link(
+                       addTerminal(rg, -10, 0, 1),
+                       addTerminal(rg, 10, 0, 4));
+        genericSplitTest(rg);
+    } 
+    
+    @Test
+    public void testSplit2() {
+        RouteGraph rg = new RouteGraph();      
+        rg.link(
+                       addTerminal(rg, -20, -20, 1), 
+                       addTerminal(rg, 20, 20, 4));
+        genericSplitTest(rg);
+    }
+    
+    @Test
+    public void testSplit3() {
+        RouteGraph rg = new RouteGraph();      
+        rg.link(
+                       addTerminal(rg, -20, -20, 1), 
+                       addTerminal(rg, 20, 20, 8));
+        genericSplitTest(rg);
+    }
+    
+    @Test
+    public void testSplit4() {
+        RouteGraph rg = new RouteGraph();   
+        rg.link(
+                       addTerminal(rg, -20, -20, 1), 
+                       rg.addLine(false, 0.0), 
+                       addTerminal(rg, 20, 20, 4));
+        genericSplitTest(rg);
+    }
+    
+    @Test
+    public void testSplit5() {
+        RouteGraph rg = new RouteGraph();
+        RouteLine v = rg.addLine(false, 0.0); 
+        rg.link(
+                addTerminal(rg, -20, -20, 1), 
+                v);
+        rg.link(
+                addTerminal(rg, 20, 20, 4),
+                v);
+        rg.link(
+                addTerminal(rg, -20, 0, 1),
+                v);
+        genericSplitTest(rg);
+    }  
+    
+    @Test
+    public void testMerge1() {
+        RouteGraph rg = new RouteGraph();
+        RouteTerminal a = addTerminal(rg, -20, -20, 1);
+        RouteLine l1 = rg.addLine(false, -10);
+        RouteLine l2 = rg.addLine(true, 0);
+        RouteLine l3 = rg.addLine(false, 10);
+        RouteTerminal b = addTerminal(rg, 20, 20, 4);        
+        rg.link(a, l1, l2, l3, b);
+        rg.merge(l2, 0.0);
+        Assert.assertArrayEquals(new double[] {20,40,20}, rg.getLineLengths(a), TOLERANCE);        
+    }
+    
+    @Test
+    public void testMerge2() {
+        RouteGraph rg = new RouteGraph();
+        RouteTerminal a = addTerminal(rg, -20, -20, 1);
+        RouteLine l = rg.addLine(false, -10);
+        RouteTerminal b = addTerminal(rg, 20, 20, 4);          
+        rg.link(a, l, b);
+        rg.merge(l, 0.0);
+        Assert.assertArrayEquals(new double[] {20,40,20}, rg.getLineLengths(a), TOLERANCE);        
+    }
+    
+    @Test
+    public void testMerge3() {
+        RouteGraph rg = new RouteGraph();
+        RouteTerminal a = addTerminal(rg, -20, -20, 1);
+        RouteTerminal b = addTerminal(rg, 20, 20, 4);        
+        rg.link(a, b);
+        rg.merge((RouteLine)rg.pick(0,0), 0.0);
+        Assert.assertArrayEquals(new double[] {20,40,20}, rg.getLineLengths(a), TOLERANCE);        
+    }
+    
+    @Test
+    public void testDeleteCorner1() {
+        RouteGraph rg = new RouteGraph();
+        RouteTerminal a = addTerminal(rg, -20, 0, 1);
+        RouteLine l1 = rg.addLine(false, -10);
+        RouteLine l2 = rg.addLine(true, 10);
+        RouteLine l3 = rg.addLine(false, 10);
+        RouteTerminal b = addTerminal(rg, 20, 0, 4);
+        rg.link(a, l1, l2, l3, b);
+        rg.deleteCorner((RouteLink)rg.pick(10, 10));
+        Assert.assertArrayEquals(new double[] {10,0,30}, rg.getLineLengths(a), TOLERANCE);
+    }
+    
+    @Test
+    public void testRendering1() {
+        RouteGraph rg = new RouteGraph();
+        RouteLine l = rg.addLine(false, 0);
+        rg.link(addTerminal(rg, -20, -20, 1, ArrowExampleLineEndStyle.INSTANCE), l);
+        rg.link(addTerminal(rg, 20, 20, 4, PlainExampleLineEndStyle.INSTANCE), l);
+        rg.link(addTerminal(rg, -40, 0, 2, PlainLineEndStyle.INSTANCE), l);
+        
+        BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
+        Graphics2D g = image.createGraphics();
+        g.setColor(Color.BLACK);
+        g.setBackground(Color.WHITE);
+        g.clearRect(0, 0, 200, 200);
+        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+        g.translate(100, 100);
+        new StyledRouteGraphRenderer(new ExampleConnectionStyle()).render(g, rg);
+                
+        //ImageViewer.run(image);
+    }
+    
+    @Test
+    public void testRendering2() {
+        RouteGraph rg = new RouteGraph();
+        rg.link(addTerminal(rg, -20, 0, 1), addTerminal(rg, 20, 1, 4));
+        
+        BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
+        Graphics2D g = image.createGraphics();
+        g.setColor(Color.BLACK);
+        g.setBackground(Color.WHITE);
+        g.clearRect(0, 0, 200, 200);
+        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+        g.translate(100, 100);
+        new StyledRouteGraphRenderer(new ExampleConnectionStyle()).render(g, rg);
+                
+        //ImageViewer.run(image);
+    }
+    
+    @Test
+    public void testRendering3() {
+        RouteGraph rg = new RouteGraph();
+        rg.link(addTerminal(rg, 0, -20, 2), addTerminal(rg, 1, 20, 8));
+        
+        BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
+        Graphics2D g = image.createGraphics();
+        g.setColor(Color.BLACK);
+        g.setBackground(Color.WHITE);
+        g.clearRect(0, 0, 200, 200);
+        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+        g.translate(100, 100);
+        new StyledRouteGraphRenderer(new ExampleConnectionStyle()).render(g, rg);
+                
+        //ImageViewer.run(image);
+    }
+    
+    @Test
+    public void testPickingLineHalves() {
+        RouteGraph rg = new RouteGraph();
+        RouteLine l = rg.addLine(false, 0);
+        RouteTerminal t1 = addTerminal(rg, -20, -20, 1);
+        /*RouteTerminal t2 = addTerminal(rg, 20, 20, 1);
+        RouteTerminal t3 = addTerminal(rg, -40, 0, 1);
+        */
+        rg.link(t1, l);
+        rg.link(addTerminal(rg, 20, 20, 1), l);
+        rg.link(addTerminal(rg, -40, 0, 1), l);
+        Assert.assertEquals(t1, rg.pickLineHalf(-1, -20, 0).getLine().getTerminal());
+        Assert.assertEquals(null, rg.pickLineHalf(-18, -20, 0));
+        Assert.assertEquals(null, rg.pickLineHalf(0, -18, 0));
+    }
+    
+    @Test
+    public void testCopy() {
+        RouteGraph rg = new RouteGraph();
+        RouteLine l = rg.addLine(false, 0.0);
+        RouteTerminal a = addTerminal(rg, -20, -20, 1);
+        RouteTerminal b = addTerminal(rg, 20, 20, 4);        
+        rg.link(a, l, b);
+        
+        RouteGraph rgc = rg.copy();        
+        rgc.split((RouteLine)rgc.pick(-10, -20), -10.0);
+        
+        Assert.assertArrayEquals(new double[] {20,40,20}, rg.getLineLengths(a), TOLERANCE);        
+    }
+    
+    @Test
+    public void testConnecting1() {
+        RouteGraph rg = new RouteGraph();
+        RouteTerminal a = addTerminal(rg, -10, 0, 1);
+        RouteTerminal b = addTerminal(rg, 10, 0, 4);
+        rg.link(a, b);
+        rg.connectTerminal(addTerminal(rg, -10, 10, 1), 0.0, 0.0, 0.1);
+        Assert.assertTrue(rg.isTree());
+    }
+    
+    @Test
+    public void testConnecting2() {
+        RouteGraph rg = new RouteGraph();
+        RouteTerminal a = addTerminal(rg, -10, -10, 1);
+        RouteTerminal b = addTerminal(rg, 10, 10, 4);
+        rg.link(a, b);
+        rg.connectTerminal(addTerminal(rg, -10, 0, 1), 0.0, 0.0, 0.1);
+        Assert.assertTrue(rg.isTree());
+    }
+    
+    @Test
+    public void testDiff1() {
+        RouteGraph rg = new RouteGraph();
+        RouteTerminal a = addTerminal(rg, -10, -10, 1);
+        a.setData(1);
+        RouteLine l = rg.addLine(false, 0);
+        l.setData(2);
+        RouteTerminal b = addTerminal(rg, 10, 10, 4);
+        b.setData(3);
+        rg.link(a, l, b);
+        
+        RouteGraph rgc = rg.copy();
+        rgc.split(rgc.getLines().iterator().next(), 0);
+        
+        new RouteGraphDelta(rg, rgc).print();
+    }
+    
+    @Test
+    public void testSerialize1() throws IOException, ClassNotFoundException {
+        RouteGraph rg = new RouteGraph();
+        RouteTerminal a = addTerminal(rg, -10, -10, 1);
+        a.setData(1);
+        RouteLine l = rg.addLine(false, 0);
+        l.setData(2);
+        RouteTerminal b = addTerminal(rg, 10, 10, 4);
+        b.setData(3);
+        rg.link(a, l, b);
+
+        IRouteGraphRenderer renderer = new StyledRouteGraphRenderer(new ExampleConnectionStyle());
+
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        ObjectOutputStream oos = new ObjectOutputStream(bos);
+        oos.writeObject(rg);
+        oos.writeObject(renderer);
+
+        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
+        ObjectInputStream ois = new ObjectInputStream(bis);
+        RouteGraph rgc = (RouteGraph) ois.readObject(); 
+        //IRouteGraphRenderer rendererc = (IRouteGraphRenderer) ois.readObject();
+
+        new RouteGraphDelta(rg, rgc).print();
+    }
+    
+}