2013-12-10 19:36:50 +00:00
|
|
|
/* ========================================================================
|
|
|
|
* PlantUML : a free UML diagram generator
|
|
|
|
* ========================================================================
|
|
|
|
*
|
2023-02-22 18:43:48 +00:00
|
|
|
* (C) Copyright 2009-2024, Arnaud Roques
|
2013-12-10 19:36:50 +00:00
|
|
|
*
|
2023-02-22 18:43:48 +00:00
|
|
|
* Project Info: https://plantuml.com
|
2013-12-10 19:36:50 +00:00
|
|
|
*
|
2017-03-15 19:13:31 +00:00
|
|
|
* If you like this project or if you find it useful, you can support us at:
|
|
|
|
*
|
2023-02-22 18:43:48 +00:00
|
|
|
* https://plantuml.com/patreon (only 1$ per month!)
|
|
|
|
* https://plantuml.com/paypal
|
2017-03-15 19:13:31 +00:00
|
|
|
*
|
2013-12-10 19:36:50 +00:00
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Original Author: Arnaud Roques
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
2023-02-02 17:59:43 +00:00
|
|
|
package net.sourceforge.plantuml.klimt.geom;
|
2013-12-10 19:36:50 +00:00
|
|
|
|
2023-02-02 17:59:43 +00:00
|
|
|
import net.sourceforge.plantuml.klimt.UTranslate;
|
2023-03-15 18:03:47 +00:00
|
|
|
import net.sourceforge.plantuml.utils.MathUtils;
|
2013-12-10 19:36:50 +00:00
|
|
|
|
2023-02-26 18:51:17 +00:00
|
|
|
public class RectangleArea {
|
2013-12-10 19:36:50 +00:00
|
|
|
|
|
|
|
private final double minX;
|
|
|
|
private final double minY;
|
|
|
|
private final double maxX;
|
|
|
|
private final double maxY;
|
|
|
|
|
2023-02-26 18:51:17 +00:00
|
|
|
public RectangleArea(double minX, double minY, double maxX, double maxY) {
|
2013-12-10 19:36:50 +00:00
|
|
|
this.minX = minX;
|
|
|
|
this.minY = minY;
|
|
|
|
this.maxX = maxX;
|
|
|
|
this.maxY = maxY;
|
|
|
|
}
|
|
|
|
|
2023-03-15 18:03:47 +00:00
|
|
|
public static RectangleArea build(XPoint2D pt1, XPoint2D pt2) {
|
|
|
|
return new RectangleArea(MathUtils.min(pt1.x, pt2.x), MathUtils.min(pt1.y, pt2.y), MathUtils.max(pt1.x, pt2.x),
|
|
|
|
MathUtils.max(pt1.y, pt2.y));
|
2022-09-14 18:12:03 +00:00
|
|
|
}
|
|
|
|
|
2023-02-26 18:51:17 +00:00
|
|
|
public RectangleArea move(double deltaX, double deltaY) {
|
|
|
|
return new RectangleArea(minX + deltaX, minY + deltaY, maxX + deltaX, maxY + deltaY);
|
2022-09-14 18:12:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public double getWidth() {
|
|
|
|
return maxX - minX;
|
|
|
|
}
|
|
|
|
|
|
|
|
public double getHeight() {
|
|
|
|
return maxY - minY;
|
|
|
|
}
|
|
|
|
|
2013-12-10 19:36:50 +00:00
|
|
|
public boolean contains(double x, double y) {
|
|
|
|
return x >= minX && x < maxX && y >= minY && y < maxY;
|
|
|
|
}
|
|
|
|
|
2023-02-26 18:51:17 +00:00
|
|
|
public RectangleArea merge(RectangleArea other) {
|
|
|
|
return new RectangleArea(Math.min(this.minX, other.minX), Math.min(this.minY, other.minY),
|
2022-09-12 20:08:34 +00:00
|
|
|
Math.max(this.maxX, other.maxX), Math.max(this.maxY, other.maxY));
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
2023-02-26 18:51:17 +00:00
|
|
|
public RectangleArea merge(XPoint2D point) {
|
2013-12-10 19:36:50 +00:00
|
|
|
final double x = point.getX();
|
|
|
|
final double y = point.getY();
|
2023-02-26 18:51:17 +00:00
|
|
|
return new RectangleArea(Math.min(this.minX, x), Math.min(this.minY, y), Math.max(this.maxX, x),
|
2022-09-12 20:08:34 +00:00
|
|
|
Math.max(this.maxY, y));
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean contains(XPoint2D p) {
|
|
|
|
return contains(p.getX(), p.getY());
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public String toString() {
|
|
|
|
return "minX=" + minX + " maxX=" + maxX + " minY=" + minY + " maxY=" + maxY;
|
|
|
|
}
|
|
|
|
|
|
|
|
public final double getMinX() {
|
|
|
|
return minX;
|
|
|
|
}
|
|
|
|
|
|
|
|
public final double getMinY() {
|
|
|
|
return minY;
|
|
|
|
}
|
|
|
|
|
|
|
|
public final double getMaxX() {
|
|
|
|
return maxX;
|
|
|
|
}
|
|
|
|
|
|
|
|
public final double getMaxY() {
|
|
|
|
return maxY;
|
|
|
|
}
|
|
|
|
|
2022-09-14 18:12:03 +00:00
|
|
|
public PointDirected getIntersection(XCubicCurve2D bez) {
|
2022-09-12 20:08:34 +00:00
|
|
|
if (contains(bez.x1, bez.y1) == contains(bez.x2, bez.y2))
|
2013-12-10 19:36:50 +00:00
|
|
|
return null;
|
2022-09-12 20:08:34 +00:00
|
|
|
|
2013-12-10 19:36:50 +00:00
|
|
|
final double dist = bez.getP1().distance(bez.getP2());
|
|
|
|
if (dist < 2) {
|
|
|
|
final double angle = BezierUtils.getStartingAngle(bez);
|
|
|
|
return new PointDirected(bez.getP1(), angle);
|
|
|
|
}
|
2023-03-12 11:15:51 +00:00
|
|
|
final XCubicCurve2D left = XCubicCurve2D.none();
|
|
|
|
final XCubicCurve2D right = XCubicCurve2D.none();
|
2013-12-10 19:36:50 +00:00
|
|
|
bez.subdivide(left, right);
|
|
|
|
final PointDirected int1 = getIntersection(left);
|
2022-09-12 20:08:34 +00:00
|
|
|
if (int1 != null)
|
2013-12-10 19:36:50 +00:00
|
|
|
return int1;
|
2022-09-12 20:08:34 +00:00
|
|
|
|
2013-12-10 19:36:50 +00:00
|
|
|
final PointDirected int2 = getIntersection(right);
|
2022-09-12 20:08:34 +00:00
|
|
|
if (int2 != null)
|
2013-12-10 19:36:50 +00:00
|
|
|
return int2;
|
2022-09-12 20:08:34 +00:00
|
|
|
|
2013-12-10 19:36:50 +00:00
|
|
|
throw new IllegalStateException();
|
|
|
|
}
|
|
|
|
|
2022-09-12 20:08:34 +00:00
|
|
|
public XPoint2D getPointCenter() {
|
|
|
|
return new XPoint2D((minX + maxX) / 2, (minY + maxY) / 2);
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
2023-02-26 18:51:17 +00:00
|
|
|
public RectangleArea withMinX(double d) {
|
|
|
|
return new RectangleArea(d, minY, maxX, maxY);
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
2023-02-26 18:51:17 +00:00
|
|
|
public RectangleArea withMaxX(double d) {
|
|
|
|
return new RectangleArea(minX, minY, d, maxY);
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
2023-02-26 18:51:17 +00:00
|
|
|
public RectangleArea addMaxX(double d) {
|
|
|
|
return new RectangleArea(minX, minY, maxX + d, maxY);
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
2023-02-26 18:51:17 +00:00
|
|
|
public RectangleArea addMaxY(double d) {
|
|
|
|
return new RectangleArea(minX, minY, maxX, maxY + d);
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
2023-02-26 18:51:17 +00:00
|
|
|
public RectangleArea addMinX(double d) {
|
|
|
|
return new RectangleArea(minX + d, minY, maxX, maxY);
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
2023-02-26 18:51:17 +00:00
|
|
|
public RectangleArea addMinY(double d) {
|
|
|
|
return new RectangleArea(minX, minY + d, maxX, maxY);
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
2023-02-26 18:51:17 +00:00
|
|
|
public RectangleArea withMinY(double d) {
|
|
|
|
return new RectangleArea(minX, d, maxX, maxY);
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
2023-02-26 18:51:17 +00:00
|
|
|
public RectangleArea withMaxY(double d) {
|
|
|
|
return new RectangleArea(minX, minY, maxX, d);
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
2023-02-26 18:51:17 +00:00
|
|
|
// public XPoint2D getProjectionOnFrontier(XPoint2D pt) {
|
|
|
|
// final double x = pt.getX();
|
|
|
|
// final double y = pt.getY();
|
|
|
|
// if (x > maxX && y >= minY && y <= maxY)
|
|
|
|
// return new XPoint2D(maxX - 1, y);
|
|
|
|
//
|
|
|
|
// if (x < minX && y >= minY && y <= maxY)
|
|
|
|
// return new XPoint2D(minX + 1, y);
|
|
|
|
//
|
|
|
|
// if (y > maxY && x >= minX && x <= maxX)
|
|
|
|
// return new XPoint2D(x, maxY - 1);
|
|
|
|
//
|
|
|
|
// if (y < minY && x >= minX && x <= maxX)
|
|
|
|
// return new XPoint2D(x, minY + 1);
|
|
|
|
//
|
|
|
|
// return new XPoint2D(x, y);
|
|
|
|
// }
|
2022-09-12 20:08:34 +00:00
|
|
|
|
2023-02-26 18:51:17 +00:00
|
|
|
public RectangleArea delta(double m1, double m2) {
|
|
|
|
return new RectangleArea(minX, minY, maxX + m1, maxY + m2);
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
2022-09-12 20:08:34 +00:00
|
|
|
public XDimension2D getDimension() {
|
|
|
|
return new XDimension2D(maxX - minX, maxY - minY);
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
2022-09-14 18:12:03 +00:00
|
|
|
public UTranslate getPosition() {
|
|
|
|
return new UTranslate(getMinX(), getMinY());
|
|
|
|
}
|
|
|
|
|
2023-02-26 18:51:17 +00:00
|
|
|
// public boolean isPointJustUpper(XPoint2D pt) {
|
|
|
|
// if (pt.getX() >= minX && pt.getX() <= maxX && pt.getY() <= minY) {
|
|
|
|
// return true;
|
|
|
|
// }
|
|
|
|
// return false;
|
|
|
|
// }
|
2015-04-07 18:18:37 +00:00
|
|
|
|
2022-09-12 20:08:34 +00:00
|
|
|
public Side getClosestSide(XPoint2D pt) {
|
2016-12-14 21:01:03 +00:00
|
|
|
final double distNorth = Math.abs(minY - pt.getY());
|
|
|
|
final double distSouth = Math.abs(maxY - pt.getY());
|
|
|
|
final double distWest = Math.abs(minX - pt.getX());
|
|
|
|
final double distEast = Math.abs(maxX - pt.getX());
|
2022-09-12 20:08:34 +00:00
|
|
|
if (isSmallerThan(distNorth, distWest, distEast, distSouth))
|
2016-12-14 21:01:03 +00:00
|
|
|
return Side.NORTH;
|
2022-09-12 20:08:34 +00:00
|
|
|
|
|
|
|
if (isSmallerThan(distSouth, distNorth, distWest, distEast))
|
2016-12-14 21:01:03 +00:00
|
|
|
return Side.SOUTH;
|
2022-09-12 20:08:34 +00:00
|
|
|
|
|
|
|
if (isSmallerThan(distEast, distNorth, distWest, distSouth))
|
2016-12-14 21:01:03 +00:00
|
|
|
return Side.EAST;
|
2022-09-12 20:08:34 +00:00
|
|
|
|
|
|
|
if (isSmallerThan(distWest, distNorth, distEast, distSouth))
|
2016-12-14 21:01:03 +00:00
|
|
|
return Side.WEST;
|
2022-09-12 20:08:34 +00:00
|
|
|
|
2016-12-14 21:01:03 +00:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
private boolean isSmallerThan(double value, double a, double b, double c) {
|
|
|
|
return value <= a && value <= b && value <= c;
|
|
|
|
}
|
|
|
|
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|