java.lang.Object java.awt.geom.Path2D
All Implemented Interfaces:
Shape, Cloneable
Direct Known Subclasses:
GeneralPath, Float, Double
Use Path2D.Float when dealing with data that can be represented and used with floating point precision. Use Path2D.Double for data that requires the accuracy or range of double precision.
{@code Path2D} provides exactly those facilities required for basic construction and management of a geometric path and implementation of the above interfaces with little added interpretation. If it is useful to manipulate the interiors of closed geometric shapes beyond simple hit testing then the Area class provides additional capabilities specifically targeted at closed figures. While both classes nominally implement the {@code Shape} interface, they differ in purpose and together they provide two useful views of a geometric shape where {@code Path2D} deals primarily with a trajectory formed by path segments and {@code Area} deals more with interpretation and manipulation of enclosed regions of 2D geometric space.
The PathIterator interface has more detailed descriptions of the types of segments that make up a path and the winding rules that control how to determine which regions are inside or outside the path.
Jim
 Graham1.6
 Nested Class Summary:  

public static class  Path2D.Float  The {@code Float} class defines a geometric path with coordinates stored in single precision floating point. 
public static class  Path2D.Double  The {@code Double} class defines a geometric path with coordinates stored in double precision floating point. 
abstract static class  Path2D.Iterator 
Field Summary  

public static final int  WIND_EVEN_ODD  An evenodd winding rule for determining the interior of
a path.

public static final int  WIND_NON_ZERO  A nonzero winding rule for determining the interior of a
path.

transient byte[]  pointTypes  
transient int  numTypes  
transient int  numCoords  
transient int  windingRule  
static final int  INIT_SIZE  
static final int  EXPAND_MAX 
Constructor: 

Path2D(){ } 
Path2D(int rule, int initialTypes){ setWindingRule(rule); this.pointTypes = new byte[initialTypes]; } 
Method from java.awt.geom.Path2D Summary: 

append, append, append, append, clone, cloneCoordsDouble, cloneCoordsFloat, closePath, contains, contains, contains, contains, contains, contains, contains, contains, createTransformedShape, curveTo, getBounds, getCurrentPoint, getPathIterator, getPoint, getWindingRule, intersects, intersects, intersects, intersects, lineTo, moveTo, needRoom, pointCrossings, quadTo, readObject, rectCrossings, reset, setWindingRule, transform, writeObject 
Methods from java.lang.Object: 

clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait 
Method from java.awt.geom.Path2D Detail: 

abstract void append(float x, float y) 
abstract void append(double x, double y) 
public final void append(Shape s, boolean connect){ append(s.getPathIterator(null), connect); }

abstract public void append(PathIterator pi, boolean connect)

abstract public Object clone()

abstract double[] cloneCoordsDouble(AffineTransform at) 
abstract float[] cloneCoordsFloat(AffineTransform at) 
public final synchronized void closePath(){ if (numTypes == 0  pointTypes[numTypes  1] != SEG_CLOSE) { needRoom(true, 0); pointTypes[numTypes++] = SEG_CLOSE; } }

public final boolean contains(Point2D p){ return contains(p.getX(), p.getY()); }

public final boolean contains(Rectangle2D r){ return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); }
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 #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. 
public static boolean contains(PathIterator pi, Point2D p){ return contains(pi, p.getX(), p.getY()); }
This method provides a basic facility for implementors of the Shape interface to implement support for the Shape#contains(Point2D) method. 
public final boolean contains(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. */ if (numTypes < 2) { return false; } int mask = (windingRule == WIND_NON_ZERO ? 1 : 1); return ((pointCrossings(x, y) & 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; } }

public static boolean contains(PathIterator pi, Rectangle2D r){ return contains(pi, r.getX(), r.getY(), r.getWidth(), r.getHeight()); }
This method provides a basic facility for implementors of the Shape interface to implement support for the Shape#contains(Rectangle2D) method. 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 #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. 
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; } }
This method provides a basic facility for implementors of the Shape interface to implement support for the Shape#contains(double, double) method. 
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); }
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 #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. 
public static boolean contains(PathIterator pi, 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 = (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); }
This method provides a basic facility for implementors of the Shape interface to implement support for the Shape#contains(double, double, double, double) method. 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 #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. 
public final synchronized Shape createTransformedShape(AffineTransform at){ Path2D p2d = (Path2D) clone(); if (at != null) { p2d.transform(at); } return p2d; }

abstract public void curveTo(double x1, double y1, double x2, double y2, double x3, double y3)

public final Rectangle getBounds(){ return getBounds2D().getBounds(); }

public final synchronized Point2D getCurrentPoint(){ int index = numCoords; if (numTypes < 1  index < 1) { return null; } if (pointTypes[numTypes  1] == SEG_CLOSE) { loop: for (int i = numTypes  2; i > 0; i) { switch (pointTypes[i]) { case SEG_MOVETO: break loop; case SEG_LINETO: index = 2; break; case SEG_QUADTO: index = 4; break; case SEG_CUBICTO: index = 6; break; case SEG_CLOSE: break; } } } return getPoint(index  2); }

public final PathIterator getPathIterator(AffineTransform at, double flatness){ return new FlatteningPathIterator(getPathIterator(at), flatness); }
The iterator for this class is not multithreaded safe, which means that this {@code Path2D} class does not guarantee that modifications to the geometry of this {@code Path2D} object do not affect any iterations of that geometry that are already in process. 
abstract Point2D getPoint(int coordindex) 
public final synchronized int getWindingRule(){ return windingRule; }

