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