< prev index next >

src/java.desktop/share/classes/java/awt/geom/CubicCurve2D.java

Print this page




  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.awt.geom;
  27 
  28 import java.awt.Shape;
  29 import java.awt.Rectangle;
  30 import java.util.Arrays;
  31 import java.io.Serializable;
  32 import sun.awt.geom.Curve;
  33 
  34 import static java.lang.Math.abs;
  35 import static java.lang.Math.max;
  36 import static java.lang.Math.ulp;
  37 
  38 /**
  39  * The <code>CubicCurve2D</code> class defines a cubic parametric curve
  40  * segment in {@code (x,y)} coordinate space.
  41  * <p>
  42  * This class is only the abstract superclass for all objects which
  43  * store a 2D cubic curve segment.
  44  * The actual storage representation of the coordinates is left to
  45  * the subclass.
  46  *
  47  * @author      Jim Graham
  48  * @since 1.2
  49  */
  50 public abstract class CubicCurve2D implements Shape, Cloneable {
  51 
  52     /**
  53      * A cubic parametric curve segment specified with
  54      * {@code float} coordinates.
  55      * @since 1.2
  56      */
  57     public static class Float extends CubicCurve2D implements Serializable {
  58         /**
  59          * The X coordinate of the start point


 705      * @param ctrlx2 the X coordinate used to set the second control point
 706      *               of this {@code CubicCurve2D}
 707      * @param ctrly2 the Y coordinate used to set the second control point
 708      *               of this {@code CubicCurve2D}
 709      * @param x2 the X coordinate used to set the end point
 710      *           of this {@code CubicCurve2D}
 711      * @param y2 the Y coordinate used to set the end point
 712      *           of this {@code CubicCurve2D}
 713      * @since 1.2
 714      */
 715     public abstract void setCurve(double x1, double y1,
 716                                   double ctrlx1, double ctrly1,
 717                                   double ctrlx2, double ctrly2,
 718                                   double x2, double y2);
 719 
 720     /**
 721      * Sets the location of the end points and control points of this curve
 722      * to the double coordinates at the specified offset in the specified
 723      * array.
 724      * @param coords a double array containing coordinates
 725      * @param offset the index of <code>coords</code> from which to begin
 726      *          setting the end points and control points of this curve
 727      *          to the coordinates contained in <code>coords</code>
 728      * @since 1.2
 729      */
 730     public void setCurve(double[] coords, int offset) {
 731         setCurve(coords[offset + 0], coords[offset + 1],
 732                  coords[offset + 2], coords[offset + 3],
 733                  coords[offset + 4], coords[offset + 5],
 734                  coords[offset + 6], coords[offset + 7]);
 735     }
 736 
 737     /**
 738      * Sets the location of the end points and control points of this curve
 739      * to the specified <code>Point2D</code> coordinates.
 740      * @param p1 the first specified <code>Point2D</code> used to set the
 741      *          start point of this curve
 742      * @param cp1 the second specified <code>Point2D</code> used to set the
 743      *          first control point of this curve
 744      * @param cp2 the third specified <code>Point2D</code> used to set the
 745      *          second control point of this curve
 746      * @param p2 the fourth specified <code>Point2D</code> used to set the
 747      *          end point of this curve
 748      * @since 1.2
 749      */
 750     public void setCurve(Point2D p1, Point2D cp1, Point2D cp2, Point2D p2) {
 751         setCurve(p1.getX(), p1.getY(), cp1.getX(), cp1.getY(),
 752                  cp2.getX(), cp2.getY(), p2.getX(), p2.getY());
 753     }
 754 
 755     /**
 756      * Sets the location of the end points and control points of this curve
 757      * to the coordinates of the <code>Point2D</code> objects at the specified
 758      * offset in the specified array.
 759      * @param pts an array of <code>Point2D</code> objects
 760      * @param offset  the index of <code>pts</code> from which to begin setting
 761      *          the end points and control points of this curve to the
 762      *          points contained in <code>pts</code>
 763      * @since 1.2
 764      */
 765     public void setCurve(Point2D[] pts, int offset) {
 766         setCurve(pts[offset + 0].getX(), pts[offset + 0].getY(),
 767                  pts[offset + 1].getX(), pts[offset + 1].getY(),
 768                  pts[offset + 2].getX(), pts[offset + 2].getY(),
 769                  pts[offset + 3].getX(), pts[offset + 3].getY());
 770     }
 771 
 772     /**
 773      * Sets the location of the end points and control points of this curve
 774      * to the same as those in the specified <code>CubicCurve2D</code>.
 775      * @param c the specified <code>CubicCurve2D</code>
 776      * @since 1.2
 777      */
 778     public void setCurve(CubicCurve2D c) {
 779         setCurve(c.getX1(), c.getY1(), c.getCtrlX1(), c.getCtrlY1(),
 780                  c.getCtrlX2(), c.getCtrlY2(), c.getX2(), c.getY2());
 781     }
 782 
 783     /**
 784      * Returns the square of the flatness of the cubic curve specified
 785      * by the indicated control points. The flatness is the maximum distance
 786      * of a control point from the line connecting the end points.
 787      *
 788      * @param x1 the X coordinate that specifies the start point
 789      *           of a {@code CubicCurve2D}
 790      * @param y1 the Y coordinate that specifies the start point
 791      *           of a {@code CubicCurve2D}
 792      * @param ctrlx1 the X coordinate that specifies the first control point
 793      *               of a {@code CubicCurve2D}
 794      * @param ctrly1 the Y coordinate that specifies the first control point
 795      *               of a {@code CubicCurve2D}


 836      * @param y2 the Y coordinate that specifies the end point
 837      *           of a {@code CubicCurve2D}
 838      * @return the flatness of the {@code CubicCurve2D}
 839      *          represented by the specified coordinates.
 840      * @since 1.2
 841      */
 842     public static double getFlatness(double x1, double y1,
 843                                      double ctrlx1, double ctrly1,
 844                                      double ctrlx2, double ctrly2,
 845                                      double x2, double y2) {
 846         return Math.sqrt(getFlatnessSq(x1, y1, ctrlx1, ctrly1,
 847                                        ctrlx2, ctrly2, x2, y2));
 848     }
 849 
 850     /**
 851      * Returns the square of the flatness of the cubic curve specified
 852      * by the control points stored in the indicated array at the
 853      * indicated index. The flatness is the maximum distance
 854      * of a control point from the line connecting the end points.
 855      * @param coords an array containing coordinates
 856      * @param offset the index of <code>coords</code> from which to begin
 857      *          getting the end points and control points of the curve
 858      * @return the square of the flatness of the <code>CubicCurve2D</code>
 859      *          specified by the coordinates in <code>coords</code> at
 860      *          the specified offset.
 861      * @since 1.2
 862      */
 863     public static double getFlatnessSq(double coords[], int offset) {
 864         return getFlatnessSq(coords[offset + 0], coords[offset + 1],
 865                              coords[offset + 2], coords[offset + 3],
 866                              coords[offset + 4], coords[offset + 5],
 867                              coords[offset + 6], coords[offset + 7]);
 868     }
 869 
 870     /**
 871      * Returns the flatness of the cubic curve specified
 872      * by the control points stored in the indicated array at the
 873      * indicated index.  The flatness is the maximum distance
 874      * of a control point from the line connecting the end points.
 875      * @param coords an array containing coordinates
 876      * @param offset the index of <code>coords</code> from which to begin
 877      *          getting the end points and control points of the curve
 878      * @return the flatness of the <code>CubicCurve2D</code>
 879      *          specified by the coordinates in <code>coords</code> at
 880      *          the specified offset.
 881      * @since 1.2
 882      */
 883     public static double getFlatness(double coords[], int offset) {
 884         return getFlatness(coords[offset + 0], coords[offset + 1],
 885                            coords[offset + 2], coords[offset + 3],
 886                            coords[offset + 4], coords[offset + 5],
 887                            coords[offset + 6], coords[offset + 7]);
 888     }
 889 
 890     /**
 891      * Returns the square of the flatness of this curve.  The flatness is the
 892      * maximum distance of a control point from the line connecting the
 893      * end points.
 894      * @return the square of the flatness of this curve.
 895      * @since 1.2
 896      */
 897     public double getFlatnessSq() {
 898         return getFlatnessSq(getX1(), getY1(), getCtrlX1(), getCtrlY1(),
 899                              getCtrlX2(), getCtrlY2(), getX2(), getY2());


 910         return getFlatness(getX1(), getY1(), getCtrlX1(), getCtrlY1(),
 911                            getCtrlX2(), getCtrlY2(), getX2(), getY2());
 912     }
 913 
 914     /**
 915      * Subdivides this cubic curve and stores the resulting two
 916      * subdivided curves into the left and right curve parameters.
 917      * Either or both of the left and right objects may be the same
 918      * as this object or null.
 919      * @param left the cubic curve object for storing for the left or
 920      * first half of the subdivided curve
 921      * @param right the cubic curve object for storing for the right or
 922      * second half of the subdivided curve
 923      * @since 1.2
 924      */
 925     public void subdivide(CubicCurve2D left, CubicCurve2D right) {
 926         subdivide(this, left, right);
 927     }
 928 
 929     /**
 930      * Subdivides the cubic curve specified by the <code>src</code> parameter
 931      * and stores the resulting two subdivided curves into the
 932      * <code>left</code> and <code>right</code> curve parameters.
 933      * Either or both of the <code>left</code> and <code>right</code> objects
 934      * may be the same as the <code>src</code> object or <code>null</code>.
 935      * @param src the cubic curve to be subdivided
 936      * @param left the cubic curve object for storing the left or
 937      * first half of the subdivided curve
 938      * @param right the cubic curve object for storing the right or
 939      * second half of the subdivided curve
 940      * @since 1.2
 941      */
 942     public static void subdivide(CubicCurve2D src,
 943                                  CubicCurve2D left,
 944                                  CubicCurve2D right) {
 945         double x1 = src.getX1();
 946         double y1 = src.getY1();
 947         double ctrlx1 = src.getCtrlX1();
 948         double ctrly1 = src.getCtrlY1();
 949         double ctrlx2 = src.getCtrlX2();
 950         double ctrly2 = src.getCtrlY2();
 951         double x2 = src.getX2();
 952         double y2 = src.getY2();
 953         double centerx = (ctrlx1 + ctrlx2) / 2.0;
 954         double centery = (ctrly1 + ctrly2) / 2.0;


 957         ctrlx2 = (x2 + ctrlx2) / 2.0;
 958         ctrly2 = (y2 + ctrly2) / 2.0;
 959         double ctrlx12 = (ctrlx1 + centerx) / 2.0;
 960         double ctrly12 = (ctrly1 + centery) / 2.0;
 961         double ctrlx21 = (ctrlx2 + centerx) / 2.0;
 962         double ctrly21 = (ctrly2 + centery) / 2.0;
 963         centerx = (ctrlx12 + ctrlx21) / 2.0;
 964         centery = (ctrly12 + ctrly21) / 2.0;
 965         if (left != null) {
 966             left.setCurve(x1, y1, ctrlx1, ctrly1,
 967                           ctrlx12, ctrly12, centerx, centery);
 968         }
 969         if (right != null) {
 970             right.setCurve(centerx, centery, ctrlx21, ctrly21,
 971                            ctrlx2, ctrly2, x2, y2);
 972         }
 973     }
 974 
 975     /**
 976      * Subdivides the cubic curve specified by the coordinates
 977      * stored in the <code>src</code> array at indices <code>srcoff</code>
 978      * through (<code>srcoff</code>&nbsp;+&nbsp;7) and stores the
 979      * resulting two subdivided curves into the two result arrays at the
 980      * corresponding indices.
 981      * Either or both of the <code>left</code> and <code>right</code>
 982      * arrays may be <code>null</code> or a reference to the same array
 983      * as the <code>src</code> array.
 984      * Note that the last point in the first subdivided curve is the
 985      * same as the first point in the second subdivided curve. Thus,
 986      * it is possible to pass the same array for <code>left</code>
 987      * and <code>right</code> and to use offsets, such as <code>rightoff</code>
 988      * equals (<code>leftoff</code> + 6), in order
 989      * to avoid allocating extra storage for this common point.
 990      * @param src the array holding the coordinates for the source curve
 991      * @param srcoff the offset into the array of the beginning of the
 992      * the 6 source coordinates
 993      * @param left the array for storing the coordinates for the first
 994      * half of the subdivided curve
 995      * @param leftoff the offset into the array of the beginning of the
 996      * the 6 left coordinates
 997      * @param right the array for storing the coordinates for the second
 998      * half of the subdivided curve
 999      * @param rightoff the offset into the array of the beginning of the
1000      * the 6 right coordinates
1001      * @since 1.2
1002      */
1003     public static void subdivide(double src[], int srcoff,
1004                                  double left[], int leftoff,
1005                                  double right[], int rightoff) {
1006         double x1 = src[srcoff + 0];
1007         double y1 = src[srcoff + 1];
1008         double ctrlx1 = src[srcoff + 2];


1033         centery = (ctrly1 + ctrly2) / 2.0;
1034         if (left != null) {
1035             left[leftoff + 2] = x1;
1036             left[leftoff + 3] = y1;
1037             left[leftoff + 4] = ctrlx1;
1038             left[leftoff + 5] = ctrly1;
1039             left[leftoff + 6] = centerx;
1040             left[leftoff + 7] = centery;
1041         }
1042         if (right != null) {
1043             right[rightoff + 0] = centerx;
1044             right[rightoff + 1] = centery;
1045             right[rightoff + 2] = ctrlx2;
1046             right[rightoff + 3] = ctrly2;
1047             right[rightoff + 4] = x2;
1048             right[rightoff + 5] = y2;
1049         }
1050     }
1051 
1052     /**
1053      * Solves the cubic whose coefficients are in the <code>eqn</code>
1054      * array and places the non-complex roots back into the same array,
1055      * returning the number of roots.  The solved cubic is represented
1056      * by the equation:
1057      * <pre>
1058      *     eqn = {c, b, a, d}
1059      *     dx^3 + ax^2 + bx + c = 0
1060      * </pre>
1061      * A return value of -1 is used to distinguish a constant equation
1062      * that might be always 0 or never 0 from an equation that has no
1063      * zeroes.
1064      * @param eqn an array containing coefficients for a cubic
1065      * @return the number of roots, or -1 if the equation is a constant.
1066      * @since 1.2
1067      */
1068     public static int solveCubic(double eqn[]) {
1069         return solveCubic(eqn, eqn);
1070     }
1071 
1072     /**
1073      * Solve the cubic whose coefficients are in the <code>eqn</code>
1074      * array and place the non-complex roots into the <code>res</code>
1075      * array, returning the number of roots.
1076      * The cubic solved is represented by the equation:
1077      *     eqn = {c, b, a, d}
1078      *     dx^3 + ax^2 + bx + c = 0
1079      * A return value of -1 is used to distinguish a constant equation,
1080      * which may be always 0 or never 0, from an equation which has no
1081      * zeroes.
1082      * @param eqn the specified array of coefficients to use to solve
1083      *        the cubic equation
1084      * @param res the array that contains the non-complex roots
1085      *        resulting from the solution of the cubic equation
1086      * @return the number of roots, or -1 if the equation is a constant
1087      * @since 1.3
1088      */
1089     public static int solveCubic(double eqn[], double res[]) {
1090         // From Graphics Gems:
1091         // http://tog.acm.org/resources/GraphicsGems/gems/Roots3And4.c
1092         final double d = eqn[3];
1093         if (d == 0) {
1094             return QuadCurve2D.solveQuadratic(eqn, res);


1500     /**
1501      * {@inheritDoc}
1502      * @since 1.2
1503      */
1504     public boolean contains(Rectangle2D r) {
1505         return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
1506     }
1507 
1508     /**
1509      * {@inheritDoc}
1510      * @since 1.2
1511      */
1512     public Rectangle getBounds() {
1513         return getBounds2D().getBounds();
1514     }
1515 
1516     /**
1517      * Returns an iteration object that defines the boundary of the
1518      * shape.
1519      * The iterator for this class is not multi-threaded safe,
1520      * which means that this <code>CubicCurve2D</code> class does not
1521      * guarantee that modifications to the geometry of this
1522      * <code>CubicCurve2D</code> object do not affect any iterations of
1523      * that geometry that are already in process.
1524      * @param at an optional <code>AffineTransform</code> to be applied to the
1525      * coordinates as they are returned in the iteration, or <code>null</code>
1526      * if untransformed coordinates are desired
1527      * @return    the <code>PathIterator</code> object that returns the
1528      *          geometry of the outline of this <code>CubicCurve2D</code>, one
1529      *          segment at a time.
1530      * @since 1.2
1531      */
1532     public PathIterator getPathIterator(AffineTransform at) {
1533         return new CubicIterator(this, at);
1534     }
1535 
1536     /**
1537      * Return an iteration object that defines the boundary of the
1538      * flattened shape.
1539      * The iterator for this class is not multi-threaded safe,
1540      * which means that this <code>CubicCurve2D</code> class does not
1541      * guarantee that modifications to the geometry of this
1542      * <code>CubicCurve2D</code> object do not affect any iterations of
1543      * that geometry that are already in process.
1544      * @param at an optional <code>AffineTransform</code> to be applied to the
1545      * coordinates as they are returned in the iteration, or <code>null</code>
1546      * if untransformed coordinates are desired
1547      * @param flatness the maximum amount that the control points
1548      * for a given curve can vary from colinear before a subdivided
1549      * curve is replaced by a straight line connecting the end points
1550      * @return    the <code>PathIterator</code> object that returns the
1551      * geometry of the outline of this <code>CubicCurve2D</code>,
1552      * one segment at a time.
1553      * @since 1.2
1554      */
1555     public PathIterator getPathIterator(AffineTransform at, double flatness) {
1556         return new FlatteningPathIterator(getPathIterator(at), flatness);
1557     }
1558 
1559     /**
1560      * Creates a new object of the same class as this object.
1561      *
1562      * @return     a clone of this instance.
1563      * @exception  OutOfMemoryError            if there is not enough memory.
1564      * @see        java.lang.Cloneable
1565      * @since      1.2
1566      */
1567     public Object clone() {
1568         try {
1569             return super.clone();
1570         } catch (CloneNotSupportedException e) {
1571             // this shouldn't happen, since we are Cloneable


  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.awt.geom;
  27 
  28 import java.awt.Shape;
  29 import java.awt.Rectangle;
  30 import java.util.Arrays;
  31 import java.io.Serializable;
  32 import sun.awt.geom.Curve;
  33 
  34 import static java.lang.Math.abs;
  35 import static java.lang.Math.max;
  36 import static java.lang.Math.ulp;
  37 
  38 /**
  39  * The {@code CubicCurve2D} class defines a cubic parametric curve
  40  * segment in {@code (x,y)} coordinate space.
  41  * <p>
  42  * This class is only the abstract superclass for all objects which
  43  * store a 2D cubic curve segment.
  44  * The actual storage representation of the coordinates is left to
  45  * the subclass.
  46  *
  47  * @author      Jim Graham
  48  * @since 1.2
  49  */
  50 public abstract class CubicCurve2D implements Shape, Cloneable {
  51 
  52     /**
  53      * A cubic parametric curve segment specified with
  54      * {@code float} coordinates.
  55      * @since 1.2
  56      */
  57     public static class Float extends CubicCurve2D implements Serializable {
  58         /**
  59          * The X coordinate of the start point


 705      * @param ctrlx2 the X coordinate used to set the second control point
 706      *               of this {@code CubicCurve2D}
 707      * @param ctrly2 the Y coordinate used to set the second control point
 708      *               of this {@code CubicCurve2D}
 709      * @param x2 the X coordinate used to set the end point
 710      *           of this {@code CubicCurve2D}
 711      * @param y2 the Y coordinate used to set the end point
 712      *           of this {@code CubicCurve2D}
 713      * @since 1.2
 714      */
 715     public abstract void setCurve(double x1, double y1,
 716                                   double ctrlx1, double ctrly1,
 717                                   double ctrlx2, double ctrly2,
 718                                   double x2, double y2);
 719 
 720     /**
 721      * Sets the location of the end points and control points of this curve
 722      * to the double coordinates at the specified offset in the specified
 723      * array.
 724      * @param coords a double array containing coordinates
 725      * @param offset the index of {@code coords} from which to begin
 726      *          setting the end points and control points of this curve
 727      *          to the coordinates contained in {@code coords}
 728      * @since 1.2
 729      */
 730     public void setCurve(double[] coords, int offset) {
 731         setCurve(coords[offset + 0], coords[offset + 1],
 732                  coords[offset + 2], coords[offset + 3],
 733                  coords[offset + 4], coords[offset + 5],
 734                  coords[offset + 6], coords[offset + 7]);
 735     }
 736 
 737     /**
 738      * Sets the location of the end points and control points of this curve
 739      * to the specified {@code Point2D} coordinates.
 740      * @param p1 the first specified {@code Point2D} used to set the
 741      *          start point of this curve
 742      * @param cp1 the second specified {@code Point2D} used to set the
 743      *          first control point of this curve
 744      * @param cp2 the third specified {@code Point2D} used to set the
 745      *          second control point of this curve
 746      * @param p2 the fourth specified {@code Point2D} used to set the
 747      *          end point of this curve
 748      * @since 1.2
 749      */
 750     public void setCurve(Point2D p1, Point2D cp1, Point2D cp2, Point2D p2) {
 751         setCurve(p1.getX(), p1.getY(), cp1.getX(), cp1.getY(),
 752                  cp2.getX(), cp2.getY(), p2.getX(), p2.getY());
 753     }
 754 
 755     /**
 756      * Sets the location of the end points and control points of this curve
 757      * to the coordinates of the {@code Point2D} objects at the specified
 758      * offset in the specified array.
 759      * @param pts an array of {@code Point2D} objects
 760      * @param offset  the index of {@code pts} from which to begin setting
 761      *          the end points and control points of this curve to the
 762      *          points contained in {@code pts}
 763      * @since 1.2
 764      */
 765     public void setCurve(Point2D[] pts, int offset) {
 766         setCurve(pts[offset + 0].getX(), pts[offset + 0].getY(),
 767                  pts[offset + 1].getX(), pts[offset + 1].getY(),
 768                  pts[offset + 2].getX(), pts[offset + 2].getY(),
 769                  pts[offset + 3].getX(), pts[offset + 3].getY());
 770     }
 771 
 772     /**
 773      * Sets the location of the end points and control points of this curve
 774      * to the same as those in the specified {@code CubicCurve2D}.
 775      * @param c the specified {@code CubicCurve2D}
 776      * @since 1.2
 777      */
 778     public void setCurve(CubicCurve2D c) {
 779         setCurve(c.getX1(), c.getY1(), c.getCtrlX1(), c.getCtrlY1(),
 780                  c.getCtrlX2(), c.getCtrlY2(), c.getX2(), c.getY2());
 781     }
 782 
 783     /**
 784      * Returns the square of the flatness of the cubic curve specified
 785      * by the indicated control points. The flatness is the maximum distance
 786      * of a control point from the line connecting the end points.
 787      *
 788      * @param x1 the X coordinate that specifies the start point
 789      *           of a {@code CubicCurve2D}
 790      * @param y1 the Y coordinate that specifies the start point
 791      *           of a {@code CubicCurve2D}
 792      * @param ctrlx1 the X coordinate that specifies the first control point
 793      *               of a {@code CubicCurve2D}
 794      * @param ctrly1 the Y coordinate that specifies the first control point
 795      *               of a {@code CubicCurve2D}


 836      * @param y2 the Y coordinate that specifies the end point
 837      *           of a {@code CubicCurve2D}
 838      * @return the flatness of the {@code CubicCurve2D}
 839      *          represented by the specified coordinates.
 840      * @since 1.2
 841      */
 842     public static double getFlatness(double x1, double y1,
 843                                      double ctrlx1, double ctrly1,
 844                                      double ctrlx2, double ctrly2,
 845                                      double x2, double y2) {
 846         return Math.sqrt(getFlatnessSq(x1, y1, ctrlx1, ctrly1,
 847                                        ctrlx2, ctrly2, x2, y2));
 848     }
 849 
 850     /**
 851      * Returns the square of the flatness of the cubic curve specified
 852      * by the control points stored in the indicated array at the
 853      * indicated index. The flatness is the maximum distance
 854      * of a control point from the line connecting the end points.
 855      * @param coords an array containing coordinates
 856      * @param offset the index of {@code coords} from which to begin
 857      *          getting the end points and control points of the curve
 858      * @return the square of the flatness of the {@code CubicCurve2D}
 859      *          specified by the coordinates in {@code coords} at
 860      *          the specified offset.
 861      * @since 1.2
 862      */
 863     public static double getFlatnessSq(double coords[], int offset) {
 864         return getFlatnessSq(coords[offset + 0], coords[offset + 1],
 865                              coords[offset + 2], coords[offset + 3],
 866                              coords[offset + 4], coords[offset + 5],
 867                              coords[offset + 6], coords[offset + 7]);
 868     }
 869 
 870     /**
 871      * Returns the flatness of the cubic curve specified
 872      * by the control points stored in the indicated array at the
 873      * indicated index.  The flatness is the maximum distance
 874      * of a control point from the line connecting the end points.
 875      * @param coords an array containing coordinates
 876      * @param offset the index of {@code coords} from which to begin
 877      *          getting the end points and control points of the curve
 878      * @return the flatness of the {@code CubicCurve2D}
 879      *          specified by the coordinates in {@code coords} at
 880      *          the specified offset.
 881      * @since 1.2
 882      */
 883     public static double getFlatness(double coords[], int offset) {
 884         return getFlatness(coords[offset + 0], coords[offset + 1],
 885                            coords[offset + 2], coords[offset + 3],
 886                            coords[offset + 4], coords[offset + 5],
 887                            coords[offset + 6], coords[offset + 7]);
 888     }
 889 
 890     /**
 891      * Returns the square of the flatness of this curve.  The flatness is the
 892      * maximum distance of a control point from the line connecting the
 893      * end points.
 894      * @return the square of the flatness of this curve.
 895      * @since 1.2
 896      */
 897     public double getFlatnessSq() {
 898         return getFlatnessSq(getX1(), getY1(), getCtrlX1(), getCtrlY1(),
 899                              getCtrlX2(), getCtrlY2(), getX2(), getY2());


 910         return getFlatness(getX1(), getY1(), getCtrlX1(), getCtrlY1(),
 911                            getCtrlX2(), getCtrlY2(), getX2(), getY2());
 912     }
 913 
 914     /**
 915      * Subdivides this cubic curve and stores the resulting two
 916      * subdivided curves into the left and right curve parameters.
 917      * Either or both of the left and right objects may be the same
 918      * as this object or null.
 919      * @param left the cubic curve object for storing for the left or
 920      * first half of the subdivided curve
 921      * @param right the cubic curve object for storing for the right or
 922      * second half of the subdivided curve
 923      * @since 1.2
 924      */
 925     public void subdivide(CubicCurve2D left, CubicCurve2D right) {
 926         subdivide(this, left, right);
 927     }
 928 
 929     /**
 930      * Subdivides the cubic curve specified by the {@code src} parameter
 931      * and stores the resulting two subdivided curves into the
 932      * {@code left} and {@code right} curve parameters.
 933      * Either or both of the {@code left} and {@code right} objects
 934      * may be the same as the {@code src} object or {@code null}.
 935      * @param src the cubic curve to be subdivided
 936      * @param left the cubic curve object for storing the left or
 937      * first half of the subdivided curve
 938      * @param right the cubic curve object for storing the right or
 939      * second half of the subdivided curve
 940      * @since 1.2
 941      */
 942     public static void subdivide(CubicCurve2D src,
 943                                  CubicCurve2D left,
 944                                  CubicCurve2D right) {
 945         double x1 = src.getX1();
 946         double y1 = src.getY1();
 947         double ctrlx1 = src.getCtrlX1();
 948         double ctrly1 = src.getCtrlY1();
 949         double ctrlx2 = src.getCtrlX2();
 950         double ctrly2 = src.getCtrlY2();
 951         double x2 = src.getX2();
 952         double y2 = src.getY2();
 953         double centerx = (ctrlx1 + ctrlx2) / 2.0;
 954         double centery = (ctrly1 + ctrly2) / 2.0;


 957         ctrlx2 = (x2 + ctrlx2) / 2.0;
 958         ctrly2 = (y2 + ctrly2) / 2.0;
 959         double ctrlx12 = (ctrlx1 + centerx) / 2.0;
 960         double ctrly12 = (ctrly1 + centery) / 2.0;
 961         double ctrlx21 = (ctrlx2 + centerx) / 2.0;
 962         double ctrly21 = (ctrly2 + centery) / 2.0;
 963         centerx = (ctrlx12 + ctrlx21) / 2.0;
 964         centery = (ctrly12 + ctrly21) / 2.0;
 965         if (left != null) {
 966             left.setCurve(x1, y1, ctrlx1, ctrly1,
 967                           ctrlx12, ctrly12, centerx, centery);
 968         }
 969         if (right != null) {
 970             right.setCurve(centerx, centery, ctrlx21, ctrly21,
 971                            ctrlx2, ctrly2, x2, y2);
 972         }
 973     }
 974 
 975     /**
 976      * Subdivides the cubic curve specified by the coordinates
 977      * stored in the {@code src} array at indices {@code srcoff}
 978      * through ({@code srcoff}&nbsp;+&nbsp;7) and stores the
 979      * resulting two subdivided curves into the two result arrays at the
 980      * corresponding indices.
 981      * Either or both of the {@code left} and {@code right}
 982      * arrays may be {@code null} or a reference to the same array
 983      * as the {@code src} array.
 984      * Note that the last point in the first subdivided curve is the
 985      * same as the first point in the second subdivided curve. Thus,
 986      * it is possible to pass the same array for {@code left}
 987      * and {@code right} and to use offsets, such as {@code rightoff}
 988      * equals ({@code leftoff} + 6), in order
 989      * to avoid allocating extra storage for this common point.
 990      * @param src the array holding the coordinates for the source curve
 991      * @param srcoff the offset into the array of the beginning of the
 992      * the 6 source coordinates
 993      * @param left the array for storing the coordinates for the first
 994      * half of the subdivided curve
 995      * @param leftoff the offset into the array of the beginning of the
 996      * the 6 left coordinates
 997      * @param right the array for storing the coordinates for the second
 998      * half of the subdivided curve
 999      * @param rightoff the offset into the array of the beginning of the
1000      * the 6 right coordinates
1001      * @since 1.2
1002      */
1003     public static void subdivide(double src[], int srcoff,
1004                                  double left[], int leftoff,
1005                                  double right[], int rightoff) {
1006         double x1 = src[srcoff + 0];
1007         double y1 = src[srcoff + 1];
1008         double ctrlx1 = src[srcoff + 2];


1033         centery = (ctrly1 + ctrly2) / 2.0;
1034         if (left != null) {
1035             left[leftoff + 2] = x1;
1036             left[leftoff + 3] = y1;
1037             left[leftoff + 4] = ctrlx1;
1038             left[leftoff + 5] = ctrly1;
1039             left[leftoff + 6] = centerx;
1040             left[leftoff + 7] = centery;
1041         }
1042         if (right != null) {
1043             right[rightoff + 0] = centerx;
1044             right[rightoff + 1] = centery;
1045             right[rightoff + 2] = ctrlx2;
1046             right[rightoff + 3] = ctrly2;
1047             right[rightoff + 4] = x2;
1048             right[rightoff + 5] = y2;
1049         }
1050     }
1051 
1052     /**
1053      * Solves the cubic whose coefficients are in the {@code eqn}
1054      * array and places the non-complex roots back into the same array,
1055      * returning the number of roots.  The solved cubic is represented
1056      * by the equation:
1057      * <pre>
1058      *     eqn = {c, b, a, d}
1059      *     dx^3 + ax^2 + bx + c = 0
1060      * </pre>
1061      * A return value of -1 is used to distinguish a constant equation
1062      * that might be always 0 or never 0 from an equation that has no
1063      * zeroes.
1064      * @param eqn an array containing coefficients for a cubic
1065      * @return the number of roots, or -1 if the equation is a constant.
1066      * @since 1.2
1067      */
1068     public static int solveCubic(double eqn[]) {
1069         return solveCubic(eqn, eqn);
1070     }
1071 
1072     /**
1073      * Solve the cubic whose coefficients are in the {@code eqn}
1074      * array and place the non-complex roots into the {@code res}
1075      * array, returning the number of roots.
1076      * The cubic solved is represented by the equation:
1077      *     eqn = {c, b, a, d}
1078      *     dx^3 + ax^2 + bx + c = 0
1079      * A return value of -1 is used to distinguish a constant equation,
1080      * which may be always 0 or never 0, from an equation which has no
1081      * zeroes.
1082      * @param eqn the specified array of coefficients to use to solve
1083      *        the cubic equation
1084      * @param res the array that contains the non-complex roots
1085      *        resulting from the solution of the cubic equation
1086      * @return the number of roots, or -1 if the equation is a constant
1087      * @since 1.3
1088      */
1089     public static int solveCubic(double eqn[], double res[]) {
1090         // From Graphics Gems:
1091         // http://tog.acm.org/resources/GraphicsGems/gems/Roots3And4.c
1092         final double d = eqn[3];
1093         if (d == 0) {
1094             return QuadCurve2D.solveQuadratic(eqn, res);


1500     /**
1501      * {@inheritDoc}
1502      * @since 1.2
1503      */
1504     public boolean contains(Rectangle2D r) {
1505         return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
1506     }
1507 
1508     /**
1509      * {@inheritDoc}
1510      * @since 1.2
1511      */
1512     public Rectangle getBounds() {
1513         return getBounds2D().getBounds();
1514     }
1515 
1516     /**
1517      * Returns an iteration object that defines the boundary of the
1518      * shape.
1519      * The iterator for this class is not multi-threaded safe,
1520      * which means that this {@code CubicCurve2D} class does not
1521      * guarantee that modifications to the geometry of this
1522      * {@code CubicCurve2D} object do not affect any iterations of
1523      * that geometry that are already in process.
1524      * @param at an optional {@code AffineTransform} to be applied to the
1525      * coordinates as they are returned in the iteration, or {@code null}
1526      * if untransformed coordinates are desired
1527      * @return    the {@code PathIterator} object that returns the
1528      *          geometry of the outline of this {@code CubicCurve2D}, one
1529      *          segment at a time.
1530      * @since 1.2
1531      */
1532     public PathIterator getPathIterator(AffineTransform at) {
1533         return new CubicIterator(this, at);
1534     }
1535 
1536     /**
1537      * Return an iteration object that defines the boundary of the
1538      * flattened shape.
1539      * The iterator for this class is not multi-threaded safe,
1540      * which means that this {@code CubicCurve2D} class does not
1541      * guarantee that modifications to the geometry of this
1542      * {@code CubicCurve2D} object do not affect any iterations of
1543      * that geometry that are already in process.
1544      * @param at an optional {@code AffineTransform} to be applied to the
1545      * coordinates as they are returned in the iteration, or {@code null}
1546      * if untransformed coordinates are desired
1547      * @param flatness the maximum amount that the control points
1548      * for a given curve can vary from colinear before a subdivided
1549      * curve is replaced by a straight line connecting the end points
1550      * @return    the {@code PathIterator} object that returns the
1551      * geometry of the outline of this {@code CubicCurve2D},
1552      * one segment at a time.
1553      * @since 1.2
1554      */
1555     public PathIterator getPathIterator(AffineTransform at, double flatness) {
1556         return new FlatteningPathIterator(getPathIterator(at), flatness);
1557     }
1558 
1559     /**
1560      * Creates a new object of the same class as this object.
1561      *
1562      * @return     a clone of this instance.
1563      * @exception  OutOfMemoryError            if there is not enough memory.
1564      * @see        java.lang.Cloneable
1565      * @since      1.2
1566      */
1567     public Object clone() {
1568         try {
1569             return super.clone();
1570         } catch (CloneNotSupportedException e) {
1571             // this shouldn't happen, since we are Cloneable
< prev index next >