/*
* @(#)GeneralPath.java 1.54 00/02/02
*
* Copyright 1996-2000 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the proprietary information of Sun Microsystems, Inc.
* Use is subject to license terms.
*
*/
package math.geom2d.curve;
import math.geom2d.Point2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator;
import java.awt.Shape;
/**
* The GeneralPath class represents a geometric path constructed
* from straight lines, and quadratic and cubic (Bezier) curves. It can contain
* multiple subpaths.
*
* The winding rule specifies how the interior of a path is determined. There
* are two types of winding rules: EVEN_ODD and NON_ZERO.
*
* An EVEN_ODD winding rule means that enclosed regions of the path alternate
* between interior and exterior areas as traversed from the outside of the path
* towards a point inside the region.
*
* A NON_ZERO winding rule means that if a ray is drawn in any direction from a
* given point to infinity and the places where the path intersects the ray are
* examined, the point is inside of the path if and only if the number of times
* that the path crosses the ray from left to right does not equal the number of
* times that the path crosses the ray from right to left.
*
* @version 1.54, 02/02/00
* @author Jim Graham
*/
public final class GeneralPath2D implements Shape, Cloneable {
GeneralPath path;
/**
* An even-odd winding rule for determining the interior of a path.
*/
public static final int WIND_EVEN_ODD = PathIterator.WIND_EVEN_ODD;
/**
* A non-zero winding rule for determining the interior of a path.
*/
public static final int WIND_NON_ZERO = PathIterator.WIND_NON_ZERO;
/**
* Constructs a new GeneralPath object. If an operation
* performed on this path requires the interior of the path to be defined
* then the default NON_ZERO winding rule is used.
*
* @see #WIND_NON_ZERO
*/
public GeneralPath2D() {
path = new GeneralPath();
}
/**
* Constructs a new GeneralPath object with the specified
* winding rule to control operations that require the interior of the path
* to be defined.
*
* @param rule the winding rule
* @see #WIND_EVEN_ODD
* @see #WIND_NON_ZERO
*/
public GeneralPath2D(int rule) {
path = new GeneralPath(rule);
}
/**
* Constructs a new GeneralPath object with the specified
* winding rule and the specified initial capacity to store path
* coordinates. This number is an initial guess as to how many path segments
* are in the path, but the storage is expanded as needed to store whatever
* path segments are added to this path.
*
* @param rule the winding rule
* @param initialCapacity the estimate for the number of path segments in
* the path
* @see #WIND_EVEN_ODD
* @see #WIND_NON_ZERO
*/
public GeneralPath2D(int rule, int initialCapacity) {
path = new GeneralPath(rule, initialCapacity);
}
/**
* Constructs a new GeneralPath object from an arbitrary
* {@link Shape} object. All of the initial geometry and the winding rule
* for this path are taken from the specified Shape object.
*
* @param s the specified Shape object
*/
public GeneralPath2D(Shape s) {
path = new GeneralPath(s);
}
/**
* Adds a point to the path by moving to the specified coordinates.
*
* @param x the x-coordinate of the destination
* @param y the y-coordinate of the destination
*/
public synchronized void moveTo(double x, double y) {
path.moveTo((float) x, (float) y);
}
/**
* Adds a point to the path by moving to the specified coordinates.
*
* @param p the specified point
*/
public synchronized void moveTo(Point2D p) {
path.moveTo((float) p.x(), (float) p.y());
}
/**
* Adds a point to the path by drawing a straight line from the current
* coordinates to the new specified coordinates.
*
* @param x the x-coordinate of the destination
* @param y the y-coordinate of the destination
*/
public synchronized void lineTo(double x, double y) {
path.lineTo((float) x, (float) y);
}
/**
* Adds a point to the path by drawing a straight line from the current
* coordinates to the new specified coordinates.
*
* @param p the coordinate of the destionation point
*/
public synchronized void lineTo(Point2D p) {
path.lineTo((float) p.x(), (float) p.y());
}
/**
* Adds a curved segment, defined by two new points, to the path by drawing
* a Quadratic curve that intersects both the current coordinates and the
* coordinates (x2, y2), using the specified point (x1, y1) as a
* quadratic parametric control point.
*
* @param x1 the x-coordinate of the control point
* @param y1 the y-coordinate of the control point
* @param x2 the x-coordinate of the end point
* @param y2 the y-coordinate of the end point
*/
public synchronized void quadTo(double x1, double y1, double x2, double y2) {
path.quadTo((float) x1, (float) y1, (float) x2, (float) y2);
}
/**
* Adds a curved segment, defined by two new points, to the path by drawing
* a Quadratic curve that intersects both the current coordinates and the
* coordinates (x2, y2), using the specified point (x1, y1) as a
* quadratic parametric control point.
*
* @param p1 the control point
* @param p2 the end point
*/
public synchronized void quadTo(Point2D p1, Point2D p2) {
path.quadTo((float) p1.x(), (float) p1.y(), (float) p2.x(),
(float) p2.y());
}
/**
* Adds a curved segment, defined by three new points, to the path by
* drawing a Bezier curve that intersects both the current coordinates and
* the coordinates (x3, y3), using the specified points (x1, y1)
* and (x2, y2) as Bezier control points.
*
* @param x1 the x-coordinate of the first control point
* @param y1 the y-coordinate of the first control point
* @param x2 the x-coordinate of the second control point
* @param y2 the y-coordinate of the second control point
* @param x3 the x-coordinate of the end point
* @param y3 the y-coordinate of the end point
*/
public synchronized void curveTo(double x1, double y1, double x2,
double y2, double x3, double y3) {
path.curveTo((float) x1, (float) y1, (float) x2, (float) y2,
(float) x3, (float) y3);
}
/**
* Adds a curved segment, defined by three new points, to the path by
* drawing a Bezier curve that intersects both the current coordinates and
* the coordinates (x3, y3), using the specified points (x1, y1)
* and (x2, y2) as Bezier control points.
*
* @param p1 the coordinates of the first control point
* @param p2 the coordinates of the second control point
* @param p3 the coordinates of the final endpoint
*/
public synchronized void curveTo(Point2D p1,
Point2D p2, Point2D p3) {
path.curveTo((float) p1.x(), (float) p1.y(), (float) p2.x(),
(float) p2.y(), (float) p3.x(), (float) p3.y());
}
/**
* Closes the current subpath by drawing a straight line back to the
* coordinates of the last moveTo. If the path is already
* closed then this method has no effect.
*/
public synchronized void closePath() {
path.closePath();
}
/**
* Appends the geometry of the specified Shape object to the
* path, possibly connecting the new geometry to the existing path segments
* with a line segment. If the connect parameter is
* true and the path is not empty then any initial
* moveTo in the geometry of the appended Shape
* is turned into a lineTo segment. If the destination
* coordinates of such a connecting lineTo segment match the
* ending coordinates of a currently open subpath then the segment is
* omitted as superfluous. The winding rule of the specified
* Shape is ignored and the appended geometry is governed by
* the winding rule specified for this path.
*
* @param s the Shape whose geometry is appended to this path
* @param connect a boolean to control whether or not to turn an initial
* moveTo segment into a lineTo
* segment to connect the new geometry to the existing path
*/
public void append(Shape s, boolean connect) {
path.append(s, connect);
}
/**
* 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 connect parameter is
* true and the path is not empty then any initial
* moveTo in the geometry of the appended Shape
* is turned into a lineTo segment. If the destination
* coordinates of such a connecting lineTo segment match the
* ending coordinates of a currently open subpath then the segment is
* omitted as superfluous. The winding rule of the specified
* Shape is ignored and the appended geometry is governed by
* the winding rule specified for this path.
*
* @param pi the PathIterator whose geometry is appended to
* this path
* @param connect a boolean to control whether or not to turn an initial
* moveTo segment into a lineTo
* segment to connect the new geometry to the existing path
*/
public void append(PathIterator pi, boolean connect) {
path.append(pi, connect);
}
/**
* Returns the fill style winding rule.
*
* @return an integer representing the current winding rule.
* @see #WIND_EVEN_ODD
* @see #WIND_NON_ZERO
*/
public synchronized int getWindingRule() {
return path.getWindingRule();
}
/**
* Sets the winding rule for this path to the specified value.
*
* @param rule an integer representing the specified winding rule
* @exception IllegalArgumentException if rule
* is not either WIND_EVEN_ODD or
* WIND_NON_ZERO
* @see #WIND_EVEN_ODD
* @see #WIND_NON_ZERO
*/
public void setWindingRule(int rule) {
path.setWindingRule(rule);
}
/**
* Returns the coordinates most recently added to the end of the path as a
* {@link Point2D} object.
*
* @return a Point2D object containing the ending coordinates
* of the path or null if there are no points in the
* path.
*/
public synchronized Point2D getCurrentPoint() {
return new Point2D(path.getCurrentPoint());
}
/**
* Resets the path to empty. The append position is set back to the
* beginning of the path and all coordinates and point types are forgotten.
*/
public synchronized void reset() {
path.reset();
}
/**
* Transforms the geometry of this path using the specified
* {@link AffineTransform}. The geometry is transformed in place, which
* permanently changes the boundary defined by this object.
*
* @param at the AffineTransform used to transform the area
*/
public void transform(AffineTransform at) {
path.transform(at);
}
/**
* Returns a new transformed Shape.
*
* @param at the AffineTransform used to transform a new
* Shape.
* @return a new Shape, transformed with the specified
* AffineTransform.
*/
public synchronized Shape createTransformedShape(AffineTransform at) {
return path.createTransformedShape(at);
}
/**
* Return the bounding box of the path.
*
* @return a {@link java.awt.Rectangle} object that bounds the current path.
*/
public java.awt.Rectangle getBounds() {
return path.getBounds();
}
/**
* Returns the bounding box of the path.
*
* @return a {@link math.geom2d.polygon.Rectangle2D} object that bounds the current path.
*/
public synchronized java.awt.geom.Rectangle2D getBounds2D() {
return path.getBounds2D();
}
/**
* Tests if the specified coordinates are inside the boundary of this
* Shape.
*
* @param x the x-coordinate of the point
* @param y the y-coordinate of the point
* @return true if the specified coordinates are inside this
* Shape; false otherwise
*/
public boolean contains(double x, double y) {
return path.contains(x, y);
}
/**
* Tests if the specified Point2D is inside the boundary of
* this Shape.
*
* @param p the specified Point2D
* @return true if this Shape contains the
* specified Point2D, false
* otherwise.
*/
public boolean contains(java.awt.geom.Point2D p) {
return path.contains(new java.awt.Point.Double(p.getX(), p.getY()));
}
/**
* Tests if the specified Point2D is inside the boundary of
* this Shape.
*
* @param p the specified Point2D
* @return true if this Shape contains the
* specified Point2D, false
* otherwise.
*/
public boolean contains(Point2D p) {
return path.contains(new java.awt.Point.Double(p.x(), p.y()));
}
/**
* Tests if the specified rectangular area is inside the boundary of this
* Shape.
*
* @param x the x coordinate of the rectangle
* @param y the y coordinate of the rectangle
* @param w the width of the specified rectangular area
* @param h the height of the specified rectangular area
* @return true if this Shape contains the
* specified rectangluar area; false otherwise.
*/
public boolean contains(double x, double y, double w, double h) {
return path.contains(x, y, w, h);
}
/**
* Tests if the specified Rectangle2D is inside the boundary
* of this Shape.
*
* @param r a specified Rectangle2D
* @return true if this Shape bounds the
* specified Rectangle2D; false
* otherwise.
*/
public boolean contains(java.awt.geom.Rectangle2D r) {
return path.contains(r);
}
/**
* Tests if the interior of this Shape intersects the
* interior of a specified set of rectangular coordinates.
*
* @param x the position of the left corner
* @param y the position of the bottom corner
* @param w the width of the specified rectangular coordinates
* @param h the height of the specified rectangular coordinates
* @return true if this Shape and the interior
* of the specified set of rectangular coordinates intersect each
* other; false otherwise.
*/
public boolean intersects(double x, double y, double w, double h) {
return path.intersects(x, y, w, h);
}
/**
* Tests if the interior of this Shape intersects the
* interior of a specified Rectangle2D.
*
* @param r the specified Rectangle2D
* @return true if this Shape and the interior
* of the specified Rectangle2D intersect each other;
* false otherwise.
*/
public boolean intersects(java.awt.geom.Rectangle2D r) {
return path.intersects(r);
}
/**
* Returns a PathIterator object that iterates along the
* boundary of this Shape and provides access to the geometry
* of the outline of this Shape. The iterator for this class
* is not multi-threaded safe, which means that this
* GeneralPath class does not guarantee that modifications to
* the geometry of this GeneralPath object do not affect any
* iterations of that geometry that are already in process.
*
* @param at an AffineTransform
* @return a new PathIterator that iterates along the
* boundary of this Shape and provides access to the
* geometry of this Shape's outline
*/
public PathIterator getPathIterator(AffineTransform at) {
return path.getPathIterator(at);
}
/**
* Returns a PathIterator object that iterates along the
* boundary of the flattened Shape and provides access to the
* geometry of the outline of the Shape. The iterator for
* this class is not multi-threaded safe, which means that this
* GeneralPath class does not guarantee that modifications to
* the geometry of this GeneralPath object do not affect any
* iterations of that geometry that are already in process.
*
* @param at an AffineTransform
* @param flatness the maximum distance that the line segments used to
* approximate the curved segments are allowed to deviate from
* any point on the original curve
* @return a new PathIterator that iterates along the
* flattened Shape boundary.
*/
public PathIterator getPathIterator(AffineTransform at, double flatness) {
return path.getPathIterator(at, flatness);
}
@Override
public boolean equals(Object obj) {
// check class, and cast type
if (!(obj instanceof GeneralPath2D))
return false;
GeneralPath2D that = (GeneralPath2D) obj;
return this.path.equals(that.path);
}
/**
* @deprecated use copy constructor instead (0.11.2)
*/
@Deprecated
@Override
public Object clone() {
return path.clone();
}
}
Ads help maintain this website.