1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\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.g2d.routing.algorithm2;
\r
14 import java.awt.geom.AffineTransform;
\r
15 import java.awt.geom.Path2D;
\r
16 import java.awt.geom.PathIterator;
\r
17 import java.awt.geom.Rectangle2D;
\r
18 import java.util.Arrays;
\r
20 import org.simantics.g2d.routing.Constants;
\r
21 import org.simantics.g2d.routing.IGraphModel;
\r
22 import org.simantics.g2d.routing.IRouter;
\r
23 import org.simantics.g2d.routing.Terminal;
\r
25 public class Router2 implements IRouter {
\r
27 static int getSomeDirection(int mask) {
\r
31 while((mask & 1) == 0) {
\r
39 public void update(IGraphModel model) {
\r
40 LocalRouter localRouter = new LocalRouter(false);
\r
41 for(Object c : model.getConnections()) {
\r
42 Terminal begin = model.getBeginTerminal(c);
\r
43 Terminal end = model.getEndTerminal(c);
\r
44 double[] points = model.getRoutePoints(c);
\r
47 if(points.length < 2)
\r
49 begin = new Terminal(points[0], points[1], 0x1, Terminal.ZEROS,
\r
50 new Rectangle2D.Double(points[0], points[1], 0.0, 0.0));
\r
51 points = Arrays.copyOfRange(points, 2, points.length);
\r
54 if(points.length < 2)
\r
56 end = new Terminal(points[points.length-2], points[points.length-1], 0xf, Terminal.ZEROS,
\r
57 new Rectangle2D.Double(points[points.length-2], points[points.length-1], 0.0, 0.0));
\r
58 points = Arrays.copyOf(points, points.length-2);
\r
61 double bestLength = Double.POSITIVE_INFINITY;
\r
62 Path2D bestPath = null;
\r
64 for(int sDir : Constants.POSSIBLE_DIRECTIONS[begin.directions])
\r
65 for(int tDir : Constants.POSSIBLE_DIRECTIONS[end.directions]) {
\r
66 localRouter.sx = begin.x;
\r
67 localRouter.sy = begin.y;
\r
68 localRouter.aMinX = begin.parentObstacle.getMinX();
\r
69 localRouter.aMinY = begin.parentObstacle.getMinY();
\r
70 localRouter.aMaxX = begin.parentObstacle.getMaxX();
\r
71 localRouter.aMaxY = begin.parentObstacle.getMaxY();
\r
72 localRouter.sourceDirection = sDir;
\r
74 localRouter.tx = end.x;
\r
75 localRouter.ty = end.y;
\r
76 localRouter.bMinX = end.parentObstacle.getMinX();
\r
77 localRouter.bMinY = end.parentObstacle.getMinY();
\r
78 localRouter.bMaxX = end.parentObstacle.getMaxX();
\r
79 localRouter.bMaxY = end.parentObstacle.getMaxY();
\r
80 localRouter.targetDirection = tDir;
\r
82 localRouter.route();
\r
84 double length = pathLength(localRouter.path);
\r
85 if(length < bestLength) {
\r
86 bestLength = length;
\r
87 bestPath = localRouter.path;
\r
91 if(bestPath != null)
\r
92 model.setPath(c, bestPath);
\r
96 final static AffineTransform IDENTITY = new AffineTransform();
\r
98 static double pathLength(Path2D path) {
\r
99 double length = 0.0;
\r
100 PathIterator it = path.getPathIterator(IDENTITY);
\r
101 double[] temp = new double[6];
\r
102 double x=0.0, y=0.0;
\r
103 double bendCount = 0.0;
\r
104 while(!it.isDone()) {
\r
106 if(it.currentSegment(temp) != PathIterator.SEG_MOVETO)
\r
107 length += Math.abs(x - temp[0] + y - temp[1]);
\r
112 return length * (6.0 + bendCount);
\r