//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Constructs a new <code>FlatteningPathIterator</code> object * that flattens a path as it iterates over it. * The <code>limit</code> parameter allows you to control the * maximum number of recursive subdivisions that the iterator * can make before it assumes that the curve is flat enough * without measuring against the <code>flatness</code> parameter. * The flattened iteration therefore never generates more than * a maximum of <code>(2^limit)</code> line segments per curve. * @param src the original unflattened path being iterated over * @param flatness the maximum allowable distance between the * control points and the flattened curve * @param limit the maximum number of recursive subdivisions * allowed for any curved segment * @exception <code>IllegalArgumentException</code> if * <code>flatness</code> or <code>limit</code> * is less than zero */ public FlatteningPathIterator(PathIterator src, int flatness, int limit) { if (flatness < 0.0) { throw new ArgumentException("flatness must be >= 0"); } if (limit < 0) { throw new ArgumentException("limit must be >= 0"); } _src = src; _squareflat = flatness * flatness; _limit = limit; _levels = new int[limit + 1]; // prime the first path segment Next(false); }
/** * Accumulate the number of times the path crosses the shadow * extending to the right of the rectangle. See the comment * for the RECT_INTERSECTS constant for more complete details. * The return Value is the sum of all crossings for both the * top and bottom of the shadow for every segment in the path, * or the special Value RECT_INTERSECTS if the path ever enters * the interior of the rectangle. * The path must start with a SEG_MOVETO, otherwise an exception is * thrown. * The caller must check r[xy]{Min,Max} for NaN values. */ public static int RectCrossingsForPath(PathIterator pi, double rxmin, double rymin, double rxmax, double rymax) { if (rxmax <= rxmin || rymax <= rymin) { return 0; } if (pi.IsDone()) { return 0; } int[] coords = new int[6]; if (pi.CurrentSegment(coords) != PathIterator.SEG_MOVETO) { throw new IllegalPathStateException("missing initial moveto " + "in path definition"); } pi.Next(); double movx, movy; double curx = movx = coords[0]; double cury = movy = coords[1]; int crossings = 0; while (crossings != RECT_INTERSECTS && !pi.IsDone()) { double endx; double endy; switch (pi.CurrentSegment(coords)) { case PathIterator.SEG_MOVETO: if (curx != movx || cury != movy) { crossings = RectCrossingsForLine(crossings, rxmin, rymin, rxmax, rymax, curx, cury, movx, movy); } // Count should always be a multiple of 2 here. // assert((crossings & 1) != 0); movx = curx = coords[0]; movy = cury = coords[1]; break; case PathIterator.SEG_LINETO: endx = coords[0]; endy = coords[1]; crossings = RectCrossingsForLine(crossings, rxmin, rymin, rxmax, rymax, curx, cury, endx, endy); curx = endx; cury = endy; break; case PathIterator.SEG_QUADTO: endx = coords[2]; endy = coords[3]; crossings = RectCrossingsForQuad(crossings, rxmin, rymin, rxmax, rymax, curx, cury, coords[0], coords[1], endx, endy, 0); curx = endx; cury = endy; break; case PathIterator.SEG_CUBICTO: endx = coords[4]; endy = coords[5]; crossings = RectCrossingsForCubic(crossings, rxmin, rymin, rxmax, rymax, curx, cury, coords[0], coords[1], coords[2], coords[3], endx, endy, 0); curx = endx; cury = endy; break; case PathIterator.SEG_CLOSE: if (curx != movx || cury != movy) { crossings = RectCrossingsForLine(crossings, rxmin, rymin, rxmax, rymax, curx, cury, movx, movy); } curx = movx; cury = movy; // Count should always be a multiple of 2 here. // assert((crossings & 1) != 0); break; } pi.Next(); } if (crossings != RECT_INTERSECTS && (curx != movx || cury != movy)) { crossings = RectCrossingsForLine(crossings, rxmin, rymin, rxmax, rymax, curx, cury, movx, movy); } // Count should always be a multiple of 2 here. // assert((crossings & 1) != 0); return crossings; }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Constructs a new <code>FlatteningPathIterator</code> object that * flattens a path as it iterates over it. The iterator does not * subdivide any curve read from the source iterator to more than * 10 levels of subdivision which yields a maximum of 1024 line * segments per curve. * @param src the original unflattened path being iterated over * @param flatness the maximum allowable distance between the * control points and the flattened curve */ public FlatteningPathIterator(PathIterator src, int flatness) : this(src, flatness, 10) { }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Constructs a new <code>FlatteningPathIterator</code> object * that flattens a path as it iterates over it. * The <code>limit</code> parameter allows you to control the * maximum number of recursive subdivisions that the iterator * can make before it assumes that the curve is flat enough * without measuring against the <code>flatness</code> parameter. * The flattened iteration therefore never generates more than * a maximum of <code>(2^limit)</code> line segments per curve. * @param src the original unflattened path being iterated over * @param flatness the maximum allowable distance between the * control points and the flattened curve * @param limit the maximum number of recursive subdivisions * allowed for any curved segment * @exception <code>IllegalArgumentException</code> if * <code>flatness</code> or <code>limit</code> * is less than zero */ public FlatteningPathIterator(PathIterator src, int flatness, int limit) { if (flatness < 0.0) { throw new ArgumentException("flatness must be >= 0"); } if (limit < 0) { throw new ArgumentException("limit must be >= 0"); } _src = src; _squareflat = flatness * flatness; _limit = limit; _levels = new int[limit + 1]; // prime the first path segment Next(false); }
/** * Calculates the number of times the given path * crosses the ray extending to the right from (px,py). * If the point lies on a part of the path, * then no crossings are counted for that intersection. * +1 is added for each crossing where the Y coordinate is increasing * -1 is added for each crossing where the Y coordinate is decreasing * The return Value is the sum of all crossings for every segment in * the path. * The path must start with a SEG_MOVETO, otherwise an exception is * thrown. * The caller must check p[xy] for NaN values. * The caller may also reject infinite p[xy] values as well. */ public static int PointCrossingsForPath(PathIterator pi, double px, double py) { if (pi.IsDone()) { return 0; } int[] coords = new int[6]; if (pi.CurrentSegment(coords) != PathIterator.SEG_MOVETO) { throw new IllegalPathStateException("missing initial moveto " + "in path definition"); } pi.Next(); double movx = coords[0]; double movy = coords[1]; double curx = movx; double cury = movy; int crossings = 0; while (!pi.IsDone()) { double endx; double endy; switch (pi.CurrentSegment(coords)) { case PathIterator.SEG_MOVETO: if (cury != movy) { crossings += PointCrossingsForLine(px, py, curx, cury, movx, movy); } movx = curx = coords[0]; movy = cury = coords[1]; break; case PathIterator.SEG_LINETO: endx = coords[0]; endy = coords[1]; crossings += PointCrossingsForLine(px, py, curx, cury, endx, endy); curx = endx; cury = endy; break; case PathIterator.SEG_QUADTO: endx = coords[2]; endy = coords[3]; crossings += PointCrossingsForQuad(px, py, curx, cury, coords[0], coords[1], endx, endy, 0); curx = endx; cury = endy; break; case PathIterator.SEG_CUBICTO: endx = coords[4]; endy = coords[5]; crossings += PointCrossingsForCubic(px, py, curx, cury, coords[0], coords[1], coords[2], coords[3], endx, endy, 0); curx = endx; cury = endy; break; case PathIterator.SEG_CLOSE: if (cury != movy) { crossings += PointCrossingsForLine(px, py, curx, cury, movx, movy); } curx = movx; cury = movy; break; } pi.Next(); } if (cury != movy) { crossings += PointCrossingsForLine(px, py, curx, cury, movx, movy); } return crossings; }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// private static ArrayList PathToCurves(PathIterator pi) { ArrayList curves = new ArrayList(); int windingRule = pi.GetWindingRule(); // coords array is big enough for holding: // coordinates returned from currentSegment (6) // OR // two subdivided quadratic curves (2+4+4=10) // AND // 0-1 horizontal splitting parameters // OR // 2 parametric equation derivative coefficients // OR // three subdivided cubic curves (2+6+6+6=20) // AND // 0-2 horizontal splitting parameters // OR // 3 parametric equation derivative coefficients var coords = new int[23]; double movx = 0, movy = 0; double curx = 0, cury = 0; while (!pi.IsDone()) { double newx; double newy; switch (pi.CurrentSegment(coords)) { case PathIterator.SEG_MOVETO: Curve.InsertLine(curves, curx, cury, movx, movy); curx = movx = coords[0]; cury = movy = coords[1]; Curve.InsertMove(curves, movx, movy); break; case PathIterator.SEG_LINETO: newx = coords[0]; newy = coords[1]; Curve.InsertLine(curves, curx, cury, newx, newy); curx = newx; cury = newy; break; case PathIterator.SEG_QUADTO: { newx = coords[2]; newy = coords[3]; var dblCoords = new double[coords.Length]; for (int i = 0; i < coords.Length; i++) { dblCoords[i] = coords[i]; } Curve.InsertQuad(curves, curx, cury, dblCoords); curx = newx; cury = newy; } break; case PathIterator.SEG_CUBICTO: { newx = coords[4]; newy = coords[5]; var dblCoords = new double[coords.Length]; for (int i = 0; i < coords.Length; i++) { dblCoords[i] = coords[i]; } Curve.InsertCubic(curves, curx, cury, dblCoords); curx = newx; cury = newy; } break; case PathIterator.SEG_CLOSE: Curve.InsertLine(curves, curx, cury, movx, movy); curx = movx; cury = movy; break; } pi.Next(); } Curve.InsertLine(curves, curx, cury, movx, movy); AreaOp op; if (windingRule == PathIterator.WIND_EVEN_ODD) { op = new AreaOp.EoWindOp(); } else { op = new AreaOp.NzWindOp(); } return(op.Calculate(curves, EmptyCurves)); }
private double _movx, _movy; // The x,y of the last move segment #endregion Fields #region Constructors //////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Constructs a new <code>FlatteningPathIterator</code> object that * flattens a path as it iterates over it. The iterator does not * subdivide any curve read from the source iterator to more than * 10 levels of subdivision which yields a maximum of 1024 line * segments per curve. * @param src the original unflattened path being iterated over * @param flatness the maximum allowable distance between the * control points and the flattened curve */ public FlatteningPathIterator(PathIterator src, int flatness) : this(src, flatness, 10) { }
public static Crossings FindCrossings(PathIterator pi, double xlo, double ylo, double xhi, double yhi) { Crossings cross; if (pi.GetWindingRule() == PathIterator.WIND_EVEN_ODD) { cross = new EvenOdd(xlo, ylo, xhi, yhi); } else { cross = new NonZero(xlo, ylo, xhi, yhi); } // coords array is big enough for holding: // coordinates returned from currentSegment (6) // OR // two subdivided quadratic curves (2+4+4=10) // AND // 0-1 horizontal splitting parameters // OR // 2 parametric equation derivative coefficients // OR // three subdivided cubic curves (2+6+6+6=20) // AND // 0-2 horizontal splitting parameters // OR // 3 parametric equation derivative coefficients var coords = new int[23]; double movx = 0; double movy = 0; double curx = 0; double cury = 0; while (!pi.IsDone()) { int type = pi.CurrentSegment(coords); double newx; double newy; switch (type) { case PathIterator.SEG_MOVETO: if (movy != cury && cross.AccumulateLine(curx, cury, movx, movy)) { return null; } movx = curx = coords[0]; movy = cury = coords[1]; break; case PathIterator.SEG_LINETO: newx = coords[0]; newy = coords[1]; if (cross.AccumulateLine(curx, cury, newx, newy)) { return null; } curx = newx; cury = newy; break; case PathIterator.SEG_QUADTO: { newx = coords[2]; newy = coords[3]; var dblCoords = new double[coords.Length]; for (int i = 0; i < coords.Length; i++) { dblCoords[i] = coords[i]; } if (cross.AccumulateQuad(curx, cury, dblCoords)) { return null; } curx = newx; cury = newy; } break; case PathIterator.SEG_CUBICTO: { newx = coords[4]; newy = coords[5]; var dblCoords = new double[coords.Length]; for (int i = 0; i < coords.Length; i++) { dblCoords[i] = coords[i]; } if (cross.AccumulateCubic(curx, cury, dblCoords)) { return null; } curx = newx; cury = newy; break; } case PathIterator.SEG_CLOSE: if (movy != cury && cross.AccumulateLine(curx, cury, movx, movy)) { return null; } curx = movx; cury = movy; break; } pi.Next(); } if (movy != cury) { if (cross.AccumulateLine(curx, cury, movx, movy)) { return null; } } return cross; }
public static Crossings FindCrossings(PathIterator pi, double xlo, double ylo, double xhi, double yhi) { Crossings cross; if (pi.GetWindingRule() == PathIterator.WIND_EVEN_ODD) { cross = new EvenOdd(xlo, ylo, xhi, yhi); } else { cross = new NonZero(xlo, ylo, xhi, yhi); } // coords array is big enough for holding: // coordinates returned from currentSegment (6) // OR // two subdivided quadratic curves (2+4+4=10) // AND // 0-1 horizontal splitting parameters // OR // 2 parametric equation derivative coefficients // OR // three subdivided cubic curves (2+6+6+6=20) // AND // 0-2 horizontal splitting parameters // OR // 3 parametric equation derivative coefficients var coords = new int[23]; double movx = 0; double movy = 0; double curx = 0; double cury = 0; while (!pi.IsDone()) { int type = pi.CurrentSegment(coords); double newx; double newy; switch (type) { case PathIterator.SEG_MOVETO: if (movy != cury && cross.AccumulateLine(curx, cury, movx, movy)) { return(null); } movx = curx = coords[0]; movy = cury = coords[1]; break; case PathIterator.SEG_LINETO: newx = coords[0]; newy = coords[1]; if (cross.AccumulateLine(curx, cury, newx, newy)) { return(null); } curx = newx; cury = newy; break; case PathIterator.SEG_QUADTO: { newx = coords[2]; newy = coords[3]; var dblCoords = new double[coords.Length]; for (int i = 0; i < coords.Length; i++) { dblCoords[i] = coords[i]; } if (cross.AccumulateQuad(curx, cury, dblCoords)) { return(null); } curx = newx; cury = newy; } break; case PathIterator.SEG_CUBICTO: { newx = coords[4]; newy = coords[5]; var dblCoords = new double[coords.Length]; for (int i = 0; i < coords.Length; i++) { dblCoords[i] = coords[i]; } if (cross.AccumulateCubic(curx, cury, dblCoords)) { return(null); } curx = newx; cury = newy; break; } case PathIterator.SEG_CLOSE: if (movy != cury && cross.AccumulateLine(curx, cury, movx, movy)) { return(null); } curx = movx; cury = movy; break; } pi.Next(); } if (movy != cury) { if (cross.AccumulateLine(curx, cury, movx, movy)) { return(null); } } return(cross); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Appends the geometry of the specified * {@link PathIterator} object * to the path, possibly connecting the new geometry to the existing * path segments with a line segment. * If the {@code connect} parameter is {@code true} and the * path is not empty then any initial {@code moveTo} in the * geometry of the appended {@code IShape} is turned into a * {@code lineTo} segment. * If the destination coordinates of such a connecting {@code lineTo} * segment match the ending coordinates of a currently open * subpath then the segment is omitted as superfluous. * The winding rule of the specified {@code IShape} is ignored * and the appended geometry is governed by the winding * rule specified for this path. * * @param pi the {@code PathIterator} whose geometry is appended to * this path * @param connect a bool to control whether or not to turn an initial * {@code moveTo} segment into a {@code lineTo} segment * to connect the new geometry to the existing path */ public void Append(PathIterator pi, bool connect) { int[] coords = new int[6]; while (!pi.IsDone()) { switch (pi.CurrentSegment(coords)) { case SEG_MOVETO: if (!connect || _numTypes < 1 || _numCoords < 1) { MoveTo(coords[0], coords[1]); break; } if (_pointTypes[_numTypes - 1] != SEG_CLOSE && _intCoords[_numCoords - 2] == coords[0] && _intCoords[_numCoords - 1] == coords[1]) { // Collapse out initial moveto/lineto break; } LineTo(coords[0], coords[1]); break; case SEG_LINETO: LineTo(coords[0], coords[1]); break; case SEG_QUADTO: QuadTo(coords[0], coords[1], coords[2], coords[3]); break; case SEG_CUBICTO: CurveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]); break; case SEG_CLOSE: ClosePath(); break; } pi.Next(); connect = false; } }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// private static ArrayList PathToCurves(PathIterator pi) { ArrayList curves = new ArrayList(); int windingRule = pi.GetWindingRule(); // coords array is big enough for holding: // coordinates returned from currentSegment (6) // OR // two subdivided quadratic curves (2+4+4=10) // AND // 0-1 horizontal splitting parameters // OR // 2 parametric equation derivative coefficients // OR // three subdivided cubic curves (2+6+6+6=20) // AND // 0-2 horizontal splitting parameters // OR // 3 parametric equation derivative coefficients var coords = new int[23]; double movx = 0, movy = 0; double curx = 0, cury = 0; while (!pi.IsDone()) { double newx; double newy; switch (pi.CurrentSegment(coords)) { case PathIterator.SEG_MOVETO: Curve.InsertLine(curves, curx, cury, movx, movy); curx = movx = coords[0]; cury = movy = coords[1]; Curve.InsertMove(curves, movx, movy); break; case PathIterator.SEG_LINETO: newx = coords[0]; newy = coords[1]; Curve.InsertLine(curves, curx, cury, newx, newy); curx = newx; cury = newy; break; case PathIterator.SEG_QUADTO: { newx = coords[2]; newy = coords[3]; var dblCoords = new double[coords.Length]; for (int i = 0; i < coords.Length; i++) { dblCoords[i] = coords[i]; } Curve.InsertQuad(curves, curx, cury, dblCoords); curx = newx; cury = newy; } break; case PathIterator.SEG_CUBICTO: { newx = coords[4]; newy = coords[5]; var dblCoords = new double[coords.Length]; for (int i = 0; i < coords.Length; i++) { dblCoords[i] = coords[i]; } Curve.InsertCubic(curves, curx, cury, dblCoords); curx = newx; cury = newy; } break; case PathIterator.SEG_CLOSE: Curve.InsertLine(curves, curx, cury, movx, movy); curx = movx; cury = movy; break; } pi.Next(); } Curve.InsertLine(curves, curx, cury, movx, movy); AreaOp op; if (windingRule == PathIterator.WIND_EVEN_ODD) { op = new AreaOp.EoWindOp(); } else { op = new AreaOp.NzWindOp(); } return op.Calculate(curves, EmptyCurves); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Tests if the interior of the specified {@link PathIterator} * intersects the interior of a specified {@link Rectangle}. * <p> * This method provides a basic facility for implementors of * the {@link IShape} interface to implement support for the * {@link IShape#intersects(Rectangle)} method. * <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. * * @param pi the specified {@code PathIterator} * @param r the specified {@code Rectangle} * @return {@code true} if the specified {@code PathIterator} and * the interior of the specified {@code Rectangle} * intersect each other; {@code false} otherwise. */ public static bool Intersects(PathIterator pi, Rectangle r) { return Intersects(pi, r.X, r.Y, r.Width, r.Height); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Tests if the interior of the specified {@link PathIterator} * intersects the interior of a specified set of rectangular * coordinates. * <p> * This method provides a basic facility for implementors of * the {@link IShape} interface to implement support for the * {@link IShape#intersects(int, int, int, int)} method. * <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. * * @param pi the specified {@code PathIterator} * @param x the specified X coordinate * @param y the specified Y coordinate * @param w the width of the specified rectangular coordinates * @param h the height of the specified rectangular coordinates * @return {@code true} if the specified {@code PathIterator} and * the interior of the specified set of rectangular * coordinates intersect each other; {@code false} otherwise. */ public static bool Intersects(PathIterator pi, int x, int y, int w, int h) { if (Double.IsNaN(x + w) || 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 = (pi.GetWindingRule() == WIND_NON_ZERO ? -1 : 2); int crossings = Curve.RectCrossingsForPath(pi, x, y, x + w, y + h); return (crossings == Curve.RECT_INTERSECTS || (crossings & mask) != 0); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Tests if the specified {@link Rectangle} is entirely inside the * closed boundary of the specified {@link PathIterator}. * <p> * This method provides a basic facility for implementors of * the {@link IShape} interface to implement support for the * {@link IShape#contains(Rectangle)} method. * <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. * * @param pi the specified {@code PathIterator} * @param r a specified {@code Rectangle} * @return {@code true} if the specified {@code PathIterator} contains * the specified {@code Rectangle}; {@code false} otherwise. */ public static bool Contains(PathIterator pi, Rectangle r) { return Contains(pi, r.X, r.Y, r.Width, r.Height); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Tests if the specified {@link Point} is inside the closed * boundary of the specified {@link PathIterator}. * <p> * This method provides a basic facility for implementors of * the {@link IShape} interface to implement support for the * {@link IShape#contains(Point)} method. * * @param pi the specified {@code PathIterator} * @param p the specified {@code Point} * @return {@code true} if the specified coordinates are inside the * specified {@code PathIterator}; {@code false} otherwise */ public static bool Contains(PathIterator pi, Point p) { return Contains(pi, p.X, p.Y); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * 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 IShape} interface to implement support for the * {@link IShape#contains(int, int)} 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 */ public static bool Contains(PathIterator pi, int x, int y) { if (x * 0 + y * 0 == 0) { /* N * 0 is 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); } /* 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; }