All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sourceforge.plantuml.graph2.Plan Maven / Gradle / Ivy

Go to download

PlantUML is a component that allows to quickly write : * sequence diagram, * use case diagram, * class diagram, * activity diagram, * component diagram, * state diagram * object diagram

There is a newer version: 8059
Show newest version
/* ========================================================================
 * PlantUML : a free UML diagram generator
 * ========================================================================
 *
 * (C) Copyright 2009-2013, Arnaud Roques
 *
 * Project Info:  http://plantuml.sourceforge.net
 * 
 * This file is part of PlantUML.
 *
 * PlantUML is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * PlantUML distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
 * License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
 * USA.
 *
 * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
 * in the United States and other countries.]
 *
 * Original Author:  Arnaud Roques
 * 
 * Revision $Revision: 9786 $
 *
 */
package net.sourceforge.plantuml.graph2;

import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import net.sourceforge.plantuml.Log;
import net.sourceforge.plantuml.graph2.Dijkstra.Vertex;

public class Plan {

	private final Map points = new LinkedHashMap();
	private final Collection lines = new ArrayList();

	public void addPoint2D(Point2D.Double point) {
		if (points.containsKey(point)) {
			throw new IllegalArgumentException();
		}
		points.put(point, new Singularity2(point));
	}

	public void debugPrint() {
		Log.println("PLAN PRINT");
		for (Singularity2 s : points.values()) {
			Log.println("s="+s);
		}
		for (Line2D.Double l : lines) {
			Log.println(GeomUtils.toString(l));
		}
	}

	public void createLink(Point2D p1, Point2D p2) {
		final Singularity2 s1 = points.get(p1);
		final Singularity2 s2 = points.get(p2);
		if (s1 == null || s2 == null) {
			throw new IllegalArgumentException();
		}
		final Line2D.Double line = new Line2D.Double(p1, p2);

		s1.addLineSegment(line);
		s2.addLineSegment(line);
		lines.add(line);
	}

	Singularity2 getSingularity(Point2D pt) {
		final Singularity2 result = points.get(pt);
		if (result == null) {
			throw new IllegalArgumentException();
		}
		return result;
	}

	List getShortestPathToInternal(Point2D start, Point2D end) {
		final Dijkstra dijkstra = new Dijkstra();
		if (points.containsKey(start) == false || points.containsKey(end) == false) {
			throw new IllegalArgumentException();
		}
		final Vertex vStart = dijkstra.addVertex(start);
		final Vertex vEnd = dijkstra.addVertex(end);
		final Map vertexes = new LinkedHashMap();
		for (Singularity2 s : points.values()) {
			for (Neighborhood2 n : s.getNeighborhoods()) {
				final Vertex v = dijkstra.addVertex(n);
				vertexes.put(n, v);
				if (n.getCenter().equals(start)) {
					vStart.addAdjacencies(v, 0.01);
				}
				if (n.getCenter().equals(end)) {
					v.addAdjacencies(vEnd, 0.01);
				}
			}
		}

		for (Vertex v1 : vertexes.values()) {
			for (Vertex v2 : vertexes.values()) {
				final Neighborhood2 n1 = (Neighborhood2) v1.getData();
				final Neighborhood2 n2 = (Neighborhood2) v2.getData();
				if (n1.getCenter().equals(n2.getCenter())) {
					continue;
				}
				final Line2D.Double line = new Line2D.Double(n1.getCenter(), n2.getCenter());
				if (isStrictCrossing(line)) {
					continue;
				}
				if (n1.isConnectable(n2) == false) {
					continue;
				}
				final double dist = n1.getCenter().distance(n2.getCenter());
				v1.addAdjacencies(v2, dist);
				v2.addAdjacencies(v1, dist);
				// Log.println("=(" + n1 + ") (" + n2 + ") " + dist);
			}
		}

		final List list = dijkstra.getShortestPathTo(vStart, vEnd);
		if (list.size() < 2) {
			throw new IllegalStateException("list=" + list);
		}
		final List result = new ArrayList();
		for (Vertex v : list.subList(1, list.size() - 1)) {
			result.add((Neighborhood2) v.getData());
		}
		return result;
	}

