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

org.stathissideris.ascii2image.graphics.ShapeEdge Maven / Gradle / Ivy

There is a newer version: 1.2024.8
Show newest version
// THIS FILE HAS BEEN GENERATED BY A PREPROCESSOR.
/* +=======================================================================
 * |
 * |      PlantUML : a free UML diagram generator
 * |
 * +=======================================================================
 *
 * (C) Copyright 2009-2024, Arnaud Roques
 *
 * Project Info:  https://plantuml.com
 *
 * If you like this project or if you find it useful, you can support us at:
 *
 * https://plantuml.com/patreon (only 1$ per month!)
 * https://plantuml.com/liberapay (only 1€ per month!)
 * https://plantuml.com/paypal
 *
 *
 * PlantUML is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser 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 Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library.  If not, see .
 *
 * PlantUML can occasionally display sponsored or advertising messages. Those
 * messages are usually generated on welcome or error images and never on
 * functional diagrams.
 * See https://plantuml.com/professional if you want to remove them
 *
 * Images (whatever their format : PNG, SVG, EPS...) generated by running PlantUML
 * are owned by the author of their corresponding sources code (that is, their
 * textual description in PlantUML language). Those images are not covered by
 * this LGPL license.
 *
 * The generated images can then be used without any reference to the LGPL license.
 * It is not even necessary to stipulate that they have been generated with PlantUML,
 * although this will be appreciated by the PlantUML team.
 *
 * There is an exception : if the textual description in PlantUML language is also covered
 * by any license, then the generated images are logically covered
 * by the very same license.
 *
 * This is the IGY distribution (Install GraphViz by Yourself).
 * You have to install GraphViz and to setup the GRAPHVIZ_DOT environment variable
 * (see https://plantuml.com/graphviz-dot )
 *
 * Icons provided by OpenIconic :  https://useiconic.com/open
 * Archimate sprites provided by Archi :  http://www.archimatetool.com
 * Stdlib AWS provided by https://github.com/milo-minderbinder/AWS-PlantUML
 * Stdlib Icons provided https://github.com/tupadr3/plantuml-icon-font-sprites
 * ASCIIMathML (c) Peter Jipsen http://www.chapman.edu/~jipsen
 * ASCIIMathML (c) David Lippman http://www.pierce.ctc.edu/dlippman
 * CafeUndZopfli ported by Eugene Klyuchnikov https://github.com/eustas/CafeUndZopfli
 * Brotli (c) by the Brotli Authors https://github.com/google/brotli
 * Themes (c) by Brett Schwarz https://github.com/bschwarz/puml-themes
 * Twemoji (c) by Twitter at https://twemoji.twitter.com/
 *
 */
package org.stathissideris.ascii2image.graphics;

import java.awt.geom.GeneralPath;

/**
 * 
 * @author Efstathios Sideris
 */
public class ShapeEdge {
	
	private static final boolean DEBUG = false;
	
	private static final int TYPE_HORIZONTAL = 0;
	private static final int TYPE_VERTICAL = 1;
	private static final int TYPE_SLOPED = 2;
	
	
	private DiagramShape owner;
	private ShapePoint startPoint;
	private ShapePoint endPoint;
	
	public ShapeEdge(ShapePoint start, ShapePoint end, DiagramShape owner){
		this.startPoint = start;
		this.endPoint = end;
		this.owner = owner;
	}
	
	public ShapeEdge(ShapeEdge other){
		this(
			new ShapePoint(other.startPoint),
			new ShapePoint(other.endPoint),
			other.owner
		);
	}
	
	private float getDistanceFromOrigin() {
		int type = this.getType();
		if(type == TYPE_SLOPED)
			throw new RuntimeException("Cannot calculate distance of sloped edge from origin");
		if(type == TYPE_HORIZONTAL)
			return startPoint.y;
		return startPoint.x; //vertical
	}

	//TODO: moveInwardsBy() not implemented
	public void moveInwardsBy(float offset){
		int type = this.getType();
		if(type == TYPE_SLOPED)
			throw new RuntimeException("Cannot move a sloped egde inwards: "+this);
		
		float xOffset = 0;
		float yOffset = 0;
		
		ShapePoint middle = getMiddle();
		GeneralPath path = owner.makeIntoPath();
		if(type == TYPE_HORIZONTAL){
			xOffset = 0;
			ShapePoint up = new ShapePoint(middle.x, middle.y - 0.05f);
			ShapePoint down = new ShapePoint(middle.x, middle.y + 0.05f);
			if(path.contains(up)) yOffset = -offset;
			else if(path.contains(down)) yOffset = offset;
		} else if(type == TYPE_VERTICAL){
			yOffset = 0;
			ShapePoint left = new ShapePoint(middle.x - 0.05f, middle.y);
			ShapePoint right = new ShapePoint(middle.x + 0.05f, middle.y);
			if(path.contains(left)) xOffset = -offset;
			else if(path.contains(right)) xOffset = offset;
		}
		if(DEBUG) System.out.println("Moved edge "+this+" by "+xOffset+", "+yOffset);
		translate(xOffset, yOffset);
	}

	public void translate(float dx, float dy){
		startPoint.x += dx;
		startPoint.y += dy;
		endPoint.x += dx;
		endPoint.y += dy;
	}

	public ShapePoint getMiddle(){
		return new ShapePoint(
			(startPoint.x + endPoint.x) / 2,
			(startPoint.y + endPoint.y) / 2
		);
	}

	/**
	 * Returns the type of the edge
	 * (TYPE_HORIZONTAL, TYPE_VERTICAL, TYPE_SLOPED).
	 * 
	 * @return
	 */
	private int getType(){
		if(isVertical()) return TYPE_VERTICAL;
		if(isHorizontal()) return TYPE_HORIZONTAL;
		return TYPE_SLOPED;
	}

	/**
	 * @return
	 */
	public ShapePoint getEndPoint() {
		return endPoint;
	}

	/**
	 * @return
	 */
	public ShapePoint getStartPoint() {
		return startPoint;
	}

	/**
	 * @param point
	 */
	public void setEndPoint(ShapePoint point) {
		endPoint = point;
	}

	/**
	 * @param point
	 */
	public void setStartPoint(ShapePoint point) {
		startPoint = point;
	}

	/**
	 * @return
	 */
	public DiagramShape getOwner() {
		return owner;
	}

	/**
	 * @param shape
	 */
	public void setOwner(DiagramShape shape) {
		owner = shape;
	}
	
	public boolean equals(Object object){
		if(!(object instanceof ShapeEdge)) return false;
		ShapeEdge edge = (ShapeEdge) object;
		if(startPoint.equals(edge.getStartPoint())
			&& endPoint.equals(edge.getEndPoint())) return true;
		if(startPoint.equals(edge.getEndPoint())
			&& endPoint.equals(edge.getStartPoint())) return true;
		return false;
	}

	public boolean touchesWith(ShapeEdge other){
		if(this.equals(other)) return true;
		
		if(this.isHorizontal() && other.isVertical()) return false;
		if(other.isHorizontal() && this.isVertical()) return false;
		
		if(this.getDistanceFromOrigin() != other.getDistanceFromOrigin()) return false;

		//covering this corner case (should produce false):
		//      ---------
		//              ---------
		
		ShapeEdge first = new ShapeEdge(this);
		ShapeEdge second = new ShapeEdge(other);
		
		if(first.isVertical()) {
			first.changeAxis();
			second.changeAxis();
		}
		
		first.fixDirection();
		second.fixDirection();
		
		if(first.startPoint.x > second.startPoint.x) {
			ShapeEdge temp = first;
			first = second;
			second = temp;
		}
		
		if(first.endPoint.equals(second.startPoint)) return false;
		
		// case 1:
		// ----------
		//      -----------
		
		// case 2:
		//         ------
		// -----------------
		
		if(this.startPoint.isWithinEdge(other) || this.endPoint.isWithinEdge(other)) return true;
		if(other.startPoint.isWithinEdge(this) || other.endPoint.isWithinEdge(this)) return true;	
		
		
		return false;
	}
	
	private void changeAxis(){
		ShapePoint temp = new ShapePoint(startPoint);
		startPoint = new ShapePoint(endPoint.y, endPoint.x);
		endPoint = new ShapePoint(temp.y, temp.x);
	}
	
	/**
	 * if horizontal flips start and end points so that start is left of end
	 * if verical flips start and end points so that start is over of end
	 *
	 */
	private void fixDirection(){
		if(isHorizontal()) {
			if(startPoint.x > endPoint.x) flipDirection();
		} else if(isVertical()) {
			if(startPoint.y > endPoint.y) flipDirection();
		} else {
			throw new RuntimeException("Cannot fix direction of sloped egde");
		}
	}
	
	private void flipDirection(){
		ShapePoint temp = startPoint;
		startPoint = endPoint;
		endPoint = temp;
	}
	
	public boolean isHorizontal(){
		if(startPoint.y == endPoint.y) return true;
		return false;
	}
	
	public boolean isVertical(){
		if(startPoint.x == endPoint.x) return true;
		return false;
	}

	public String toString(){
		return startPoint+" -> "+endPoint;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy