org.stathissideris.ascii2image.graphics.ShapeEdge Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of plantuml-asl Show documentation
Show all versions of plantuml-asl Show documentation
PlantUML is a component that allows to quickly write diagrams from text.
The 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 Apache Software License.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 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 APACHE license.
*
* The generated images can then be used without any reference to the APACHE 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;
}
}