package rescuecore2.misc.geometry.spatialindex; import static rescuecore2.misc.geometry.spatialindex.Tools.equal; import rescuecore2.misc.geometry.GeometryTools2D; /** A rectangular region. */ public class RectangleRegion implements Region { private double xMin; private double xMax; private double yMin; private double yMax; /** Construct a rectangular region. @param xMin The lower X coordinate. @param yMin The lower Y coordinate. @param xMax The upper X coordinate. @param yMax The upper Y coordinate. */ public RectangleRegion(double xMin, double yMin, double xMax, double yMax) { this.xMin = xMin; this.yMin = yMin; this.xMax = xMax; this.yMax = yMax; if (xMin > xMax) { this.xMin = xMax; this.xMax = xMin; } if (yMin > yMax) { this.yMin = yMax; this.yMax = yMin; } } @Override public double getXMin() { return xMin; } @Override public double getYMin() { return yMin; } @Override public double getXMax() { return xMax; } @Override public double getYMax() { return yMax; } /** Calculate the overlap with another RectangleRegion. @param other The other region. @return The overlapping area. */ public double getOverlapArea(RectangleRegion other) { if (!this.intersects(other)) { return 0; } double overlapXMin = Math.max(this.xMin, other.xMin); double overlapXMax = Math.min(this.xMax, other.xMax); double overlapYMin = Math.max(this.yMin, other.yMin); double overlapYMax = Math.min(this.yMax, other.yMax); return (overlapXMax - overlapXMin) * (overlapYMax - overlapYMin); } /** Get the area of this rectangle. @return The area. */ public double getArea() { return (xMax - xMin) * (yMax - yMin); } @Override public String toString() { return "Rectangle region: " + xMin + ", " + yMin + " -> " + xMax + ", " + yMax; } @Override public boolean equals(Object o) { if (o instanceof RectangleRegion) { RectangleRegion r = (RectangleRegion)o; return equal(xMin, r.xMin) && equal(xMax, r.xMax) && equal(yMin, r.yMin) && equal(yMax, r.yMax); } return false; } @Override public int hashCode() { Double d = xMin; return d.hashCode(); } @Override public boolean intersects(Region r) { if (r instanceof RectangleRegion) { RectangleRegion rect = (RectangleRegion)r; if (rect.xMax < this.xMin || rect.xMin > this.xMax || rect.yMax < this.yMin || rect.yMin > this.yMax) { return false; } return true; } else if (r instanceof LineRegion) { LineRegion l = (LineRegion)r; return GeometryTools2D.clipToRectangle(l.getLine(), getXMin(), getYMin(), getXMax(), getYMax()) != null; } else if (r instanceof PointRegion) { PointRegion p = (PointRegion)r; if (p.getX() < xMin || p.getX() > xMax || p.getY() < yMin || p.getY() > yMax) { return false; } return true; } else { return false; } } @Override public boolean contains(Region r) { if (r instanceof RectangleRegion) { RectangleRegion rect = (RectangleRegion)r; return (rect.xMin >= this.xMin && rect.xMax <= this.xMax && rect.yMin >= this.yMin && rect.yMax <= this.yMax); } else if (r instanceof LineRegion) { LineRegion l = (LineRegion)r; return (l.getXMin() >= this.xMin && l.getXMax() <= this.xMax && l.getYMin() >= this.yMin && l.getYMax() <= this.yMax); } else if (r instanceof PointRegion) { PointRegion p = (PointRegion)r; return (p.getX() >= this.xMin && p.getX() <= this.xMax && p.getY() >= this.yMin && p.getY() <= this.yMax); } else { return false; } } /* @Override public boolean touches(Region r) { if (r instanceof RectangleRegion) { RectangleRegion rect = (RectangleRegion)r; return (equal(this.xMin, rect.xMin) || equal(this.xMax, rect.xMax) || equal(this.yMin, rect.yMin) || equal(this.yMax, rect.yMax)); } else if (r instanceof PointRegion) { PointRegion p = (PointRegion)r; return (equal(this.xMin, p.getX()) || equal(this.xMax, p.getX()) || equal(this.yMin, p.getY()) || equal(this.yMax, p.getY())); } else if (r instanceof NullRegion) { return false; } else { throw new IllegalArgumentException("Cannot check for touch with " + r); } } */ }