/** * Gets the lowest y-coordinate value of the vertices composing this polygon. * * @return the minimum y-coordinate. * @throws OutdatedPolygonException if {@link ConvexPolygon2DBasics#update()} has not been called * since last time this polygon's vertices were edited. * @throws EmptyPolygonException if this polygon is empty when calling this method. */ default double getMinY() { return getBoundingBox().getMinY(); }
/** * Sets this bounding box to the union of {@code boundingBoxOne} and {@code boundingBoxTwo}. * <p> * This bounding box is set such that it is the smallest bounding box containing the two given * bounding boxes. * </p> * * @param boundingBoxOne the first bounding box. Can be the same instance as this. Not modified. * @param boundingBoxTwo the second bounding box. Can be the same instance as this. Not modified. */ default void combine(BoundingBox2DReadOnly boundingBoxOne, BoundingBox2DReadOnly boundingBoxTwo) { double minX = Math.min(boundingBoxOne.getMinX(), boundingBoxTwo.getMinX()); double minY = Math.min(boundingBoxOne.getMinY(), boundingBoxTwo.getMinY()); double maxX = Math.max(boundingBoxOne.getMaxX(), boundingBoxTwo.getMaxX()); double maxY = Math.max(boundingBoxOne.getMaxY(), boundingBoxTwo.getMaxY()); set(minX, minY, maxX, maxY); }
/** * Asserts that the minimum coordinates are less or equal to the maximum coordinates. * * @throws RuntimeException if any of the minimum coordinates is strictly greater than the maximum * coordinate on the same axis. */ default void checkBounds() { if (getMinX() > getMaxX()) throw new BoundingBoxException("minPoint.getX() > maxPoint.getX(): " + getMinX() + ">" + getMaxX()); if (getMinY() > getMaxY()) throw new BoundingBoxException("minPoint.getY() > maxPoint.getY(): " + getMinY() + ">" + getMaxY()); }
/** * Tests if this bounding box and {@code other} intersects. * <p> * The two bounding boxes are considered to not be intersecting if they share a corner or an edge. * </p> * * @param other the other bounding box to test if it is intersecting with this bounding box. Not * Modified. * @return {@code true} if the two bounding boxes intersect, {@code false} otherwise. */ default boolean intersectsExclusive(BoundingBox2DReadOnly other) { checkBounds(); if (other.getMinX() >= getMaxX() || other.getMaxX() <= getMinX()) return false; if (other.getMinY() >= getMaxY() || other.getMaxY() <= getMinY()) return false; return true; }
/** * Tests if this bounding box and {@code other} intersects. * <p> * The two bounding boxes are considered to be intersecting if they share a corner or an edge. * </p> * * @param other the other bounding box to test if it is intersecting with this bounding box. Not * Modified. * @return {@code true} if the two bounding boxes intersect, {@code false} otherwise. * @throws RuntimeException if this bounding box is improper according to {@link #checkBounds()}. */ default boolean intersectsInclusive(BoundingBox2DReadOnly other) { checkBounds(); if (other.getMinX() > getMaxX() || other.getMaxX() < getMinX()) return false; if (other.getMinY() > getMaxY() || other.getMaxY() < getMinY()) return false; return true; }
/** * Performs a linear interpolation between this bounding box minimum and maximum coordinates using * independent parameters {@code xParameter} and {@code yParameter} for the x-axis and y-axis * respectively. The result is stored in {@code pointToPack}. * <p> * <ul> * <li>{@code (xParameter == 0)} results in: {@code (pointToPack.getX() == this.getMinX())}. * <li>{@code (xParameter == 1)} results in: {@code (pointToPack.getX() == this.getMaxX())}. * <li>{@code (yParameter == 0)} results in: {@code (pointToPack.getY() == this.getMinY())}. * <li>{@code (yParameter == 1)} results in: {@code (pointToPack.getY() == this.getMaxY())}. * </ul> * </p> * * @param xParameter the parameter to use for the interpolation along the x-axis. * @param yParameter the parameter to use for the interpolation along the y-axis. * @param pointToPack the point 2D in which the result is stored. Modified. * @throws RuntimeException if this bounding box is improper according to {@link #checkBounds()}. */ default void getPointGivenParameters(double xParameter, double yParameter, Point2DBasics pointToPack) { checkBounds(); pointToPack.setX(getMinX() + xParameter * (getMaxX() - getMinX())); pointToPack.setY(getMinY() + yParameter * (getMaxY() - getMinY())); }
/** * Tests if this bounding box and {@code other} intersects. * <p> * <ul> * <li>if {@code epsilon == 0}, this method is equivalent to * {@link #intersectsExclusive(BoundingBox2DReadOnly)}. * <li>if {@code epsilon > 0}, the size of this bounding box is scaled up by shifting the edges of * {@code epsilon} toward the outside. * <li>if {@code epsilon > 0}, the size of this bounding box is scaled down by shifting the edges of * {@code epsilon} toward the inside. * </ul> * </p> * * @param other the other bounding box to test if it is intersecting with this bounding box. Not * Modified. * @param epsilon the tolerance to use in this test. * @return {@code true} if the two bounding boxes intersect, {@code false} otherwise. * @throws RuntimeException if this bounding box is improper according to {@link #checkBounds()}. */ default boolean intersectsEpsilon(BoundingBox2DReadOnly other, double epsilon) { checkBounds(); if (other.getMinX() >= getMaxX() + epsilon || other.getMaxX() <= getMinX() - epsilon) return false; if (other.getMinY() >= getMaxY() + epsilon || other.getMaxY() <= getMinY() - epsilon) return false; return true; }
/** * Tests if the {@code query} is located inside this bounding box. * <p> * The query is considered to be inside if located exactly on an edge of this bounding box. * </p> * * @param x the x-coordinate of the query to test if it is located inside this bounding box. Not * modified. * @param y the y-coordinate of the query to test if it is located inside this bounding box. Not * modified. * @return {@code true} if the query is inside or located on an edge of this bounding box, * {@code false} if outside. * @throws RuntimeException if this bounding box is improper according to {@link #checkBounds()}. */ default boolean isInsideInclusive(double x, double y) { checkBounds(); if (x < getMinX() || x > getMaxX()) return false; if (y < getMinY() || y > getMaxY()) return false; return true; }
/** * Tests if the {@code query} is located inside this bounding box. * <p> * The query is considered to be outside if located exactly on an edge of this bounding box. * </p> * * @param x the x-coordinate of the query to test if it is located inside this bounding box. Not * modified. * @param y the y-coordinate of the query to test if it is located inside this bounding box. Not * modified. * @return {@code true} if the query is inside, {@code false} if outside or located on an edge of * this bounding box. * @throws RuntimeException if this bounding box is improper according to {@link #checkBounds()}. */ default boolean isInsideExclusive(double x, double y) { checkBounds(); if (x <= getMinX() || x >= getMaxX()) return false; if (y <= getMinY() || y >= getMaxY()) return false; return true; }
return false; if (y <= getMinY() - epsilon || y >= getMaxY() + epsilon) return false;
/** * Tests if this bounding box and {@code other} intersects. * <p> * The two bounding boxes are considered to not be intersecting if they share a corner or an edge. * </p> * <p> * This method is equivalent to projecting this bounding box onto the XY-plane before performing the * test. * </p> * * @param other the other bounding box to test if it is intersecting with this bounding box. Not * Modified. * @return {@code true} if the two bounding boxes intersect, {@code false} otherwise. */ public boolean intersectsExclusiveInXYPlane(BoundingBox2DReadOnly other) { if (other.getMinX() >= getMaxX() || other.getMaxX() <= getMinX()) return false; if (other.getMinY() >= getMaxY() || other.getMaxY() <= getMinY()) return false; return true; }
/** * Tests if this bounding box and {@code other} intersects. * <p> * The two bounding boxes are considered to be intersecting if they share a corner or an edge. * </p> * <p> * This method is equivalent to projecting this bounding box onto the XY-plane before performing the * test. * </p> * * @param other the other bounding box to test if it is intersecting with this bounding box. Not * Modified. * @return {@code true} if the two bounding boxes intersect, {@code false} otherwise. */ public boolean intersectsInclusiveInXYPlane(BoundingBox2DReadOnly other) { if (other.getMinX() > getMaxX() || other.getMaxX() < getMinX()) return false; if (other.getMinY() > getMaxY() || other.getMaxY() < getMinY()) return false; return true; }
/** * Tests if this bounding box and {@code other} intersects. * <p> * <ul> * <li>if {@code epsilon == 0}, this method is equivalent to * {@link #intersectsExclusiveInXYPlane(BoundingBox2DReadOnly)}. * <li>if {@code epsilon > 0}, the size of this bounding box is scaled up by shifting the edges of * {@code epsilon} toward the outside. * <li>if {@code epsilon > 0}, the size of this bounding box is scaled down by shifting the edges of * {@code epsilon} toward the inside. * </ul> * </p> * <p> * This method is equivalent to projecting this bounding box onto the XY-plane before performing the * test. * </p> * * @param other the other bounding box to test if it is intersecting with this bounding box. Not * Modified. * @param epsilon the tolerance to use in this test. * @return {@code true} if the two bounding boxes intersect, {@code false} otherwise. */ public boolean intersectsEpsilonInXYPlane(BoundingBox2DReadOnly other, double epsilon) { if (other.getMinX() >= getMaxX() + epsilon || other.getMaxX() <= getMinX() - epsilon) return false; if (other.getMinY() >= getMaxY() + epsilon || other.getMaxY() <= getMinY() - epsilon) return false; return true; }