/******************************************************************************* * Copyright (c) 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; import gnu.trove.map.hash.THashMap; import java.io.PrintStream; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import org.simantics.diagram.connection.segments.Segment; public class RouteLine implements RouteNode, Serializable { private static final long serialVersionUID = -7256429294500809465L; Object data; boolean isHorizontal; double position; boolean hidden; ArrayList points = new ArrayList(4); RouteLine nextTransient; RouteTerminal terminal; RouteLine(boolean isHorizontal, double position) { this.isHorizontal = isHorizontal; this.position = position; } @Override public void setData(Object data) { this.data = data; } @Override public Object getData() { return data; } public boolean isHorizontal() { return isHorizontal; } public boolean isHidden() { return hidden; } public double getPosition() { return position; } public List getPoints() { if(RouteGraph.RETURN_UNMODIFIABLE_COLLECTIONS) return Collections.unmodifiableList(points); else return points; } void addPoint(RoutePoint link) { points.add(link); } void remove() { for(RoutePoint point : points) point.removeFromOther(this); } void setPointPositions() { if(isHorizontal) { for(RoutePoint point : points) point.y = position; } else { for(RoutePoint point : points) point.x = position; } } void sortPoints() { Collections.sort(points, isHorizontal ? RoutePoint.X_COMPARATOR : RoutePoint.Y_COMPARATOR); } public boolean isNear(double x2, double y2, double tolerance) { return isHorizontal ? Math.abs(y2-position) <= tolerance && points.get(0).x <= x2 && x2 <= points.get(points.size()-1).x : Math.abs(x2-position) <= tolerance && points.get(0).y <= y2 && y2 <= points.get(points.size()-1).y; } public void print(PrintStream out) { if(isHorizontal) out.print(" HOR"); else out.print(" VER"); for(RoutePoint point : points) { out.print(" ("+point.x+","+point.y+")"); } out.print(" (data=" + data + ")"); out.println(); } void setLocation(double x, double y) { if(isHorizontal) position = y; else position = x; } public double getLength() { if(isHorizontal) return points.get(points.size()-1).x - points.get(0).x; else return points.get(points.size()-1).y - points.get(0).y; } boolean isConnectedToPeristentLine() { for(RoutePoint point : points) if(point instanceof RouteLink) { RouteLink link = (RouteLink)point; if(link.a == this) { if(!link.b.isTransient()) return true; } else { if(!link.a.isTransient()) return true; } } return false; } public RoutePoint getBegin() { return points.get(0); } public RoutePoint getEnd() { return points.get(points.size()-1); } public boolean isTransient() { return terminal != null; } RouteLine copy(THashMap map) { RouteLine copy = (RouteLine)map.get(this); if(copy == null) { copy = new RouteLine(isHorizontal, position); map.put(this, copy); copy.data = data; copy.nextTransient = nextTransient == null ? null : nextTransient.copy(map); copy.terminal = terminal == null ? null : terminal.copy(map); for(RoutePoint point : points) copy.points.add(point.copy(map)); } return copy; } public Collection getPersistentNeighbors() { ArrayList lines = new ArrayList(); for(RoutePoint point : points) if(point instanceof RouteLink) { RouteLink link = (RouteLink)point; RouteLine line = link.getOther(this); if(!line.isTransient()) lines.add(line); } return lines; } public RouteTerminal getTerminal() { return terminal; } public boolean beginsWithTerminal() { RoutePoint begin = points.get(0); if(begin == terminal) return true; else if(begin instanceof RouteLink) { RouteLink link = (RouteLink)begin; if(link.a == this) return link.b.hasTerminal(link, terminal); else return link.a.hasTerminal(link, terminal); } else return false; } private boolean hasTerminal(RouteLink oldLink, RouteTerminal terminal) { RoutePoint begin = points.get(0); RoutePoint end = points.get(1); if(begin == terminal || end == terminal) return true; if(begin instanceof RouteLink && begin != oldLink) { RouteLink link = (RouteLink)begin; if(link.a == this) return link.b.hasTerminal(link, terminal); else return link.a.hasTerminal(link, terminal); } else if(end instanceof RouteLink && end != oldLink) { RouteLink link = (RouteLink)end; if(link.a == this) return link.b.hasTerminal(link, terminal); else return link.a.hasTerminal(link, terminal); } else return false; } public boolean isDegenerated() { if(points.size() <= 1) return true; if(isHorizontal) return points.get(0).x == points.get(points.size()-1).x; else return points.get(0).y == points.get(points.size()-1).y; } public void collectSegments(ArrayList segments) { RoutePoint p0 = points.get(0); for(int i=1;i