1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2011 Association for Decentralized Information Management in
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.diagram.connection.tests;
\r
14 import gnu.trove.map.hash.THashMap;
\r
15 import gnu.trove.set.hash.THashSet;
\r
17 import java.awt.Color;
\r
18 import java.awt.Graphics2D;
\r
19 import java.awt.RenderingHints;
\r
20 import java.awt.image.BufferedImage;
\r
21 import java.io.ByteArrayInputStream;
\r
22 import java.io.ByteArrayOutputStream;
\r
23 import java.io.IOException;
\r
24 import java.io.ObjectInputStream;
\r
25 import java.io.ObjectOutputStream;
\r
26 import java.util.Arrays;
\r
28 import org.junit.Assert;
\r
29 import org.junit.Test;
\r
30 import org.simantics.diagram.connection.RouteGraph;
\r
31 import org.simantics.diagram.connection.RouteLine;
\r
32 import org.simantics.diagram.connection.RouteLink;
\r
33 import org.simantics.diagram.connection.RoutePoint;
\r
34 import org.simantics.diagram.connection.RouteTerminal;
\r
35 import org.simantics.diagram.connection.delta.RouteGraphDelta;
\r
36 import org.simantics.diagram.connection.rendering.ExampleConnectionStyle;
\r
37 import org.simantics.diagram.connection.rendering.IRouteGraphRenderer;
\r
38 import org.simantics.diagram.connection.rendering.StyledRouteGraphRenderer;
\r
39 import org.simantics.diagram.connection.rendering.arrows.ArrowExampleLineEndStyle;
\r
40 import org.simantics.diagram.connection.rendering.arrows.ILineEndStyle;
\r
41 import org.simantics.diagram.connection.rendering.arrows.PlainExampleLineEndStyle;
\r
42 import org.simantics.diagram.connection.rendering.arrows.PlainLineEndStyle;
\r
44 public class ConnectionRoutingTests {
\r
46 public static final double TOLERANCE = 1e-4;
\r
48 public RouteTerminal addTerminal(RouteGraph rg, double x, double y, int ad) {
\r
49 return rg.addTerminal(x, y, x-1, y-1, x+1, y+1, ad);
\r
52 public RouteTerminal addTerminal(RouteGraph rg, double x, double y, int ad, ILineEndStyle style) {
\r
53 return rg.addTerminal(x, y, x-1, y-1, x+1, y+1, ad, style);
\r
56 private double[] routeSimpleConnection(double x, double y, int ad1, int ad2) {
\r
57 RouteGraph rg = new RouteGraph();
\r
58 RouteTerminal a = addTerminal(rg, 0, 0, ad1);
\r
59 RouteTerminal b = addTerminal(rg, x, y, ad2);
\r
61 return rg.getLineLengths(a);
\r
64 public void testRoute(double x, double y, int ad, double[] expected) {
\r
65 Assert.assertArrayEquals(expected, routeSimpleConnection(x, y, 1, ad), TOLERANCE);
\r
69 public void testRoutingConsistency() {
\r
70 for(double x = -2.5;x <= 2.5;x += 1.0) {
\r
71 for(double y = -2.5;y <= 2.5;y += 1.0) {
\r
72 if(Math.abs(x) > 2.0 || Math.abs(y) > 2.0) {
\r
73 for(int dir = 0;dir < 4;++dir)
\r
74 if(dir != 2 || x != -2.5 || Math.abs(y) > 1.5) // cannot be consistent
\r
75 testRoutingConsistency(x, y, dir);
\r
81 private static final boolean DEBUG_ROUTING_CONSISTENCY = false;
\r
82 private void testRoutingConsistency(double origX, double origY, int origDir) {
\r
83 double[] expected = routeSimpleConnection(origX, origY, 1, 1<<origDir);
\r
85 if(DEBUG_ROUTING_CONSISTENCY)
\r
86 System.out.println("(" + origX + "," + origY + ") dir" + origDir + ": " +
\r
87 Arrays.toString(expected));
\r
89 for(int rotation=0;rotation<4;++rotation)
\r
90 for(int mirror=0;mirror<2;++mirror) {
\r
92 double y = mirror==1 ? -origY : origY;
\r
100 for(int i=0;i<rotation;++i) {
\r
106 double[] actual = routeSimpleConnection(x, y, 1<<rotation, 1<<((dir+rotation)%4));
\r
107 if(DEBUG_ROUTING_CONSISTENCY)
\r
108 System.out.println(mirror + " " + rotation + " -- " +
\r
109 Arrays.toString(actual));
\r
110 Assert.assertArrayEquals(expected, actual, TOLERANCE);
\r
115 public void testSimpleConnection1() {
\r
117 final double X = -0.5;
\r
118 final double Y = -2.5;
\r
119 testRoute(X, Y, 1, new double[] {1, 2.5, 1.5});
\r
120 testRoute(X, Y, 2, new double[] {1, 1.25, 1.5, 1.25});
\r
121 testRoute(X, Y, 4, new double[] {1, 1.25, 2.5, 1.25, 1});
\r
122 testRoute(X, Y, 8, new double[] {1, 3.5, 1.5, 1});
\r
127 public void testSimpleConnection2() {
\r
129 final double X = 0.5;
\r
130 final double Y = -4;
\r
131 testRoute(X, Y, 1, new double[] {1.5, 4, 1});
\r
132 testRoute(X, Y, 2, new double[] {1, 2, 0.5, 2});
\r
133 testRoute(X, Y, 4, new double[] {1, 2, 1.5, 2, 1});
\r
134 testRoute(X, Y, 8, new double[] {1.5, 5, 1, 1});
\r
139 public void testSimpleConnection3() {
\r
141 final double X = -3;
\r
142 final double Y = 0;
\r
143 testRoute(X, Y, 1, new double[] {1, 1, 2.5, 1, 1.5});
\r
144 testRoute(X, Y, 2, new double[] {1, 1, 4, 1});
\r
145 testRoute(X, Y, 4, new double[] {1, 1, 5, 1, 1});
\r
146 testRoute(X, Y, 8, new double[] {1, 1, 4, 1});
\r
151 public void testSimpleConnection4() {
\r
153 final double X = 3;
\r
154 final double Y = 0;
\r
155 testRoute(X, Y, 1, new double[] {1.5, 1, 2.5, 1, 1});
\r
156 testRoute(X, Y, 2, new double[] {1.5, 1, 1.5, 1});
\r
157 testRoute(X, Y, 4, new double[] {3});
\r
158 testRoute(X, Y, 8, new double[] {1.5, 1, 1.5, 1});
\r
163 public void testSimpleConnection5() {
\r
165 final double X = -4;
\r
166 final double Y = 0.5;
\r
167 testRoute(X, Y, 1, new double[] {1, 1, 3, 0.5, 2});
\r
168 testRoute(X, Y, 2, new double[] {1, 1.5, 5, 1});
\r
169 // testRoute(X, Y, 4, ); // not consistent
\r
170 testRoute(X, Y, 8, new double[] {1, 1, 5, 1.5});
\r
175 public void testSimpleConnection6() {
\r
176 final double X = 4;
\r
177 final double Y = 3;
\r
178 testRoute(X, Y, 1, new double[] {5, 3, 1});
\r
179 testRoute(X, Y, 2, new double[] {2, 4, 2, 1});
\r
180 testRoute(X, Y, 4, new double[] {2, 3, 2});
\r
181 testRoute(X, Y, 8, new double[] {4, 3});
\r
186 public void testSimpleConnection7() {
\r
187 final double X = -4;
\r
188 final double Y = 3;
\r
189 testRoute(X, Y, 1, new double[] {1, 3, 5});
\r
190 testRoute(X, Y, 2, new double[] {1, 4, 5, 1});
\r
191 testRoute(X, Y, 4, new double[] {1, 1.5, 6, 1.5, 1});
\r
192 testRoute(X, Y, 8, new double[] {1, 1.5, 5, 1.5});
\r
195 static class Line {
\r
196 double x1, y1, x2, y2;
\r
198 public Line(double x1, double y1, double x2, double y2) {
\r
205 public Line(RoutePoint a, RoutePoint b) {
\r
206 this.x1 = a.getX();
\r
207 this.y1 = a.getY();
\r
208 this.x2 = b.getX();
\r
209 this.y2 = b.getY();
\r
212 public Line(RouteLine line) {
\r
213 this(line.getBegin(), line.getEnd());
\r
217 public int hashCode() {
\r
218 final int prime = 31;
\r
221 temp = Double.doubleToLongBits(x1);
\r
222 result = prime * result + (int) (temp ^ (temp >>> 32));
\r
223 temp = Double.doubleToLongBits(x2);
\r
224 result = prime * result + (int) (temp ^ (temp >>> 32));
\r
225 temp = Double.doubleToLongBits(y1);
\r
226 result = prime * result + (int) (temp ^ (temp >>> 32));
\r
227 temp = Double.doubleToLongBits(y2);
\r
228 result = prime * result + (int) (temp ^ (temp >>> 32));
\r
233 public boolean equals(Object obj) {
\r
238 if (getClass() != obj.getClass())
\r
240 Line other = (Line) obj;
\r
241 if (Double.doubleToLongBits(x1) != Double
\r
242 .doubleToLongBits(other.x1))
\r
244 if (Double.doubleToLongBits(x2) != Double
\r
245 .doubleToLongBits(other.x2))
\r
247 if (Double.doubleToLongBits(y1) != Double
\r
248 .doubleToLongBits(other.y1))
\r
250 if (Double.doubleToLongBits(y2) != Double
\r
251 .doubleToLongBits(other.y2))
\r
257 public static THashSet<Line> lineDiff(RouteGraph rg1, RouteGraph rg2) {
\r
258 THashSet<Line> lines = new THashSet<Line>();
\r
260 for(RouteLine line : rg1.getAllLines())
\r
261 lines.add(new Line(line));
\r
262 for(RouteLine line : rg2.getAllLines())
\r
263 lines.remove(new Line(line));
\r
268 private void genericSplitTest(RouteGraph rg, RouteLine lineToSplit) {
\r
269 THashMap<Object, Object> map = new THashMap<Object, Object>();
\r
270 RouteGraph rgCopy = rg.copy(map);
\r
271 RouteLine lineToSplitCopy = (RouteLine)map.get(lineToSplit);
\r
273 double x1 = lineToSplit.getBegin().getX();
\r
274 double y1 = lineToSplit.getBegin().getY();
\r
275 double x2 = lineToSplit.getEnd().getX();
\r
276 double y2 = lineToSplit.getEnd().getY();
\r
277 double mx = 0.5 * (x1 + x2);
\r
278 double my = 0.5 * (y1 + y2);
\r
280 rgCopy.split(lineToSplitCopy, lineToSplit.isHorizontal() ? mx : my);
\r
281 THashSet<Line> diff1 = lineDiff(rg, rgCopy);
\r
282 THashSet<Line> diff2 = lineDiff(rgCopy, rg);
\r
284 Assert.assertArrayEquals(new Object[] { new Line(lineToSplit) }, diff1.toArray());
\r
285 Assert.assertEquals(diff2.size(), 3);
\r
286 Assert.assertTrue(diff2.contains(new Line(x1, y1, mx, my)));
\r
287 Assert.assertTrue(diff2.contains(new Line(mx, my, mx, my)));
\r
288 Assert.assertTrue(diff2.contains(new Line(mx, my, x2, y2)));
\r
289 Assert.assertTrue(rgCopy.isTree());
\r
292 private void genericSplitTest(RouteGraph rg) {
\r
293 Assert.assertTrue(rg.isTree());
\r
294 for(RouteLine line : rg.getAllLines())
\r
295 genericSplitTest(rg, line);
\r
299 public void testSplit1() {
\r
300 RouteGraph rg = new RouteGraph();
\r
302 addTerminal(rg, -10, 0, 1),
\r
303 addTerminal(rg, 10, 0, 4));
\r
304 genericSplitTest(rg);
\r
308 public void testSplit2() {
\r
309 RouteGraph rg = new RouteGraph();
\r
311 addTerminal(rg, -20, -20, 1),
\r
312 addTerminal(rg, 20, 20, 4));
\r
313 genericSplitTest(rg);
\r
317 public void testSplit3() {
\r
318 RouteGraph rg = new RouteGraph();
\r
320 addTerminal(rg, -20, -20, 1),
\r
321 addTerminal(rg, 20, 20, 8));
\r
322 genericSplitTest(rg);
\r
326 public void testSplit4() {
\r
327 RouteGraph rg = new RouteGraph();
\r
329 addTerminal(rg, -20, -20, 1),
\r
330 rg.addLine(false, 0.0),
\r
331 addTerminal(rg, 20, 20, 4));
\r
332 genericSplitTest(rg);
\r
336 public void testSplit5() {
\r
337 RouteGraph rg = new RouteGraph();
\r
338 RouteLine v = rg.addLine(false, 0.0);
\r
340 addTerminal(rg, -20, -20, 1),
\r
343 addTerminal(rg, 20, 20, 4),
\r
346 addTerminal(rg, -20, 0, 1),
\r
348 genericSplitTest(rg);
\r
352 public void testMerge1() {
\r
353 RouteGraph rg = new RouteGraph();
\r
354 RouteTerminal a = addTerminal(rg, -20, -20, 1);
\r
355 RouteLine l1 = rg.addLine(false, -10);
\r
356 RouteLine l2 = rg.addLine(true, 0);
\r
357 RouteLine l3 = rg.addLine(false, 10);
\r
358 RouteTerminal b = addTerminal(rg, 20, 20, 4);
\r
359 rg.link(a, l1, l2, l3, b);
\r
361 Assert.assertArrayEquals(new double[] {20,40,20}, rg.getLineLengths(a), TOLERANCE);
\r
365 public void testMerge2() {
\r
366 RouteGraph rg = new RouteGraph();
\r
367 RouteTerminal a = addTerminal(rg, -20, -20, 1);
\r
368 RouteLine l = rg.addLine(false, -10);
\r
369 RouteTerminal b = addTerminal(rg, 20, 20, 4);
\r
372 Assert.assertArrayEquals(new double[] {20,40,20}, rg.getLineLengths(a), TOLERANCE);
\r
376 public void testMerge3() {
\r
377 RouteGraph rg = new RouteGraph();
\r
378 RouteTerminal a = addTerminal(rg, -20, -20, 1);
\r
379 RouteTerminal b = addTerminal(rg, 20, 20, 4);
\r
381 rg.merge((RouteLine)rg.pick(0,0), 0.0);
\r
382 Assert.assertArrayEquals(new double[] {20,40,20}, rg.getLineLengths(a), TOLERANCE);
\r
386 public void testDeleteCorner1() {
\r
387 RouteGraph rg = new RouteGraph();
\r
388 RouteTerminal a = addTerminal(rg, -20, 0, 1);
\r
389 RouteLine l1 = rg.addLine(false, -10);
\r
390 RouteLine l2 = rg.addLine(true, 10);
\r
391 RouteLine l3 = rg.addLine(false, 10);
\r
392 RouteTerminal b = addTerminal(rg, 20, 0, 4);
\r
393 rg.link(a, l1, l2, l3, b);
\r
394 rg.deleteCorner((RouteLink)rg.pick(10, 10));
\r
395 Assert.assertArrayEquals(new double[] {10,0,30}, rg.getLineLengths(a), TOLERANCE);
\r
399 public void testRendering1() {
\r
400 RouteGraph rg = new RouteGraph();
\r
401 RouteLine l = rg.addLine(false, 0);
\r
402 rg.link(addTerminal(rg, -20, -20, 1, ArrowExampleLineEndStyle.INSTANCE), l);
\r
403 rg.link(addTerminal(rg, 20, 20, 4, PlainExampleLineEndStyle.INSTANCE), l);
\r
404 rg.link(addTerminal(rg, -40, 0, 2, PlainLineEndStyle.INSTANCE), l);
\r
406 BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
\r
407 Graphics2D g = image.createGraphics();
\r
408 g.setColor(Color.BLACK);
\r
409 g.setBackground(Color.WHITE);
\r
410 g.clearRect(0, 0, 200, 200);
\r
411 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
\r
412 g.translate(100, 100);
\r
413 new StyledRouteGraphRenderer(new ExampleConnectionStyle()).render(g, rg);
\r
415 //ImageViewer.run(image);
\r
419 public void testRendering2() {
\r
420 RouteGraph rg = new RouteGraph();
\r
421 rg.link(addTerminal(rg, -20, 0, 1), addTerminal(rg, 20, 1, 4));
\r
423 BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
\r
424 Graphics2D g = image.createGraphics();
\r
425 g.setColor(Color.BLACK);
\r
426 g.setBackground(Color.WHITE);
\r
427 g.clearRect(0, 0, 200, 200);
\r
428 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
\r
429 g.translate(100, 100);
\r
430 new StyledRouteGraphRenderer(new ExampleConnectionStyle()).render(g, rg);
\r
432 //ImageViewer.run(image);
\r
436 public void testRendering3() {
\r
437 RouteGraph rg = new RouteGraph();
\r
438 rg.link(addTerminal(rg, 0, -20, 2), addTerminal(rg, 1, 20, 8));
\r
440 BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
\r
441 Graphics2D g = image.createGraphics();
\r
442 g.setColor(Color.BLACK);
\r
443 g.setBackground(Color.WHITE);
\r
444 g.clearRect(0, 0, 200, 200);
\r
445 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
\r
446 g.translate(100, 100);
\r
447 new StyledRouteGraphRenderer(new ExampleConnectionStyle()).render(g, rg);
\r
449 //ImageViewer.run(image);
\r
453 public void testPickingLineHalves() {
\r
454 RouteGraph rg = new RouteGraph();
\r
455 RouteLine l = rg.addLine(false, 0);
\r
456 RouteTerminal t1 = addTerminal(rg, -20, -20, 1);
\r
457 /*RouteTerminal t2 = addTerminal(rg, 20, 20, 1);
\r
458 RouteTerminal t3 = addTerminal(rg, -40, 0, 1);
\r
461 rg.link(addTerminal(rg, 20, 20, 1), l);
\r
462 rg.link(addTerminal(rg, -40, 0, 1), l);
\r
464 Assert.assertEquals(t1, rg.pickLineHalf(-1, -20, 0).getLine().getTerminal());
\r
465 Assert.assertEquals(null, rg.pickLineHalf(-18, -20, 0));
\r
466 Assert.assertEquals(null, rg.pickLineHalf(0, -18, 0));
\r
470 public void testCopy() {
\r
471 RouteGraph rg = new RouteGraph();
\r
472 RouteLine l = rg.addLine(false, 0.0);
\r
473 RouteTerminal a = addTerminal(rg, -20, -20, 1);
\r
474 RouteTerminal b = addTerminal(rg, 20, 20, 4);
\r
477 RouteGraph rgc = rg.copy();
\r
478 rgc.split((RouteLine)rgc.pick(-10, -20), -10.0);
\r
480 Assert.assertArrayEquals(new double[] {20,40,20}, rg.getLineLengths(a), TOLERANCE);
\r
484 public void testConnecting1() {
\r
485 RouteGraph rg = new RouteGraph();
\r
486 RouteTerminal a = addTerminal(rg, -10, 0, 1);
\r
487 RouteTerminal b = addTerminal(rg, 10, 0, 4);
\r
489 rg.connectTerminal(addTerminal(rg, -10, 10, 1), 0.0, 0.0, 0.1);
\r
490 Assert.assertTrue(rg.isTree());
\r
494 public void testConnecting2() {
\r
495 RouteGraph rg = new RouteGraph();
\r
496 RouteTerminal a = addTerminal(rg, -10, -10, 1);
\r
497 RouteTerminal b = addTerminal(rg, 10, 10, 4);
\r
499 rg.connectTerminal(addTerminal(rg, -10, 0, 1), 0.0, 0.0, 0.1);
\r
500 Assert.assertTrue(rg.isTree());
\r
504 public void testDiff1() {
\r
505 RouteGraph rg = new RouteGraph();
\r
506 RouteTerminal a = addTerminal(rg, -10, -10, 1);
\r
508 RouteLine l = rg.addLine(false, 0);
\r
510 RouteTerminal b = addTerminal(rg, 10, 10, 4);
\r
514 RouteGraph rgc = rg.copy();
\r
515 rgc.split(rgc.getLines().iterator().next(), 0);
\r
517 new RouteGraphDelta(rg, rgc).print();
\r
521 public void testSerialize1() throws IOException, ClassNotFoundException {
\r
522 RouteGraph rg = new RouteGraph();
\r
523 RouteTerminal a = addTerminal(rg, -10, -10, 1);
\r
525 RouteLine l = rg.addLine(false, 0);
\r
527 RouteTerminal b = addTerminal(rg, 10, 10, 4);
\r
531 IRouteGraphRenderer renderer = new StyledRouteGraphRenderer(new ExampleConnectionStyle());
\r
533 ByteArrayOutputStream bos = new ByteArrayOutputStream();
\r
534 ObjectOutputStream oos = new ObjectOutputStream(bos);
\r
535 oos.writeObject(rg);
\r
536 oos.writeObject(renderer);
\r
538 ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
\r
539 ObjectInputStream ois = new ObjectInputStream(bis);
\r
540 RouteGraph rgc = (RouteGraph) ois.readObject();
\r
541 //IRouteGraphRenderer rendererc = (IRouteGraphRenderer) ois.readObject();
\r
543 new RouteGraphDelta(rg, rgc).print();
\r