	public List getIntermediatePoints(Point2D start, Point2D end) {
		// Log.println("start=" + start + " end=" + end);
		final List result = new ArrayList();
		final List list = getShortestPathToInternal(start, end);
		// Log.println("Neighborhood2 = " + list);
		for (int i = 1; i < list.size() - 1; i++) {
			final Neighborhood2 n = list.get(i);
			final Point2D.Double before = list.get(i - 1).getCenter();
			final Point2D.Double after = list.get(i + 1).getCenter();
			// Log.println("before="+before);
			// Log.println("after="+after);
			// Log.println("n.getCenter()="+n.getCenter());
			// Log.println("getMindist(n.getCenter())="+getMindist(n.getCenter()));
			final Point2D.Double pointInNeighborhood = n.getPointInNeighborhood(getMindist(n.getCenter()) / 2, before,
					after);
			// Log.println("pointInNeighborhood="+pointInNeighborhood);
			result.add(pointInNeighborhood);
		}
		return result;

	}

	private boolean isStrictCrossing(Line2D.Double line) {
		for (Line2D.Double l : lines) {
			if (intersectsLineStrict(l, line)) {
				return true;
			}
		}
		return false;
	}

	public static boolean intersectsLineStrict(Line2D.Double l1, Line2D.Double l2) {
		assert intersectsLineStrictInternal(l1, l2) == intersectsLineStrictInternal(l2, l1);
		assert intersectsLineStrictInternal(l1, l2) == intersectsLineStrictInternal(inverse(l1), l2);
		assert intersectsLineStrictInternal(l1, l2) == intersectsLineStrictInternal(l1, inverse(l2));
		assert intersectsLineStrictInternal(l1, l2) == intersectsLineStrictInternal(inverse(l1), inverse(l2));
		return intersectsLineStrictInternal(l1, l2);
	}

	private static Line2D.Double inverse(Line2D.Double line) {
		return new Line2D.Double(line.getP2(), line.getP1());
	}

	private static boolean intersectsLineStrictInternal(Line2D.Double l1, Line2D.Double l2) {
		if (l1.intersectsLine(l2) == false) {
			return false;
		}
		assert l1.intersectsLine(l2);

		Point2D.Double l1a = (Point2D.Double) l1.getP1();
		Point2D.Double l1b = (Point2D.Double) l1.getP2();
		Point2D.Double l2a = (Point2D.Double) l2.getP1();
		Point2D.Double l2b = (Point2D.Double) l2.getP2();

		if (l1a.equals(l2a) == false && l1a.equals(l2b) == false && l1b.equals(l2a) == false
				&& l1b.equals(l2b) == false) {
			return true;
		}

		if (l1a.equals(l2b)) {
			final Point2D.Double tmp = l2a;
			l2a = l2b;
			l2b = tmp;
		} else if (l2a.equals(l1b)) {
			final Point2D.Double tmp = l1a;
			l1a = l1b;
			l1b = tmp;
		} else if (l1b.equals(l2b)) {
			Point2D.Double tmp = l2a;
			l2a = l2b;
			l2b = tmp;
			tmp = l1a;
			l1a = l1b;
			l1b = tmp;
		}

		assert l1a.equals(l2a);

		return false;

	}

	final double getMindist(Point2D.Double pt) {
		double result = Double.MAX_VALUE;
		for (Point2D p : points.keySet()) {
			if (pt.equals(p)) {
				continue;
			}
			final double v = p.distance(pt);
			if (v < 1E-4) {
				throw new IllegalStateException();
			}
			result = Math.min(result, v);
		}
		for (Line2D line : lines) {
			if (line.getP1().equals(pt) || line.getP2().equals(pt)) {
				continue;
			}
			final double v = line.ptSegDist(pt);
			if (result < 1E-4) {
				throw new IllegalStateException("pt=" + pt + " line=" + GeomUtils.toString(line));
			}
			result = Math.min(result, v);
		}
		if (result == 0) {
			throw new IllegalStateException();
		}
		// Log.println("getMindist=" + result);
		return result;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy