home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / 3rdParty / jbuilder / unsupported / JDK1.2beta3 / SOURCE / SRC.ZIP / java / awt / geom / QuadCurve2D.java < prev    next >
Encoding:
Java Source  |  1998-03-20  |  23.1 KB  |  813 lines

  1. /*
  2.  * @(#)QuadCurve2D.java    1.10 98/03/18
  3.  *
  4.  * Copyright 1997, 1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.awt.geom;
  16.  
  17. import java.awt.Shape;
  18. import java.awt.Rectangle;
  19.  
  20. /**
  21.  * A quadratic parametric curve segment in (x, y) coordinate space.
  22.  * <p>
  23.  * This class is only the abstract superclass for all objects which
  24.  * store a 2D quadratic curve segment.
  25.  * The actual storage representation of the coordinates is left to
  26.  * the subclass.
  27.  *
  28.  * @version 10 Feb 1997
  29.  * @author    Jim Graham
  30.  */
  31. public abstract class QuadCurve2D implements Shape, Cloneable {
  32.     /**
  33.      * A quadratic parametric curve segment specified with float coordinates.
  34.      */
  35.     public static class Float extends QuadCurve2D {
  36.     /**
  37.      * The X coordinate of the start point of the quadratic curve segment.
  38.      */
  39.     public float x1;
  40.  
  41.     /**
  42.      * The Y coordinate of the start point of the quadratic curve segment.
  43.      */
  44.     public float y1;
  45.  
  46.     /**
  47.      * The X coordinate of the control point of the quadratic curve segment.
  48.      */
  49.     public float ctrlx;
  50.  
  51.     /**
  52.      * The Y coordinate of the control point of the quadratic curve segment.
  53.      */
  54.     public float ctrly;
  55.  
  56.     /**
  57.      * The X coordinate of the end point of the quadratic curve segment.
  58.      */
  59.     public float x2;
  60.  
  61.     /**
  62.      * The Y coordinate of the end point of the quadratic curve segment.
  63.      */
  64.     public float y2;
  65.  
  66.     /**
  67.      * Constructs and initializes a QuadCurve with coordinates
  68.      * (0, 0, 0, 0, 0, 0).
  69.      */
  70.     public Float() {
  71.     }
  72.  
  73.     /**
  74.      * Constructs and initializes a QuadCurve from the specified coordinates.
  75.      */
  76.     public Float(float x1, float y1,
  77.              float ctrlx, float ctrly,
  78.              float x2, float y2) {
  79.         setCurve(x1, y1, ctrlx, ctrly, x2, y2);
  80.     }
  81.  
  82.     /**
  83.      * Returns the X coordinate of the start point in double precision.
  84.      */
  85.     public double getX1() {
  86.         return (double) x1;
  87.     }
  88.  
  89.     /**
  90.      * Returns the Y coordinate of the start point in double precision.
  91.      */
  92.     public double getY1() {
  93.         return (double) y1;
  94.     }
  95.  
  96.     /**
  97.      * Returns the X coordinate of the control point in double precision.
  98.      */
  99.     public double getCtrlX() {
  100.         return (double) ctrlx;
  101.     }
  102.  
  103.     /**
  104.      * Returns the Y coordinate of the control point in double precision.
  105.      */
  106.     public double getCtrlY() {
  107.         return (double) ctrly;
  108.     }
  109.  
  110.     /**
  111.      * Returns the X coordinate of the end point in double precision.
  112.      */
  113.     public double getX2() {
  114.         return (double) x2;
  115.     }
  116.  
  117.     /**
  118.      * Returns the Y coordinate of the end point in double precision.
  119.      */
  120.     public double getY2() {
  121.         return (double) y2;
  122.     }
  123.  
  124.     /**
  125.      * Sets the location of the endpoints and controlpoint of this curve
  126.      * to the specified double coordinates.
  127.      */
  128.     public void setCurve(double x1, double y1,
  129.                  double ctrlx, double ctrly,
  130.                  double x2, double y2) {
  131.         this.x1    = (float) x1;
  132.         this.y1    = (float) y1;
  133.         this.ctrlx = (float) ctrlx;
  134.         this.ctrly = (float) ctrly;
  135.         this.x2    = (float) x2;
  136.         this.y2    = (float) y2;
  137.     }
  138.  
  139.     /**
  140.      * Return the bounding box of the shape.
  141.      */
  142.     public Rectangle2D getBounds2D() {
  143.         float left   = Math.min(Math.min(x1, x2), ctrlx);
  144.         float top    = Math.min(Math.min(y1, y2), ctrly);
  145.         float right  = Math.max(Math.max(x1, x2), ctrlx);
  146.         float bottom = Math.max(Math.max(y1, y2), ctrly);
  147.         return new Rectangle2D.Float(left, top,
  148.                      right - left, bottom - top);
  149.     }
  150.     }
  151.  
  152.     /**
  153.      * A quadratic parametric curve segment specified with double coordinates.
  154.      */
  155.     public static class Double extends QuadCurve2D {
  156.     /**
  157.      * The X coordinate of the start point of the quadratic curve segment.
  158.      */
  159.     public double x1;
  160.  
  161.     /**
  162.      * The Y coordinate of the start point of the quadratic curve segment.
  163.      */
  164.     public double y1;
  165.  
  166.     /**
  167.      * The X coordinate of the control point of the quadratic curve segment.
  168.      */
  169.     public double ctrlx;
  170.  
  171.     /**
  172.      * The Y coordinate of the control point of the quadratic curve segment.
  173.      */
  174.     public double ctrly;
  175.  
  176.     /**
  177.      * The X coordinate of the end point of the quadratic curve segment.
  178.      */
  179.     public double x2;
  180.  
  181.     /**
  182.      * The Y coordinate of the end point of the quadratic curve segment.
  183.      */
  184.     public double y2;
  185.  
  186.     /**
  187.      * Constructs and initializes a QuadCurve with coordinates
  188.      * (0, 0, 0, 0, 0, 0).
  189.      */
  190.     public Double() {
  191.     }
  192.  
  193.     /**
  194.      * Constructs and initializes a QuadCurve from the specified coordinates.
  195.      */
  196.     public Double(double x1, double y1,
  197.               double ctrlx, double ctrly,
  198.               double x2, double y2) {
  199.         setCurve(x1, y1, ctrlx, ctrly, x2, y2);
  200.     }
  201.  
  202.     /**
  203.      * Returns the X coordinate of the start point in double precision.
  204.      */
  205.     public double getX1() {
  206.         return x1;
  207.     }
  208.  
  209.     /**
  210.      * Returns the Y coordinate of the start point in double precision.
  211.      */
  212.     public double getY1() {
  213.         return y1;
  214.     }
  215.  
  216.     /**
  217.      * Returns the X coordinate of the control point in double precision.
  218.      */
  219.     public double getCtrlX() {
  220.         return ctrlx;
  221.     }
  222.  
  223.     /**
  224.      * Returns the Y coordinate of the control point in double precision.
  225.      */
  226.     public double getCtrlY() {
  227.         return ctrly;
  228.     }
  229.  
  230.     /**
  231.      * Returns the X coordinate of the end point in double precision.
  232.      */
  233.     public double getX2() {
  234.         return x2;
  235.     }
  236.  
  237.     /**
  238.      * Returns the Y coordinate of the end point in double precision.
  239.      */
  240.     public double getY2() {
  241.         return y2;
  242.     }
  243.  
  244.     /**
  245.      * Sets the location of the endpoints and controlpoint of this curve
  246.      * to the specified double coordinates.
  247.      */
  248.     public void setCurve(double x1, double y1,
  249.                  double ctrlx, double ctrly,
  250.                  double x2, double y2) {
  251.         this.x1    = x1;
  252.         this.y1    = y1;
  253.         this.ctrlx = ctrlx;
  254.         this.ctrly = ctrly;
  255.         this.x2    = x2;
  256.         this.y2    = y2;
  257.     }
  258.  
  259.     /**
  260.      * Return the bounding box of the shape.
  261.      */
  262.     public Rectangle2D getBounds2D() {
  263.         double left   = Math.min(Math.min(x1, x2), ctrlx);
  264.         double top    = Math.min(Math.min(y1, y2), ctrly);
  265.         double right  = Math.max(Math.max(x1, x2), ctrlx);
  266.         double bottom = Math.max(Math.max(y1, y2), ctrly);
  267.         return new Rectangle2D.Double(left, top,
  268.                       right - left, bottom - top);
  269.     }
  270.     }
  271.  
  272.     protected QuadCurve2D() {
  273.     }
  274.  
  275.     /**
  276.      * Returns the X coordinate of the start point in double precision.
  277.      */
  278.     public abstract double getX1();
  279.  
  280.     /**
  281.      * Returns the Y coordinate of the start point in double precision.
  282.      */
  283.     public abstract double getY1();
  284.  
  285.     /**
  286.      * Returns the X coordinate of the control point in double precision.
  287.      */
  288.     public abstract double getCtrlX();
  289.  
  290.     /**
  291.      * Returns the Y coordinate of the control point in double precision.
  292.      */
  293.     public abstract double getCtrlY();
  294.  
  295.     /**
  296.      * Returns the X coordinate of the end point in double precision.
  297.      */
  298.     public abstract double getX2();
  299.  
  300.     /**
  301.      * Returns the Y coordinate of the end point in double precision.
  302.      */
  303.     public abstract double getY2();
  304.  
  305.     /**
  306.      * Sets the location of the endpoints and controlpoint of this curve
  307.      * to the specified double coordinates.
  308.      */
  309.     public abstract void setCurve(double x1, double y1,
  310.                   double ctrlx, double ctrly,
  311.                   double x2, double y2);
  312.  
  313.     /**
  314.      * Sets the location of the endpoints and controlpoints of this curve
  315.      * to the double coordinates at the specified offset in the specified
  316.      * array.
  317.      */
  318.     public void setCurve(double[] coords, int offset) {
  319.     setCurve(coords[offset + 0], coords[offset + 1],
  320.          coords[offset + 2], coords[offset + 3],
  321.          coords[offset + 4], coords[offset + 5]);
  322.     }
  323.  
  324.     /**
  325.      * Sets the location of the endpoints and controlpoint of this curve
  326.      * to the specified Point coordinates.
  327.      */
  328.     public void setCurve(Point2D p1, Point2D cp, Point2D p2) {
  329.     setCurve(p1.getX(), p1.getY(),
  330.          cp.getX(), cp.getY(),
  331.          p2.getX(), p2.getY());
  332.     }
  333.  
  334.     /**
  335.      * Sets the location of the endpoints and controlpoints of this curve
  336.      * to the coordinates of the Point objects at the specified offset in
  337.      * the specified array.
  338.      */
  339.     public void setCurve(Point2D[] pts, int offset) {
  340.     setCurve(pts[offset + 0].getX(), pts[offset + 0].getY(),
  341.          pts[offset + 1].getX(), pts[offset + 1].getY(),
  342.          pts[offset + 2].getX(), pts[offset + 2].getY());
  343.     }
  344.  
  345.     /**
  346.      * Sets the location of the endpoints and controlpoint of this curve
  347.      * to the same as those in the specified QuadCurve.
  348.      */
  349.     public void setCurve(QuadCurve2D c) {
  350.     setCurve(c.getX1(), c.getY1(),
  351.          c.getCtrlX(), c.getCtrlY(),
  352.          c.getX2(), c.getY2());
  353.     }
  354.  
  355.     /**
  356.      * Returns the square of the flatness, or maximum distance of a
  357.      * controlpoint from the line connecting the endpoints, of the
  358.      * quadratic curve specified by the indicated controlpoints.
  359.      */
  360.     public static double getFlatnessSq(double x1, double y1,
  361.                        double ctrlx, double ctrly,
  362.                        double x2, double y2) {
  363.     return Line2D.ptSegDistSq(x1, y1, x2, y2, ctrlx, ctrly);
  364.     }
  365.  
  366.     /**
  367.      * Returns the flatness, or maximum distance of a
  368.      * controlpoint from the line connecting the endpoints, of the
  369.      * quadratic curve specified by the indicated controlpoints.
  370.      */
  371.     public static double getFlatness(double x1, double y1,
  372.                      double ctrlx, double ctrly,
  373.                      double x2, double y2) {
  374.     return Line2D.ptSegDist(x1, y1, x2, y2, ctrlx, ctrly);
  375.     }
  376.  
  377.     /**
  378.      * Returns the square of the flatness, or maximum distance of a
  379.      * controlpoint from the line connecting the endpoints, of the
  380.      * quadratic curve specified by the controlpoints stored in the
  381.      * indicated array at the indicated index.
  382.      */
  383.     public static double getFlatnessSq(double coords[], int offset) {
  384.     return Line2D.ptSegDistSq(coords[offset + 0], coords[offset + 1],
  385.                   coords[offset + 4], coords[offset + 5],
  386.                   coords[offset + 2], coords[offset + 3]);
  387.     }
  388.  
  389.     /**
  390.      * Returns the flatness, or maximum distance of a
  391.      * controlpoint from the line connecting the endpoints, of the
  392.      * quadratic curve specified by the controlpoints stored in the
  393.      * indicated array at the indicated index.
  394.      */
  395.     public static double getFlatness(double coords[], int offset) {
  396.     return Line2D.ptSegDist(coords[offset + 0], coords[offset + 1],
  397.                 coords[offset + 4], coords[offset + 5],
  398.                 coords[offset + 2], coords[offset + 3]);
  399.     }
  400.  
  401.     /**
  402.      * Returns the square of the flatness, or maximum distance of a
  403.      * controlpoint from the line connecting the endpoints, of this curve.
  404.      */
  405.     public double getFlatnessSq() {
  406.     return Line2D.ptSegDistSq(getX1(), getY1(),
  407.                   getX2(), getY2(),
  408.                   getCtrlX(), getCtrlY());
  409.     }
  410.  
  411.     /**
  412.      * Returns the flatness, or maximum distance of a
  413.      * controlpoint from the line connecting the endpoints, of this curve.
  414.      */
  415.     public double getFlatness() {
  416.     return Line2D.ptSegDist(getX1(), getY1(),
  417.                 getX2(), getY2(),
  418.                 getCtrlX(), getCtrlY());
  419.     }
  420.  
  421.     /**
  422.      * Subdivides this quadratic curve and stores the resulting two
  423.      * subdivided curves into the left and right curve parameters.
  424.      * Either or both of the left and right objects may be the same
  425.      * as this object or null.
  426.      * @param left the quadratic curve object for storing for the left or
  427.      * first half of the subdivided curve
  428.      * @param right the quadratic curve object for storing for the right or
  429.      * second half of the subdivided curve
  430.      */
  431.     public void subdivide(QuadCurve2D left, QuadCurve2D right) {
  432.     subdivide(this, left, right);
  433.     }
  434.  
  435.     /**
  436.      * Subdivides the quadratic curve specified by the src parameter
  437.      * and stores the resulting two subdivided curves into the left
  438.      * and right curve parameters.
  439.      * Either or both of the left and right objects may be the same
  440.      * as the src object or null.
  441.      * @param src the quadratic curve to be subdivided
  442.      * @param left the quadratic curve object for storing for the left or
  443.      * first half of the subdivided curve
  444.      * @param right the quadratic curve object for storing for the right or
  445.      * second half of the subdivided curve
  446.      */
  447.     public static void subdivide(QuadCurve2D src,
  448.                  QuadCurve2D left,
  449.                  QuadCurve2D right) {
  450.     double x1 = src.getX1();
  451.     double y1 = src.getY1();
  452.     double ctrlx = src.getCtrlX();
  453.     double ctrly = src.getCtrlY();
  454.     double x2 = src.getX2();
  455.     double y2 = src.getY2();
  456.     double ctrlx1 = (x1 + ctrlx) / 2.0;
  457.     double ctrly1 = (y1 + ctrly) / 2.0;
  458.     double ctrlx2 = (x2 + ctrlx) / 2.0;
  459.     double ctrly2 = (y2 + ctrly) / 2.0;
  460.     ctrlx = (ctrlx1 + ctrlx2) / 2.0;
  461.     ctrly = (ctrly1 + ctrly2) / 2.0;
  462.     if (left != null) {
  463.         left.setCurve(x1, y1, ctrlx1, ctrly1, ctrlx, ctrly);
  464.     }
  465.     if (right != null) {
  466.         right.setCurve(ctrlx, ctrly, ctrlx2, ctrly2, x2, y2);
  467.     }
  468.     }
  469.  
  470.     /**
  471.      * Subdivides the quadratic curve specified by the the coordinates
  472.      * stored in the src array at indices (srcoff) through (srcoff + 5)
  473.      * and stores the resulting two subdivided curves into the two
  474.      * result arrays at the corresponding indices.
  475.      * Either or both of the left and right arrays may be null or a
  476.      * reference to the same array and offset as the src array.
  477.      * Note that the last point in the first subdivided curve is the
  478.      * same as the first point in the second subdivided curve and thus
  479.      * it is possible to pass the same array for left and right and
  480.      * to use offsets such that rightoff equals (leftoff + 4) in order
  481.      * to avoid allocating extra storage for this common point.
  482.      * @param src the array holding the coordinates for the source curve
  483.      * @param srcoff the offset into the array of the beginning of the
  484.      * the 6 source coordinates
  485.      * @param left the array for storing the coordinates for the first
  486.      * half of the subdivided curve
  487.      * @param leftoff the offset into the array of the beginning of the
  488.      * the 6 left coordinates
  489.      * @param right the array for storing the coordinates for the second
  490.      * half of the subdivided curve
  491.      * @param rightoff the offset into the array of the beginning of the
  492.      * the 6 right coordinates
  493.      */
  494.     public static void subdivide(double src[], int srcoff,
  495.                  double left[], int leftoff,
  496.                  double right[], int rightoff) {
  497.     double x1 = src[srcoff + 0];
  498.     double y1 = src[srcoff + 1];
  499.     double ctrlx = src[srcoff + 2];
  500.     double ctrly = src[srcoff + 3];
  501.     double x2 = src[srcoff + 4];
  502.     double y2 = src[srcoff + 5];
  503.     if (left != null) {
  504.         left[leftoff + 0] = x1;
  505.         left[leftoff + 1] = y1;
  506.     }
  507.     if (right != null) {
  508.         right[rightoff + 4] = x2;
  509.         right[rightoff + 5] = y2;
  510.     }
  511.     x1 = (x1 + ctrlx) / 2.0;
  512.     y1 = (y1 + ctrly) / 2.0;
  513.     x2 = (x2 + ctrlx) / 2.0;
  514.     y2 = (y2 + ctrly) / 2.0;
  515.     ctrlx = (x1 + x2) / 2.0;
  516.     ctrly = (y1 + y2) / 2.0;
  517.     if (left != null) {
  518.         left[leftoff + 2] = x1;
  519.         left[leftoff + 3] = y1;
  520.         left[leftoff + 4] = ctrlx;
  521.         left[leftoff + 5] = ctrly;
  522.     }
  523.     if (right != null) {
  524.         right[rightoff + 0] = ctrlx;
  525.         right[rightoff + 1] = ctrly;
  526.         right[rightoff + 2] = x2;
  527.         right[rightoff + 3] = y2;
  528.     }
  529.     }
  530.  
  531.     /**
  532.      * Solve the quadratic whose coefficients are in the eqn array and
  533.      * place the non-complex roots back into the array, returning the
  534.      * number of roots.  The quadratic solved is represented by the
  535.      * equation:
  536.      *     eqn = {C, B, A};
  537.      *     ax^2 + bx + c = 0
  538.      * A return value of -1 is used to distinguish a constant equation,
  539.      * which may be always 0 or never 0, from an equation which has no
  540.      * zeroes.
  541.      * @return the number of roots, or -1 if the equation is a constant
  542.      */
  543.     public static int solveQuadratic(double eqn[]) {
  544.     double a = eqn[2];
  545.     double b = eqn[1];
  546.     double c = eqn[0];
  547.     int roots = 0;
  548.     if (a == 0.0) {
  549.         // The quadratic parabola has degenerated to a line.
  550.         if (b == 0.0) {
  551.         // The line has degenerated to a constant.
  552.         return -1;
  553.         } 
  554.         eqn[roots++] = -c / b;
  555.     } else {
  556.         // From Numerical Recipes, 5.6, Quadratic and Cubic Equations
  557.         double d = b * b - 4.0 * a * c;
  558.         if (d < 0.0) {
  559.         // If d < 0.0, then there are no roots
  560.         return 0;
  561.         }
  562.         d = Math.sqrt(d);
  563.         // For accuracy, calculate one root using:
  564.         //     (-b +/- d) / 2a
  565.         // and the other using:
  566.         //     2c / (-b +/- d)
  567.         // Choose the sign of the +/- so that b+d gets larger in magnitude
  568.         if (b < 0.0) {
  569.         d = -d;
  570.         }
  571.         double q = (b + d) / -2.0;
  572.         // We already tested a for being 0 above
  573.         eqn[roots++] = q / a;
  574.         if (q != 0.0) {
  575.         eqn[roots++] = c / q;
  576.         }
  577.     }
  578.     return roots;
  579.     }
  580.  
  581.     /**
  582.      * Test if a given coordinate is inside the boundary of the shape.
  583.      */
  584.     public boolean contains(double x, double y) {
  585.     // We count the "Y" crossings to determine if the point is
  586.     // inside the curve bounded by its closing line.
  587.     int crossings = 0;
  588.     double x1 = getX1();
  589.     double y1 = getY1();
  590.     double x2 = getX2();
  591.     double y2 = getY2();
  592.     // First check for a crossing of the line connecting the endpoints
  593.     double dy = y2 - y1;
  594.     if ((dy > 0.0 && y >= y1 && y <= y2) ||
  595.         (dy < 0.0 && y <= y1 && y >= y2))
  596.     {
  597.         if (x <= x1 + (y - y1) * (x2 - x1) / dy) {
  598.         crossings++;
  599.         }
  600.     }
  601.     // Solve the Y parametric equation for intersections with y
  602.     // Since the points at t = 0.0 and t = 1.0 were already
  603.     // checked by the line test above, we are only interested
  604.     // in solutions in the range (0,1)
  605.     // We currently have:
  606.     //     y = Py(t) = y1(1-t)^2 + 2cyt(1 - t) + y2t^2
  607.     //               = y1 - 2y1t + y1t^2 + 2cyt - 2cyt^2 + y2t^2
  608.     //               = y1 + (2cy - 2y1)t + (y1 - 2cy + y2)t^2
  609.     //             0 = (y1 - y) + (2cy - 2y1)t + (y1 - 2cy + y2)t^2
  610.     //             0 = C + Bt + At^2
  611.     double ctrlx = getCtrlX();
  612.     double ctrly = getCtrlY();
  613.     double eqn[] = {y1 - y,
  614.             ctrly + ctrly - y1 - y1,
  615.             y1 - ctrly - ctrly + y2};
  616.     int roots = solveQuadratic(eqn);
  617.     while (--roots >= 0) {
  618.         double t = eqn[roots];
  619.         if (t > 0.0 && t < 1.0) {
  620.         double u = 1.0 - t;
  621.         if (x <= x1 * u * u + 2.0 * ctrlx * t * u + x2 * t * t) {
  622.             crossings++;
  623.         }
  624.         }
  625.     }
  626.     return ((crossings & 1) == 1);
  627.     }
  628.  
  629.     /**
  630.      * Test if a given Point is inside the boundary of the shape.
  631.      */
  632.     public boolean contains(Point2D p) {
  633.     return contains(p.getX(), p.getY());
  634.     }
  635.  
  636.     /**
  637.      * Test if the Shape intersects the interior of a given
  638.      * set of rectangular coordinates.
  639.      */
  640.     public boolean intersects(double x, double y, double w, double h) {
  641.  
  642.         /*
  643.           This is also a beizer with only three control points
  644.           Just solve the equation with each line segment
  645.           If there is a root within range then it intersects
  646.           */
  647.  
  648.       double[] eqn = new double[3];
  649.       double[] backup = new double[3];
  650.       double temp, temp2;
  651.       int result;
  652.  
  653.       eqn[0] = getX1() - x;
  654.       eqn[1] = (2 * getCtrlX()) - (2 * getX1());
  655.       eqn[2] = getX1() + getX2() - (2 * getCtrlX());
  656.  
  657.       System.arraycopy(eqn, 0, backup, 0, 3);
  658.  
  659.       result = solveQuadratic(eqn);
  660.  
  661.       for (int i = 0; i < result; i++) {
  662.       if ((eqn[i] >= 0) && (eqn[i] <= 1)) {
  663.         temp = (getY1() * Math.pow((1 - eqn[i]), 2)) 
  664.                 + (getCtrlY() * 2 * eqn[i] * (1 - eqn[i])) 
  665.                 + (getY2() * Math.pow(eqn[i], 2));
  666.         temp2 = (getX1() * Math.pow((1 - eqn[i]), 2)) 
  667.                 + (getCtrlX() * 2 * eqn[i] * (1 - eqn[i])) 
  668.                 + (getX2() * Math.pow(eqn[i], 2));
  669.             
  670.         if ((temp >= y) && (temp <= (y+h))) {
  671.           return true;
  672.             }
  673.       }
  674.       }
  675.       
  676.       System.arraycopy(backup, 0, eqn, 0, 3);
  677.       eqn[0] = getX1() - (x + w);
  678.       System.arraycopy(eqn, 0, backup, 0, 3);
  679.  
  680.       result = solveQuadratic(eqn);
  681.       
  682.       for (int i = 0; i < result; i++) {
  683.       if ((eqn[i] >= 0) && (eqn[i] <= 1)) {
  684.         temp = (getY1() * Math.pow((1 - eqn[i]), 2)) 
  685.                 + (getCtrlY() * 2 * eqn[i] * (1 - eqn[i])) 
  686.                 + (getY2() * Math.pow(eqn[i], 2));
  687.         temp2 = (getX1() * Math.pow((1 - eqn[i]), 2))
  688.                 + (getCtrlX() * 2 * eqn[i] * (1 - eqn[i])) 
  689.                 + (getX2() * Math.pow(eqn[i], 2));
  690.  
  691.         if ((temp >= y) && (temp <= (y+h))) {
  692.           return true;
  693.             }
  694.         }
  695.       }
  696.       
  697.       eqn[0] = getY1() - y;
  698.       eqn[1] = (2 * getCtrlY()) - (2 * getY1());
  699.       eqn[2] = getY1() + getY2() - (2 * getCtrlY());
  700.  
  701.       System.arraycopy(eqn, 0, backup, 0, 3);
  702.  
  703.       result = solveQuadratic(eqn);
  704.  
  705.       for (int i = 0; i < result; i++) {
  706.       if ((eqn[i] >= 0) && (eqn[i] <= 1)) {
  707.         temp = (getX1() * Math.pow((1 - eqn[i]), 2))
  708.                 + (getCtrlX() * 2 * eqn[i] * (1 - eqn[i])) 
  709.                 + (getX2() * Math.pow(eqn[i], 2));
  710.         temp2 = (getY1() * Math.pow((1 - eqn[i]), 2)) 
  711.                 + (getCtrlY() * 2 * eqn[i] * (1 - eqn[i])) 
  712.                 + (getY2() * Math.pow(eqn[i], 2));
  713.  
  714.         if ((temp >= x) && (temp <= (x+w))) {
  715.           return true;
  716.             }
  717.     }
  718.       }
  719.  
  720.       System.arraycopy(backup, 0, eqn, 0, 3);
  721.       eqn[0] = getY1() - (y + h);
  722.       System.arraycopy(eqn, 0, backup, 0, 3);
  723.  
  724.       result = solveQuadratic(eqn);
  725.  
  726.       for (int i = 0; i < result; i++) {
  727.       if ((eqn[i] >= 0) && (eqn[i] <= 1)) {
  728.               temp = (getX1() * Math.pow((1 - eqn[i]), 2)) 
  729.                   + (getCtrlX() * 2 * eqn[i] * (1 - eqn[i])) 
  730.                   + (getX2() * Math.pow(eqn[i], 2));
  731.         temp2 = (getY1() * Math.pow((1 - eqn[i]), 2)) 
  732.                 + (getCtrlY() * 2 * eqn[i] * (1 - eqn[i])) 
  733.                 + (getY2() * Math.pow(eqn[i], 2));
  734.  
  735.         if ((temp >= x) && (temp <= (x+w))) {
  736.           return true;
  737.             }
  738.       }
  739.     }
  740.  
  741.       return false;
  742.     }
  743.  
  744.     /**
  745.      * Test if the Shape intersects the interior of a given
  746.      * Rectangle.
  747.      */
  748.     public boolean intersects(Rectangle2D r) {
  749.     return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
  750.     }
  751.  
  752.     /**
  753.      * Test if the interior of the Shape entirely contains the given
  754.      * set of rectangular coordinates.
  755.      */
  756.     public boolean contains(double x, double y, double w, double h) {
  757.     // Assertion: Quadratic curves closed by connecting their
  758.     // endpoints are always convex.
  759.     return (contains(x, y) &&
  760.         contains(x + w, y) &&
  761.         contains(x + w, y + h) &&
  762.         contains(x, y + h));
  763.     }
  764.  
  765.     /**
  766.      * Test if the interior of the Shape entirely contains the given
  767.      * Rectangle.
  768.      */
  769.     public boolean contains(Rectangle2D r) {
  770.     return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
  771.     }
  772.  
  773.     /**
  774.      * Return the bounding box of the shape.
  775.      */
  776.     public Rectangle getBounds() {
  777.     return getBounds2D().getBounds();
  778.     }
  779.  
  780.     /**
  781.      * Return an iteration object that defines the boundary of the
  782.      * shape.
  783.      */
  784.     public PathIterator getPathIterator(AffineTransform at) {
  785.     return new QuadIterator(this, at);
  786.     }
  787.  
  788.     /**
  789.      * Return an iteration object that defines the boundary of the
  790.      * flattened shape.
  791.      */
  792.     public PathIterator getPathIterator(AffineTransform at, double flatness) {
  793.     return new FlatteningPathIterator(getPathIterator(at), flatness);
  794.     }
  795.  
  796.     /**
  797.      * Creates a new object of the same class as this object.
  798.      *
  799.      * @return     a clone of this instance.
  800.      * @exception  OutOfMemoryError            if there is not enough memory.
  801.      * @see        java.lang.Cloneable
  802.      * @since      JDK1.2
  803.      */
  804.     public Object clone() {
  805.     try {
  806.         return super.clone();
  807.     } catch (CloneNotSupportedException e) {
  808.         // this shouldn't happen, since we are Cloneable
  809.         throw new InternalError();
  810.     }
  811.     }
  812. }
  813.