public final boolean intersects(Rectangle2D r){ return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); }
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. 
public static boolean intersects(PathIterator pi, Rectangle2D r){ return intersects(pi, r.getX(), r.getY(), r.getWidth(), r.getHeight()); }
This method provides a basic facility for implementors of the Shape interface to implement support for the Shape#intersects(Rectangle2D) method. 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. 
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); }
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. 
public static boolean intersects(PathIterator pi, 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 = (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); }
This method provides a basic facility for implementors of the Shape interface to implement support for the Shape#intersects(double, double, double, double) method. 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. 
abstract public void lineTo(double x, double y)

abstract public void moveTo(double x, double y)

abstract void needRoom(boolean needMove, int newCoords) 
abstract int pointCrossings(double px, double py) 
abstract public void quadTo(double x1, double y1, double x2, double y2)

final void readObject(ObjectInputStream s, boolean storedbl) throws ClassNotFoundException, IOException{ s.defaultReadObject(); // The subclass calls this method with the storage type that // they want us to use (storedbl) so we ignore the storage // method hint from the stream. s.readByte(); int nT = s.readInt(); int nC = s.readInt(); try { setWindingRule(s.readByte()); } catch (IllegalArgumentException iae) { throw new java.io.InvalidObjectException(iae.getMessage()); } pointTypes = new byte[(nT < 0) ? INIT_SIZE : nT]; if (nC < 0) { nC = INIT_SIZE * 2; } if (storedbl) { ((Path2D.Double) this).doubleCoords = new double[nC]; } else { ((Path2D.Float) this).floatCoords = new float[nC]; } PATHDONE: for (int i = 0; nT < 0  i < nT; i++) { boolean isdbl; int npoints; byte segtype; byte serialtype = s.readByte(); switch (serialtype) { case SERIAL_SEG_FLT_MOVETO: isdbl = false; npoints = 1; segtype = SEG_MOVETO; break; case SERIAL_SEG_FLT_LINETO: isdbl = false; npoints = 1; segtype = SEG_LINETO; break; case SERIAL_SEG_FLT_QUADTO: isdbl = false; npoints = 2; segtype = SEG_QUADTO; break; case SERIAL_SEG_FLT_CUBICTO: isdbl = false; npoints = 3; segtype = SEG_CUBICTO; break; case SERIAL_SEG_DBL_MOVETO: isdbl = true; npoints = 1; segtype = SEG_MOVETO; break; case SERIAL_SEG_DBL_LINETO: isdbl = true; npoints = 1; segtype = SEG_LINETO; break; case SERIAL_SEG_DBL_QUADTO: isdbl = true; npoints = 2; segtype = SEG_QUADTO; break; case SERIAL_SEG_DBL_CUBICTO: isdbl = true; npoints = 3; segtype = SEG_CUBICTO; break; case SERIAL_SEG_CLOSE: isdbl = false; npoints = 0; segtype = SEG_CLOSE; break; case SERIAL_PATH_END: if (nT < 0) { break PATHDONE; } throw new StreamCorruptedException("unexpected PATH_END"); default: throw new StreamCorruptedException("unrecognized path type"); } needRoom(segtype != SEG_MOVETO, npoints * 2); if (isdbl) { while (npoints >= 0) { append(s.readDouble(), s.readDouble()); } } else { while (npoints >= 0) { append(s.readFloat(), s.readFloat()); } } pointTypes[numTypes++] = segtype; } if (nT >= 0 && s.readByte() != SERIAL_PATH_END) { throw new StreamCorruptedException("missing PATH_END"); } } 
abstract int rectCrossings(double rxmin, double rymin, double rxmax, double rymax) 
public final synchronized void reset(){ numTypes = numCoords = 0; }

public final void setWindingRule(int rule){ if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO) { throw new IllegalArgumentException("winding rule must be "+ "WIND_EVEN_ODD or "+ "WIND_NON_ZERO"); } windingRule = rule; }

abstract public void transform(AffineTransform at)

final void writeObject(ObjectOutputStream s, boolean isdbl) throws IOException{ s.defaultWriteObject(); float fCoords[]; double dCoords[]; if (isdbl) { dCoords = ((Path2D.Double) this).doubleCoords; fCoords = null; } else { fCoords = ((Path2D.Float) this).floatCoords; dCoords = null; } int numTypes = this.numTypes; s.writeByte(isdbl ? SERIAL_STORAGE_DBL_ARRAY : SERIAL_STORAGE_FLT_ARRAY); s.writeInt(numTypes); s.writeInt(numCoords); s.writeByte((byte) windingRule); int cindex = 0; for (int i = 0; i < numTypes; i++) { int npoints; byte serialtype; switch (pointTypes[i]) { case SEG_MOVETO: npoints = 1; serialtype = (isdbl ? SERIAL_SEG_DBL_MOVETO : SERIAL_SEG_FLT_MOVETO); break; case SEG_LINETO: npoints = 1; serialtype = (isdbl ? SERIAL_SEG_DBL_LINETO : SERIAL_SEG_FLT_LINETO); break; case SEG_QUADTO: npoints = 2; serialtype = (isdbl ? SERIAL_SEG_DBL_QUADTO : SERIAL_SEG_FLT_QUADTO); break; case SEG_CUBICTO: npoints = 3; serialtype = (isdbl ? SERIAL_SEG_DBL_CUBICTO : SERIAL_SEG_FLT_CUBICTO); break; case SEG_CLOSE: npoints = 0; serialtype = SERIAL_SEG_CLOSE; break; default: // Should never happen throw new InternalError("unrecognized path type"); } s.writeByte(serialtype); while (npoints >= 0) { if (isdbl) { s.writeDouble(dCoords[cindex++]); s.writeDouble(dCoords[cindex++]); } else { s.writeFloat(fCoords[cindex++]); s.writeFloat(fCoords[cindex++]); } } } s.writeByte((byte) SERIAL_PATH_END); } 