1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
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.g2d.routing.algorithm2;
14 import java.awt.geom.Path2D;
16 import org.simantics.g2d.routing.Constants;
18 public class LocalRouter {
20 static final double CORNER_SIZE = 1.0;
45 public LocalRouter(boolean roundCorners) {
46 this.roundCorners = roundCorners;
50 * Case where both source and target connection directions
54 if(bMinX >= aMaxX || tx >= 0 && !(bMaxY < aMinY || aMaxY < bMinY)) {
62 double mx = 0.5 * (aMaxX + bMinX);
67 ; // Just a straight line
86 * If the elements are separated in Y-direction,
87 * route between the elements (this is always the shortest path).
89 if(bMaxY < aMinY) my = 0.5 * (aMinY + bMaxY);
90 else if(aMaxY < bMinY) my = 0.5 * (aMaxY + bMinY);
93 * /------------------------\
98 * | |______| |______| |
100 * \------------------------/
117 * We may choose either lower or upper path.
119 double upperX0 = bMinX;
120 double upperX1 = aMaxX;
121 double lowerX0 = bMinX;
122 double lowerX1 = aMaxX;
123 double upperY = Math.min(aMinY, bMinY);
124 double lowerY = Math.max(aMaxY, bMaxY);
127 if(ty < 0.5 * (aMinY + aMaxY))
134 if(ty < 0.5 * (aMinY + aMaxY))
140 double upperLength = upperX1 - upperY + (upperX1 - upperX0) + (ty - upperY) + (tx - upperX0);
141 double lowerLength = lowerX1 + lowerY + (lowerX1 - lowerX0) + (lowerY - ty) + (tx - lowerX0);
143 if(upperLength < lowerLength) {
163 double fx = Math.max(aMaxX, bMaxX);
164 double mx = 0.5 * (aMaxX + bMinX);
165 if(bMinY >= 0.0 || bMaxY <= 0.0 || mx < 0.0) {
172 * | |-------------------/
184 * | |----+ |______| |
186 * |______| \-------------/
188 * We may choose either upper or lower path
189 * by the path length.
192 Math.abs(bMinY) + Math.abs(ty - bMinY)
193 < Math.abs(bMaxY) + Math.abs(ty - bMaxY)
202 double fx = Math.max(aMaxX, bMaxX);
203 double mx = 0.5 * (aMinX + bMaxX);
205 if(ty <= aMinY || ty >= aMaxY || (tx >= mx && ty >= aMinY && ty <= aMaxY)) {
212 * | |<------------------/
224 * | |<---+ |______| |
226 * |______| \-------------/
228 * We may choose either upper or lower path
229 * by the path length.
232 Math.abs(aMinY) + Math.abs(ty - aMinY)
233 < Math.abs(aMaxY) + Math.abs(ty - aMaxY)
243 if(tx > 0.0 && (bMinY >= 0.0 || (ty > 0.0 && bMinX <= aMaxX)))
245 else if(bMinX > aMaxX) {
246 double mx = 0.5 * (aMaxX + bMinX);
253 double my = 0.5 * (aMaxY + bMinY);
254 if(my < aMaxY && (tx < aMinX || ty < aMinY)) {
255 my = Math.min(aMinY, bMinY);
265 double xx, xy, yx, yy;
266 void point(double x, double y) {
268 continuePath(x*xx + y*yx + sx, x*xy + y*yy + sy);
270 path.lineTo(x*xx + y*yx + sx, x*xy + y*yy + sy);
274 double prevX, prevY, curX, curY, nextX, nextY;
276 void beginPath(double x, double y) {
283 static double dd(double d) {
284 if(Math.abs(d) < CORNER_SIZE*2.0)
287 return Math.signum(d)*CORNER_SIZE;
290 void continuePath(double x, double y) {
301 double prevDeltaX = dd(prevX - curX);
302 double prevDeltaY = dd(prevY - curY);
303 double nextDeltaX = dd(nextX - curX);
304 double nextDeltaY = dd(nextY - curY);
307 path.lineTo(curX+prevDeltaX, curY+prevDeltaY);
310 curX+nextDeltaX, curY+nextDeltaY);
311 //path.lineTo(curX+nextDeltaX, curY+nextDeltaY);
313 //path.lineTo(curX, curY);
318 path.lineTo(nextX, nextY);
349 if(targetDirection < 0)
350 targetDirection += 4;
370 targetDirection = (targetDirection + 2) % 4;
374 * Puts source terminal to origo and rotates the situation
375 * so that the connection leaves to east. Finally, the
376 * case where target direction is to south is eliminated
377 * by optionally flipping the situation.
379 void canonicalize() {
392 while(sourceDirection > 0)
395 if(targetDirection == Constants.SOUTH)
399 public void route() {
400 //System.out.println("route");
401 //System.out.println(sourceDirection + " " + targetDirection);
403 path = new Path2D.Double();
409 if(bMinX < sx && sx < bMaxX && bMinY < sy && sy < bMaxY)
410 targetDirection = (targetDirection+2)&3;
411 if(aMinX < tx && tx < aMaxX && aMinY < ty && ty < aMaxY)
412 sourceDirection = (sourceDirection+2)&3;
414 // // Vertical and horizontal cases
415 // if(Math.abs(sx - tx) < 1e-5 || Math.abs(sy - ty) < 1e-5) {
416 // path.lineTo(tx, ty);
424 // Vertical and horizontal cases
425 // TODO Removed this seemingly incorrect code (they were already disabled in roundCorners case
426 /*if(Math.abs(sx - tx) < 1e-5 || Math.abs(sy - ty) < 1e-5) {
434 switch(targetDirection) {
435 case Constants.EAST: routeWest(); break;
436 case Constants.WEST: routeEast(); break;
437 case Constants.NORTH: routeSouth(); break;
444 //System.out.println(sourceDirection + " " + targetDirection);