package com.github.davidmoten.rtree.geometry; import com.github.davidmoten.guavamini.Objects; import com.github.davidmoten.guavamini.Optional; import com.github.davidmoten.guavamini.Preconditions; import com.github.davidmoten.rtree.internal.util.ObjectsHelper; final class RectangleImpl implements Rectangle { private final float x1, y1, x2, y2; private RectangleImpl(float x1, float y1, float x2, float y2) { Preconditions.checkArgument(x2 >= x1); Preconditions.checkArgument(y2 >= y1); this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; } static Rectangle create(double x1, double y1, double x2, double y2) { return new RectangleImpl((float) x1, (float) y1, (float) x2, (float) y2); } static Rectangle create(float x1, float y1, float x2, float y2) { return new RectangleImpl(x1, y1, x2, y2); } /* * (non-Javadoc) * * @see com.github.davidmoten.rtree.geometry.RectangleI#x1() */ @Override public float x1() { return x1; } /* * (non-Javadoc) * * @see com.github.davidmoten.rtree.geometry.RectangleI#y1() */ @Override public float y1() { return y1; } /* * (non-Javadoc) * * @see com.github.davidmoten.rtree.geometry.RectangleI#x2() */ @Override public float x2() { return x2; } /* * (non-Javadoc) * * @see com.github.davidmoten.rtree.geometry.RectangleI#y2() */ @Override public float y2() { return y2; } /* * (non-Javadoc) * * @see com.github.davidmoten.rtree.geometry.RectangleI#area() */ @Override public float area() { return (x2 - x1) * (y2 - y1); } /* * (non-Javadoc) * * @see * com.github.davidmoten.rtree.geometry.RectangleI#add(com.github.davidmoten * .rtree.geometry.Rectangle) */ @Override public Rectangle add(Rectangle r) { return new RectangleImpl(min(x1, r.x1()), min(y1, r.y1()), max(x2, r.x2()), max(y2, r.y2())); } /* * (non-Javadoc) * * @see com.github.davidmoten.rtree.geometry.RectangleI#contains(double, * double) */ @Override public boolean contains(double x, double y) { return x >= x1 && x <= x2 && y >= y1 && y <= y2; } @Override public boolean intersects(Rectangle r) { return intersects(x1, y1, x2, y2, r.x1(), r.y1(), r.x2(), r.y2()); // return r.x2() >= x1 && r.x1() <= x2 && r.y2() >= y1 && r.y1() <= y2; } @Override public double distance(Rectangle r) { return distance(x1, y1, x2, y2, r.x1(), r.y1(), r.x2(), r.y2()); // if (intersects(r)) // return 0; // else { // Rectangle mostLeft = x1 < r.x1() ? this : r; // Rectangle mostRight = x1 > r.x1() ? this : r; // double xDifference = max(0, // mostLeft.x1() == mostRight.x1() ? 0 : mostRight.x1() - // mostLeft.x2()); // // Rectangle upper = y1 < r.y1() ? this : r; // Rectangle lower = y1 > r.y1() ? this : r; // // double yDifference = max(0, upper.y1() == lower.y1() ? 0 : lower.y1() // - upper.y2()); // // return Math.sqrt(xDifference * xDifference + yDifference * // yDifference); // } } public static double distance(float x1, float y1, float x2, float y2, float a1, float b1, float a2, float b2) { if (intersects(x1, y1, x2, y2, a1, b1, a2, b2)) { return 0; } boolean xyMostLeft = x1 < a1; float mostLeftX1 = xyMostLeft ? x1 : a1; float mostRightX1 = xyMostLeft ? a1 : x1; float mostLeftX2 = xyMostLeft ? x2 : a2; double xDifference = max(0, mostLeftX1 == mostRightX1 ? 0 : mostRightX1 - mostLeftX2); boolean xyMostDown = y1 < b1; float mostDownY1 = xyMostDown ? y1 : b1; float mostUpY1 = xyMostDown ? b1 : y1; float mostDownY2 = xyMostDown ? y2 : b2; double yDifference = max(0, mostDownY1 == mostUpY1 ? 0 : mostUpY1 - mostDownY2); return Math.sqrt(xDifference * xDifference + yDifference * yDifference); } private static boolean intersects(float x1, float y1, float x2, float y2, float a1, float b1, float a2, float b2) { return x1 <= a2 && a1 <= x2 && y1 <= b2 && b1 <= y2; } @Override public Rectangle mbr() { return this; } @Override public String toString() { return "Rectangle [x1=" + x1 + ", y1=" + y1 + ", x2=" + x2 + ", y2=" + y2 + "]"; } @Override public int hashCode() { return Objects.hashCode(x1, y1, x2, y2); } @Override public boolean equals(Object obj) { Optional<RectangleImpl> other = ObjectsHelper.asClass(obj, RectangleImpl.class); if (other.isPresent()) { return Objects.equal(x1, other.get().x1) && Objects.equal(x2, other.get().x2) && Objects.equal(y1, other.get().y1) && Objects.equal(y2, other.get().y2); } else return false; } /* * (non-Javadoc) * * @see * com.github.davidmoten.rtree.geometry.RectangleI#intersectionArea(com. * github.davidmoten.rtree.geometry.Rectangle) */ @Override public float intersectionArea(Rectangle r) { if (!intersects(r)) return 0; else return create(max(x1, r.x1()), max(y1, r.y1()), min(x2, r.x2()), min(y2, r.y2())) .area(); } /* * (non-Javadoc) * * @see com.github.davidmoten.rtree.geometry.RectangleI#perimeter() */ @Override public float perimeter() { return 2 * (x2 - x1) + 2 * (y2 - y1); } @Override public Geometry geometry() { return this; } private static float max(float a, float b) { if (a < b) return b; else return a; } private static float min(float a, float b) { if (a < b) return a; else return b; } }