/** * Tests if the specified coordinates are inside the closed * boundary of the specified {@link PathIterator}. * <p> * This method provides a basic facility for implementors of * the {@link Shape} interface to implement support for the * {@link Shape#contains(double, double)} method. * * @param pi the specified {@code PathIterator} * @param x the specified X coordinate * @param y the specified Y coordinate * @return {@code true} if the specified coordinates are inside the * specified {@code PathIterator}; {@code false} otherwise * @since 1.6 */ public static boolean contains(PathIterator pi, double x, double y) { if (x * 0.0 + y * 0.0 == 0.0) { /* N * 0.0 is 0.0 only if N is finite. * Here we know that both x and y are finite. */ int mask = (pi.getWindingRule() == WIND_NON_ZERO ? -1 : 1); int cross = Curve.pointCrossingsForPath(pi, x, y); return ((cross & mask) != 0); } else { /* Either x or y was infinite or NaN. * A NaN always produces a negative response to any test * and Infinity values cannot be "inside" any path so * they should return false as well. */ return false; } }
/** * {@inheritDoc} * <p> * This method object may conservatively return false in * cases where the specified rectangular area intersects a * segment of the path, but that segment does not represent a * boundary between the interior and exterior of the path. * Such segments could lie entirely within the interior of the * path if they are part of a path with a {@link #WIND_NON_ZERO} * winding rule or if the segments are retraced in the reverse * direction such that the two sets of segments cancel each * other out without any exterior area falling between them. * To determine whether segments represent true boundaries of * the interior of the path would require extensive calculations * involving all of the segments of the path and the winding * rule and are thus beyond the scope of this implementation. * * @since 1.6 */ public final boolean contains(double x, double y, double w, double h) { if (java.lang.Double.isNaN(x+w) || java.lang.Double.isNaN(y+h)) { /* [xy]+[wh] is NaN if any of those values are NaN, * or if adding the two together would produce NaN * by virtue of adding opposing Infinte values. * Since we need to add them below, their sum must * not be NaN. * We return false because NaN always produces a * negative response to tests */ return false; } if (w <= 0 || h <= 0) { return false; } int mask = (windingRule == WIND_NON_ZERO ? -1 : 2); int crossings = rectCrossings(x, y, x+w, y+h); return (crossings != Curve.RECT_INTERSECTS && (crossings & mask) != 0); }
/** * {@inheritDoc} * <p> * This method object may conservatively return true in * cases where the specified rectangular area intersects a * segment of the path, but that segment does not represent a * boundary between the interior and exterior of the path. * Such a case may occur if some set of segments of the * path are retraced in the reverse direction such that the * two sets of segments cancel each other out without any * interior area between them. * To determine whether segments represent true boundaries of * the interior of the path would require extensive calculations * involving all of the segments of the path and the winding * rule and are thus beyond the scope of this implementation. * * @since 1.6 */ public final boolean intersects(double x, double y, double w, double h) { if (java.lang.Double.isNaN(x+w) || java.lang.Double.isNaN(y+h)) { /* [xy]+[wh] is NaN if any of those values are NaN, * or if adding the two together would produce NaN * by virtue of adding opposing Infinte values. * Since we need to add them below, their sum must * not be NaN. * We return false because NaN always produces a * negative response to tests */ return false; } if (w <= 0 || h <= 0) { return false; } int mask = (windingRule == WIND_NON_ZERO ? -1 : 2); int crossings = rectCrossings(x, y, x+w, y+h); return (crossings == Curve.RECT_INTERSECTS || (crossings & mask) != 0); }
/** * Tests whether this <code>Area</code> is rectangular in shape. * @return <code>true</code> if the geometry of this * <code>Area</code> is rectangular in shape; <code>false</code> * otherwise. * @since 1.2 */ public boolean isRectangular() { int size = curves.size(); if (size == 0) { return true; } if (size > 3) { return false; } Curve c1 = (Curve) curves.get(1); Curve c2 = (Curve) curves.get(2); if (c1.getOrder() != 1 || c2.getOrder() != 1) { return false; } if (c1.getXTop() != c1.getXBot() || c2.getXTop() != c2.getXBot()) { return false; } if (c1.getYTop() != c2.getYTop() || c1.getYBot() != c2.getYBot()) { // One might be able to prove that this is impossible... return false; } return true; }
/** * {@inheritDoc} * @since 1.2 */ public boolean contains(double x, double y) { if (!(x * 0.0 + y * 0.0 == 0.0)) { /* Either x or y was infinite or NaN. * A NaN always produces a negative response to any test * and Infinity values cannot be "inside" any path so * they should return false as well. */ return false; } // We count the "Y" crossings to determine if the point is // inside the curve bounded by its closing line. double x1 = getX1(); double y1 = getY1(); double x2 = getX2(); double y2 = getY2(); int crossings = (Curve.pointCrossingsForLine(x, y, x1, y1, x2, y2) + Curve.pointCrossingsForCubic(x, y, x1, y1, getCtrlX1(), getCtrlY1(), getCtrlX2(), getCtrlY2(), x2, y2, 0)); return ((crossings & 1) == 1); }
private int rectCrossings(double x, double y, double w, double h) { int crossings = 0; if (!(getX1() == getX2() && getY1() == getY2())) { crossings = Curve.rectCrossingsForLine(crossings, x, y, x+w, y+h, getX1(), getY1(), getX2(), getY2()); if (crossings == Curve.RECT_INTERSECTS) { return crossings; } } // we call this with the curve's direction reversed, because we wanted // to call rectCrossingsForLine first, because it's cheaper. return Curve.rectCrossingsForCubic(crossings, x, y, x+w, y+h, getX2(), getY2(), getCtrlX2(), getCtrlY2(), getCtrlX1(), getCtrlY1(), getX1(), getY1(), 0); }
/** * Tests whether this {@code Area} is rectangular in shape. * @return {@code true} if the geometry of this * {@code Area} is rectangular in shape; {@code false} * otherwise. * @since 1.2 */ public boolean isRectangular() { int size = curves.size(); if (size == 0) { return true; } if (size > 3) { return false; } Curve c1 = curves.get(1); Curve c2 = curves.get(2); if (c1.getOrder() != 1 || c2.getOrder() != 1) { return false; } if (c1.getXTop() != c1.getXBot() || c2.getXTop() != c2.getXBot()) { return false; } if (c1.getYTop() != c2.getYTop() || c1.getYBot() != c2.getYBot()) { // One might be able to prove that this is impossible... return false; } return true; }