Source for java.awt.geom.QuadCurve2D

   1: /* QuadCurve2D.java -- represents a parameterized quadratic curve in 2-D space
   2:    Copyright (C) 2002, 2003, 2004 Free Software Foundation
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: package java.awt.geom;
  39: 
  40: import java.awt.Rectangle;
  41: import java.awt.Shape;
  42: import java.util.NoSuchElementException;
  43: 
  44: /**
  45:  * A two-dimensional curve that is parameterized with a quadratic
  46:  * function.
  47:  *
  48:  * <p><img src="doc-files/QuadCurve2D-1.png" width="350" height="180"
  49:  * alt="A drawing of a QuadCurve2D" />
  50:  *
  51:  * @author Eric Blake (ebb9@email.byu.edu)
  52:  * @author Graydon Hoare (graydon@redhat.com)
  53:  * @author Sascha Brawer (brawer@dandelis.ch)
  54:  * @author Sven de Marothy (sven@physto.se)
  55:  *
  56:  * @since 1.2
  57:  */
  58: public abstract class QuadCurve2D implements Shape, Cloneable
  59: {
  60:   private static final double BIG_VALUE = java.lang.Double.MAX_VALUE / 10.0;
  61:   private static final double EPSILON = 1E-10;
  62: 
  63:   /**
  64:    * Constructs a new QuadCurve2D. Typical users will want to
  65:    * construct instances of a subclass, such as {@link
  66:    * QuadCurve2D.Float} or {@link QuadCurve2D.Double}.
  67:    */
  68:   protected QuadCurve2D()
  69:   {
  70:   }
  71: 
  72:   /**
  73:    * Returns the <i>x</i> coordinate of the curve&#x2019;s start
  74:    * point.
  75:    */
  76:   public abstract double getX1();
  77: 
  78:   /**
  79:    * Returns the <i>y</i> coordinate of the curve&#x2019;s start
  80:    * point.
  81:    */
  82:   public abstract double getY1();
  83: 
  84:   /**
  85:    * Returns the curve&#x2019;s start point.
  86:    */
  87:   public abstract Point2D getP1();
  88: 
  89:   /**
  90:    * Returns the <i>x</i> coordinate of the curve&#x2019;s control
  91:    * point.
  92:    */
  93:   public abstract double getCtrlX();
  94: 
  95:   /**
  96:    * Returns the <i>y</i> coordinate of the curve&#x2019;s control
  97:    * point.
  98:    */
  99:   public abstract double getCtrlY();
 100: 
 101:   /**
 102:    * Returns the curve&#x2019;s control point.
 103:    */
 104:   public abstract Point2D getCtrlPt();
 105: 
 106:   /**
 107:    * Returns the <i>x</i> coordinate of the curve&#x2019;s end
 108:    * point.
 109:    */
 110:   public abstract double getX2();
 111: 
 112:   /**
 113:    * Returns the <i>y</i> coordinate of the curve&#x2019;s end
 114:    * point.
 115:    */
 116:   public abstract double getY2();
 117: 
 118:   /**
 119:    * Returns the curve&#x2019;s end point.
 120:    */
 121:   public abstract Point2D getP2();
 122: 
 123:   /**
 124:    * Changes the curve geometry, separately specifying each coordinate
 125:    * value.
 126:    *
 127:    * @param x1 the <i>x</i> coordinate of the curve&#x2019;s new start
 128:    * point.
 129:    *
 130:    * @param y1 the <i>y</i> coordinate of the curve&#x2019;s new start
 131:    * point.
 132:    *
 133:    * @param cx the <i>x</i> coordinate of the curve&#x2019;s new
 134:    * control point.
 135:    *
 136:    * @param cy the <i>y</i> coordinate of the curve&#x2019;s new
 137:    * control point.
 138:    *
 139:    * @param x2 the <i>x</i> coordinate of the curve&#x2019;s new end
 140:    * point.
 141:    *
 142:    * @param y2 the <i>y</i> coordinate of the curve&#x2019;s new end
 143:    * point.
 144:    */
 145:   public abstract void setCurve(double x1, double y1, double cx, double cy,
 146:                                 double x2, double y2);
 147: 
 148:   /**
 149:    * Changes the curve geometry, passing coordinate values in an
 150:    * array.
 151:    *
 152:    * @param coords an array containing the new coordinate values.  The
 153:    * <i>x</i> coordinate of the new start point is located at
 154:    * <code>coords[offset]</code>, its <i>y</i> coordinate at
 155:    * <code>coords[offset + 1]</code>.  The <i>x</i> coordinate of the
 156:    * new control point is located at <code>coords[offset + 2]</code>,
 157:    * its <i>y</i> coordinate at <code>coords[offset + 3]</code>. The
 158:    * <i>x</i> coordinate of the new end point is located at
 159:    * <code>coords[offset + 4]</code>, its <i>y</i> coordinate at
 160:    * <code>coords[offset + 5]</code>.
 161:    *
 162:    * @param offset the offset of the first coordinate value in
 163:    * <code>coords</code>.
 164:    */
 165:   public void setCurve(double[] coords, int offset)
 166:   {
 167:     setCurve(coords[offset++], coords[offset++], coords[offset++],
 168:              coords[offset++], coords[offset++], coords[offset++]);
 169:   }
 170: 
 171:   /**
 172:    * Changes the curve geometry, specifying coordinate values in
 173:    * separate Point objects.
 174:    *
 175:    * <p><img src="doc-files/QuadCurve2D-1.png" width="350" height="180"
 176:    * alt="A drawing of a QuadCurve2D" />
 177:    *
 178:    * <p>The curve does not keep any reference to the passed point
 179:    * objects. Therefore, a later change to <code>p1</code>,
 180:    * <code>c</code> <code>p2</code> will not affect the curve
 181:    * geometry.
 182:    *
 183:    * @param p1 the new start point.
 184:    * @param c the new control point.
 185:    * @param p2 the new end point.
 186:    */
 187:   public void setCurve(Point2D p1, Point2D c, Point2D p2)
 188:   {
 189:     setCurve(p1.getX(), p1.getY(), c.getX(), c.getY(), p2.getX(), p2.getY());
 190:   }
 191: 
 192:   /**
 193:    * Changes the curve geometry, specifying coordinate values in an
 194:    * array of Point objects.
 195:    *
 196:    * <p><img src="doc-files/QuadCurve2D-1.png" width="350" height="180"
 197:    * alt="A drawing of a QuadCurve2D" />
 198:    *
 199:    * <p>The curve does not keep references to the passed point
 200:    * objects. Therefore, a later change to the <code>pts</code> array
 201:    * or any of its elements will not affect the curve geometry.
 202:    *
 203:    * @param pts an array containing the points. The new start point
 204:    * is located at <code>pts[offset]</code>, the new control
 205:    * point at <code>pts[offset + 1]</code>, and the new end point
 206:    * at <code>pts[offset + 2]</code>.
 207:    *
 208:    * @param offset the offset of the start point in <code>pts</code>.
 209:    */
 210:   public void setCurve(Point2D[] pts, int offset)
 211:   {
 212:     setCurve(pts[offset].getX(), pts[offset].getY(), pts[offset + 1].getX(),
 213:              pts[offset + 1].getY(), pts[offset + 2].getX(),
 214:              pts[offset + 2].getY());
 215:   }
 216: 
 217:   /**
 218:    * Changes the geometry of the curve to that of another curve.
 219:    *
 220:    * @param c the curve whose coordinates will be copied.
 221:    */
 222:   public void setCurve(QuadCurve2D c)
 223:   {
 224:     setCurve(c.getX1(), c.getY1(), c.getCtrlX(), c.getCtrlY(), c.getX2(),
 225:              c.getY2());
 226:   }
 227: 
 228:   /**
 229:    * Calculates the squared flatness of a quadratic curve, directly
 230:    * specifying each coordinate value. The flatness is the distance of
 231:    * the control point to the line between start and end point.
 232:    *
 233:    * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180"
 234:    * alt="A drawing that illustrates the flatness" />
 235:    *
 236:    * <p>In the above drawing, the straight line connecting start point
 237:    * P1 and end point P2 is depicted in gray.  The result will be the
 238:    * the square of the distance between C and the gray line, i.e.
 239:    * the squared length of the red line.
 240:    *
 241:    * @param x1 the <i>x</i> coordinate of the start point P1.
 242:    * @param y1 the <i>y</i> coordinate of the start point P1.
 243:    * @param cx the <i>x</i> coordinate of the control point C.
 244:    * @param cy the <i>y</i> coordinate of the control point C.
 245:    * @param x2 the <i>x</i> coordinate of the end point P2.
 246:    * @param y2 the <i>y</i> coordinate of the end point P2.
 247:    */
 248:   public static double getFlatnessSq(double x1, double y1, double cx,
 249:                                      double cy, double x2, double y2)
 250:   {
 251:     return Line2D.ptSegDistSq(x1, y1, x2, y2, cx, cy);
 252:   }
 253: 
 254:   /**
 255:    * Calculates the flatness of a quadratic curve, directly specifying
 256:    * each coordinate value. The flatness is the distance of the
 257:    * control point to the line between start and end point.
 258:    *
 259:    * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180"
 260:    * alt="A drawing that illustrates the flatness" />
 261:    *
 262:    * <p>In the above drawing, the straight line connecting start point
 263:    * P1 and end point P2 is depicted in gray.  The result will be the
 264:    * the distance between C and the gray line, i.e. the length of
 265:    * the red line.
 266:    *
 267:    * @param x1 the <i>x</i> coordinate of the start point P1.
 268:    * @param y1 the <i>y</i> coordinate of the start point P1.
 269:    * @param cx the <i>x</i> coordinate of the control point C.
 270:    * @param cy the <i>y</i> coordinate of the control point C.
 271:    * @param x2 the <i>x</i> coordinate of the end point P2.
 272:    * @param y2 the <i>y</i> coordinate of the end point P2.
 273:    */
 274:   public static double getFlatness(double x1, double y1, double cx, double cy,
 275:                                    double x2, double y2)
 276:   {
 277:     return Line2D.ptSegDist(x1, y1, x2, y2, cx, cy);
 278:   }
 279: 
 280:   /**
 281:    * Calculates the squared flatness of a quadratic curve, specifying
 282:    * the coordinate values in an array. The flatness is the distance
 283:    * of the control point to the line between start and end point.
 284:    *
 285:    * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180"
 286:    * alt="A drawing that illustrates the flatness" />
 287:    *
 288:    * <p>In the above drawing, the straight line connecting start point
 289:    * P1 and end point P2 is depicted in gray.  The result will be the
 290:    * the square of the distance between C and the gray line, i.e.
 291:    * the squared length of the red line.
 292:    *
 293:    * @param coords an array containing the coordinate values.  The
 294:    * <i>x</i> coordinate of the start point P1 is located at
 295:    * <code>coords[offset]</code>, its <i>y</i> coordinate at
 296:    * <code>coords[offset + 1]</code>.  The <i>x</i> coordinate of the
 297:    * control point C is located at <code>coords[offset + 2]</code>,
 298:    * its <i>y</i> coordinate at <code>coords[offset + 3]</code>. The
 299:    * <i>x</i> coordinate of the end point P2 is located at
 300:    * <code>coords[offset + 4]</code>, its <i>y</i> coordinate at
 301:    * <code>coords[offset + 5]</code>.
 302:    *
 303:    * @param offset the offset of the first coordinate value in
 304:    * <code>coords</code>.
 305:    */
 306:   public static double getFlatnessSq(double[] coords, int offset)
 307:   {
 308:     return Line2D.ptSegDistSq(coords[offset], coords[offset + 1],
 309:                               coords[offset + 4], coords[offset + 5],
 310:                               coords[offset + 2], coords[offset + 3]);
 311:   }
 312: 
 313:   /**
 314:    * Calculates the flatness of a quadratic curve, specifying the
 315:    * coordinate values in an array. The flatness is the distance of
 316:    * the control point to the line between start and end point.
 317:    *
 318:    * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180"
 319:    * alt="A drawing that illustrates the flatness" />
 320:    *
 321:    * <p>In the above drawing, the straight line connecting start point
 322:    * P1 and end point P2 is depicted in gray.  The result will be the
 323:    * the the distance between C and the gray line, i.e.  the length of
 324:    * the red line.
 325:    *
 326:    * @param coords an array containing the coordinate values.  The
 327:    * <i>x</i> coordinate of the start point P1 is located at
 328:    * <code>coords[offset]</code>, its <i>y</i> coordinate at
 329:    * <code>coords[offset + 1]</code>.  The <i>x</i> coordinate of the
 330:    * control point C is located at <code>coords[offset + 2]</code>,
 331:    * its <i>y</i> coordinate at <code>coords[offset + 3]</code>. The
 332:    * <i>x</i> coordinate of the end point P2 is located at
 333:    * <code>coords[offset + 4]</code>, its <i>y</i> coordinate at
 334:    * <code>coords[offset + 5]</code>.
 335:    *
 336:    * @param offset the offset of the first coordinate value in
 337:    * <code>coords</code>.
 338:    */
 339:   public static double getFlatness(double[] coords, int offset)
 340:   {
 341:     return Line2D.ptSegDist(coords[offset], coords[offset + 1],
 342:                             coords[offset + 4], coords[offset + 5],
 343:                             coords[offset + 2], coords[offset + 3]);
 344:   }
 345: 
 346:   /**
 347:    * Calculates the squared flatness of this curve. The flatness is
 348:    * the distance of the control point to the line between start and
 349:    * end point.
 350:    *
 351:    * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180"
 352:    * alt="A drawing that illustrates the flatness" />
 353:    *
 354:    * <p>In the above drawing, the straight line connecting start point
 355:    * P1 and end point P2 is depicted in gray.  The result will be the
 356:    * the square of the distance between C and the gray line, i.e. the
 357:    * squared length of the red line.
 358:    */
 359:   public double getFlatnessSq()
 360:   {
 361:     return Line2D.ptSegDistSq(getX1(), getY1(), getX2(), getY2(), getCtrlX(),
 362:                               getCtrlY());
 363:   }
 364: 
 365:   /**
 366:    * Calculates the flatness of this curve. The flatness is the
 367:    * distance of the control point to the line between start and end
 368:    * point.
 369:    *
 370:    * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180"
 371:    * alt="A drawing that illustrates the flatness" />
 372:    *
 373:    * <p>In the above drawing, the straight line connecting start point
 374:    * P1 and end point P2 is depicted in gray.  The result will be the
 375:    * the distance between C and the gray line, i.e.  the length of the
 376:    * red line.
 377:    */
 378:   public double getFlatness()
 379:   {
 380:     return Line2D.ptSegDist(getX1(), getY1(), getX2(), getY2(), getCtrlX(),
 381:                             getCtrlY());
 382:   }
 383: 
 384:   /**
 385:    * Subdivides this curve into two halves.
 386:    *
 387:    * <p><img src="doc-files/QuadCurve2D-3.png" width="700"
 388:    * height="180" alt="A drawing that illustrates the effects of
 389:    * subdividing a QuadCurve2D" />
 390:    *
 391:    * @param left a curve whose geometry will be set to the left half
 392:    * of this curve, or <code>null</code> if the caller is not
 393:    * interested in the left half.
 394:    *
 395:    * @param right a curve whose geometry will be set to the right half
 396:    * of this curve, or <code>null</code> if the caller is not
 397:    * interested in the right half.
 398:    */
 399:   public void subdivide(QuadCurve2D left, QuadCurve2D right)
 400:   {
 401:     // Use empty slots at end to share single array.
 402:     double[] d = new double[]
 403:                  {
 404:                    getX1(), getY1(), getCtrlX(), getCtrlY(), getX2(), getY2(),
 405:                    0, 0, 0, 0
 406:                  };
 407:     subdivide(d, 0, d, 0, d, 4);
 408:     if (left != null)
 409:       left.setCurve(d, 0);
 410:     if (right != null)
 411:       right.setCurve(d, 4);
 412:   }
 413: 
 414:   /**
 415:    * Subdivides a quadratic curve into two halves.
 416:    *
 417:    * <p><img src="doc-files/QuadCurve2D-3.png" width="700"
 418:    * height="180" alt="A drawing that illustrates the effects of
 419:    * subdividing a QuadCurve2D" />
 420:    *
 421:    * @param src the curve to be subdivided.
 422:    *
 423:    * @param left a curve whose geometry will be set to the left half
 424:    * of <code>src</code>, or <code>null</code> if the caller is not
 425:    * interested in the left half.
 426:    *
 427:    * @param right a curve whose geometry will be set to the right half
 428:    * of <code>src</code>, or <code>null</code> if the caller is not
 429:    * interested in the right half.
 430:    */
 431:   public static void subdivide(QuadCurve2D src, QuadCurve2D left,
 432:                                QuadCurve2D right)
 433:   {
 434:     src.subdivide(left, right);
 435:   }
 436: 
 437:   /**
 438:    * Subdivides a quadratic curve into two halves, passing all
 439:    * coordinates in an array.
 440:    *
 441:    * <p><img src="doc-files/QuadCurve2D-3.png" width="700"
 442:    * height="180" alt="A drawing that illustrates the effects of
 443:    * subdividing a QuadCurve2D" />
 444:    *
 445:    * <p>The left end point and the right start point will always be
 446:    * identical. Memory-concious programmers thus may want to pass the
 447:    * same array for both <code>left</code> and <code>right</code>, and
 448:    * set <code>rightOff</code> to <code>leftOff + 4</code>.
 449:    *
 450:    * @param src an array containing the coordinates of the curve to be
 451:    * subdivided.  The <i>x</i> coordinate of the start point is
 452:    * located at <code>src[srcOff]</code>, its <i>y</i> at
 453:    * <code>src[srcOff + 1]</code>.  The <i>x</i> coordinate of the
 454:    * control point is located at <code>src[srcOff + 2]</code>, its
 455:    * <i>y</i> at <code>src[srcOff + 3]</code>.  The <i>x</i>
 456:    * coordinate of the end point is located at <code>src[srcOff +
 457:    * 4]</code>, its <i>y</i> at <code>src[srcOff + 5]</code>.
 458:    *
 459:    * @param srcOff an offset into <code>src</code>, specifying
 460:    * the index of the start point&#x2019;s <i>x</i> coordinate.
 461:    *
 462:    * @param left an array that will receive the coordinates of the
 463:    * left half of <code>src</code>. It is acceptable to pass
 464:    * <code>src</code>. A caller who is not interested in the left half
 465:    * can pass <code>null</code>.
 466:    *
 467:    * @param leftOff an offset into <code>left</code>, specifying the
 468:    * index where the start point&#x2019;s <i>x</i> coordinate will be
 469:    * stored.
 470:    *
 471:    * @param right an array that will receive the coordinates of the
 472:    * right half of <code>src</code>. It is acceptable to pass
 473:    * <code>src</code> or <code>left</code>. A caller who is not
 474:    * interested in the right half can pass <code>null</code>.
 475:    *
 476:    * @param rightOff an offset into <code>right</code>, specifying the
 477:    * index where the start point&#x2019;s <i>x</i> coordinate will be
 478:    * stored.
 479:    */
 480:   public static void subdivide(double[] src, int srcOff, double[] left,
 481:                                int leftOff, double[] right, int rightOff)
 482:   {
 483:     double x1;
 484:     double y1;
 485:     double xc;
 486:     double yc;
 487:     double x2;
 488:     double y2;
 489: 
 490:     x1 = src[srcOff];
 491:     y1 = src[srcOff + 1];
 492:     xc = src[srcOff + 2];
 493:     yc = src[srcOff + 3];
 494:     x2 = src[srcOff + 4];
 495:     y2 = src[srcOff + 5];
 496: 
 497:     if (left != null)
 498:       {
 499:     left[leftOff] = x1;
 500:     left[leftOff + 1] = y1;
 501:       }
 502: 
 503:     if (right != null)
 504:       {
 505:     right[rightOff + 4] = x2;
 506:     right[rightOff + 5] = y2;
 507:       }
 508: 
 509:     x1 = (x1 + xc) / 2;
 510:     x2 = (xc + x2) / 2;
 511:     xc = (x1 + x2) / 2;
 512:     y1 = (y1 + yc) / 2;
 513:     y2 = (y2 + yc) / 2;
 514:     yc = (y1 + y2) / 2;
 515: 
 516:     if (left != null)
 517:       {
 518:     left[leftOff + 2] = x1;
 519:     left[leftOff + 3] = y1;
 520:     left[leftOff + 4] = xc;
 521:     left[leftOff + 5] = yc;
 522:       }
 523: 
 524:     if (right != null)
 525:       {
 526:     right[rightOff] = xc;
 527:     right[rightOff + 1] = yc;
 528:     right[rightOff + 2] = x2;
 529:     right[rightOff + 3] = y2;
 530:       }
 531:   }
 532: 
 533:   /**
 534:    * Finds the non-complex roots of a quadratic equation, placing the
 535:    * results into the same array as the equation coefficients. The
 536:    * following equation is being solved:
 537:    *
 538:    * <blockquote><code>eqn[2]</code> &#xb7; <i>x</i><sup>2</sup>
 539:    * + <code>eqn[1]</code> &#xb7; <i>x</i>
 540:    * + <code>eqn[0]</code>
 541:    * = 0
 542:    * </blockquote>
 543:    *
 544:    * <p>For some background about solving quadratic equations, see the
 545:    * article <a href=
 546:    * "http://planetmath.org/encyclopedia/QuadraticFormula.html"
 547:    * >&#x201c;Quadratic Formula&#x201d;</a> in <a href=
 548:    * "http://planetmath.org/">PlanetMath</a>. For an extensive library
 549:    * of numerical algorithms written in the C programming language,
 550:    * see the <a href="http://www.gnu.org/software/gsl/">GNU Scientific
 551:    * Library</a>.
 552:    *
 553:    * @see #solveQuadratic(double[], double[])
 554:    * @see CubicCurve2D#solveCubic(double[], double[])
 555:    *
 556:    * @param eqn an array with the coefficients of the equation. When
 557:    * this procedure has returned, <code>eqn</code> will contain the
 558:    * non-complex solutions of the equation, in no particular order.
 559:    *
 560:    * @return the number of non-complex solutions. A result of 0
 561:    * indicates that the equation has no non-complex solutions. A
 562:    * result of -1 indicates that the equation is constant (i.e.,
 563:    * always or never zero).
 564:    *
 565:    * @author Brian Gough (bjg@network-theory.com)
 566:    * (original C implementation in the <a href=
 567:    * "http://www.gnu.org/software/gsl/">GNU Scientific Library</a>)
 568:    *
 569:    * @author Sascha Brawer (brawer@dandelis.ch)
 570:    * (adaptation to Java)
 571:    */
 572:   public static int solveQuadratic(double[] eqn)
 573:   {
 574:     return solveQuadratic(eqn, eqn);
 575:   }
 576: 
 577:   /**
 578:    * Finds the non-complex roots of a quadratic equation. The
 579:    * following equation is being solved:
 580:    *
 581:    * <blockquote><code>eqn[2]</code> &#xb7; <i>x</i><sup>2</sup>
 582:    * + <code>eqn[1]</code> &#xb7; <i>x</i>
 583:    * + <code>eqn[0]</code>
 584:    * = 0
 585:    * </blockquote>
 586:    *
 587:    * <p>For some background about solving quadratic equations, see the
 588:    * article <a href=
 589:    * "http://planetmath.org/encyclopedia/QuadraticFormula.html"
 590:    * >&#x201c;Quadratic Formula&#x201d;</a> in <a href=
 591:    * "http://planetmath.org/">PlanetMath</a>. For an extensive library
 592:    * of numerical algorithms written in the C programming language,
 593:    * see the <a href="http://www.gnu.org/software/gsl/">GNU Scientific
 594:    * Library</a>.
 595:    *
 596:    * @see CubicCurve2D#solveCubic(double[],double[])
 597:    *
 598:    * @param eqn an array with the coefficients of the equation.
 599:    *
 600:    * @param res an array into which the non-complex roots will be
 601:    * stored.  The results may be in an arbitrary order. It is safe to
 602:    * pass the same array object reference for both <code>eqn</code>
 603:    * and <code>res</code>.
 604:    *
 605:    * @return the number of non-complex solutions. A result of 0
 606:    * indicates that the equation has no non-complex solutions. A
 607:    * result of -1 indicates that the equation is constant (i.e.,
 608:    * always or never zero).
 609:    *
 610:    * @author Brian Gough (bjg@network-theory.com)
 611:    * (original C implementation in the <a href=
 612:    * "http://www.gnu.org/software/gsl/">GNU Scientific Library</a>)
 613:    *
 614:    * @author Sascha Brawer (brawer@dandelis.ch)
 615:    * (adaptation to Java)
 616:    */
 617:   public static int solveQuadratic(double[] eqn, double[] res)
 618:   {
 619:     // Taken from poly/solve_quadratic.c in the GNU Scientific Library
 620:     // (GSL), cvs revision 1.7 of 2003-07-26. For the original source,
 621:     // see http://www.gnu.org/software/gsl/
 622:     //
 623:     // Brian Gough, the author of that code, has granted the
 624:     // permission to use it in GNU Classpath under the GNU Classpath
 625:     // license, and has assigned the copyright to the Free Software
 626:     // Foundation.
 627:     //
 628:     // The Java implementation is very similar to the GSL code, but
 629:     // not a strict one-to-one copy. For example, GSL would sort the
 630:     // result.
 631:     double a;
 632:     double b;
 633:     double c;
 634:     double disc;
 635: 
 636:     c = eqn[0];
 637:     b = eqn[1];
 638:     a = eqn[2];
 639: 
 640:     // Check for linear or constant functions. This is not done by the
 641:     // GNU Scientific Library.  Without this special check, we
 642:     // wouldn't return -1 for constant functions, and 2 instead of 1
 643:     // for linear functions.
 644:     if (a == 0)
 645:       {
 646:     if (b == 0)
 647:       return -1;
 648: 
 649:     res[0] = -c / b;
 650:     return 1;
 651:       }
 652: 
 653:     disc = b * b - 4 * a * c;
 654: 
 655:     if (disc < 0)
 656:       return 0;
 657: 
 658:     if (disc == 0)
 659:       {
 660:     // The GNU Scientific Library returns two identical results here.
 661:     // We just return one.
 662:     res[0] = -0.5 * b / a;
 663:     return 1;
 664:       }
 665: 
 666:     // disc > 0
 667:     if (b == 0)
 668:       {
 669:     double r;
 670: 
 671:     r = Math.abs(0.5 * Math.sqrt(disc) / a);
 672:     res[0] = -r;
 673:     res[1] = r;
 674:       }
 675:     else
 676:       {
 677:     double sgnb;
 678:     double temp;
 679: 
 680:     sgnb = (b > 0 ? 1 : -1);
 681:     temp = -0.5 * (b + sgnb * Math.sqrt(disc));
 682: 
 683:     // The GNU Scientific Library sorts the result here. We don't.
 684:     res[0] = temp / a;
 685:     res[1] = c / temp;
 686:       }
 687:     return 2;
 688:   }
 689: 
 690:   /**
 691:    * Determines whether a point is inside the area bounded
 692:    * by the curve and the straight line connecting its end points.
 693:    *
 694:    * <p><img src="doc-files/QuadCurve2D-5.png" width="350" height="180"
 695:    * alt="A drawing of the area spanned by the curve" />
 696:    *
 697:    * <p>The above drawing illustrates in which area points are
 698:    * considered &#x201c;inside&#x201d; a QuadCurve2D.
 699:    */
 700:   public boolean contains(double x, double y)
 701:   {
 702:     if (! getBounds2D().contains(x, y))
 703:       return false;
 704: 
 705:     return ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0);
 706:   }
 707: 
 708:   /**
 709:    * Determines whether a point is inside the area bounded
 710:    * by the curve and the straight line connecting its end points.
 711:    *
 712:    * <p><img src="doc-files/QuadCurve2D-5.png" width="350" height="180"
 713:    * alt="A drawing of the area spanned by the curve" />
 714:    *
 715:    * <p>The above drawing illustrates in which area points are
 716:    * considered &#x201c;inside&#x201d; a QuadCurve2D.
 717:    */
 718:   public boolean contains(Point2D p)
 719:   {
 720:     return contains(p.getX(), p.getY());
 721:   }
 722: 
 723:   /**
 724:    * Determines whether any part of a rectangle is inside the area bounded
 725:    * by the curve and the straight line connecting its end points.
 726:    *
 727:    * <p><img src="doc-files/QuadCurve2D-5.png" width="350" height="180"
 728:    * alt="A drawing of the area spanned by the curve" />
 729:    *
 730:    * <p>The above drawing illustrates in which area points are
 731:    * considered &#x201c;inside&#x201d; in a CubicCurve2D.
 732:    */
 733:   public boolean intersects(double x, double y, double w, double h)
 734:   {
 735:     if (! getBounds2D().contains(x, y, w, h))
 736:       return false;
 737: 
 738:     /* Does any edge intersect? */
 739:     if (getAxisIntersections(x, y, true, w) != 0 /* top */
 740:         || getAxisIntersections(x, y + h, true, w) != 0 /* bottom */
 741:         || getAxisIntersections(x + w, y, false, h) != 0 /* right */
 742:         || getAxisIntersections(x, y, false, h) != 0) /* left */
 743:       return true;
 744: 
 745:     /* No intersections, is any point inside? */
 746:     if ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0)
 747:       return true;
 748: 
 749:     return false;
 750:   }
 751: 
 752:   /**
 753:    * Determines whether any part of a Rectangle2D is inside the area bounded 
 754:    * by the curve and the straight line connecting its end points.
 755:    * @see #intersects(double, double, double, double)
 756:    */
 757:   public boolean intersects(Rectangle2D r)
 758:   {
 759:     return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
 760:   }
 761: 
 762:   /**
 763:    * Determines whether a rectangle is entirely inside the area bounded
 764:    * by the curve and the straight line connecting its end points.
 765:    *
 766:    * <p><img src="doc-files/QuadCurve2D-5.png" width="350" height="180"
 767:    * alt="A drawing of the area spanned by the curve" />
 768:    *
 769:    * <p>The above drawing illustrates in which area points are
 770:    * considered &#x201c;inside&#x201d; a QuadCurve2D.
 771:    * @see #contains(double, double)
 772:    */
 773:   public boolean contains(double x, double y, double w, double h)
 774:   {
 775:     if (! getBounds2D().intersects(x, y, w, h))
 776:       return false;
 777: 
 778:     /* Does any edge intersect? */
 779:     if (getAxisIntersections(x, y, true, w) != 0 /* top */
 780:         || getAxisIntersections(x, y + h, true, w) != 0 /* bottom */
 781:         || getAxisIntersections(x + w, y, false, h) != 0 /* right */
 782:         || getAxisIntersections(x, y, false, h) != 0) /* left */
 783:       return false;
 784: 
 785:     /* No intersections, is any point inside? */
 786:     if ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0)
 787:       return true;
 788: 
 789:     return false;
 790:   }
 791: 
 792:   /**
 793:    * Determines whether a Rectangle2D is entirely inside the area that is 
 794:    * bounded by the curve and the straight line connecting its end points.
 795:    * @see #contains(double, double, double, double)
 796:    */
 797:   public boolean contains(Rectangle2D r)
 798:   {
 799:     return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
 800:   }
 801: 
 802:   /**
 803:    * Determines the smallest rectangle that encloses the
 804:    * curve&#x2019;s start, end and control point. As the illustration
 805:    * below shows, the invisible control point may cause the bounds to
 806:    * be much larger than the area that is actually covered by the
 807:    * curve.
 808:    *
 809:    * <p><img src="doc-files/QuadCurve2D-2.png" width="350" height="180"
 810:    * alt="An illustration of the bounds of a QuadCurve2D" />
 811:    */
 812:   public Rectangle getBounds()
 813:   {
 814:     return getBounds2D().getBounds();
 815:   }
 816: 
 817:   public PathIterator getPathIterator(final AffineTransform at)
 818:   {
 819:     return new PathIterator()
 820:       {
 821:     /** Current coordinate. */
 822:     private int current = 0;
 823: 
 824:     public int getWindingRule()
 825:     {
 826:       return WIND_NON_ZERO;
 827:     }
 828: 
 829:     public boolean isDone()
 830:     {
 831:       return current >= 2;
 832:     }
 833: 
 834:     public void next()
 835:     {
 836:       current++;
 837:     }
 838: 
 839:     public int currentSegment(float[] coords)
 840:     {
 841:       int result;
 842:       switch (current)
 843:         {
 844:         case 0:
 845:           coords[0] = (float) getX1();
 846:           coords[1] = (float) getY1();
 847:           result = SEG_MOVETO;
 848:           break;
 849:         case 1:
 850:           coords[0] = (float) getCtrlX();
 851:           coords[1] = (float) getCtrlY();
 852:           coords[2] = (float) getX2();
 853:           coords[3] = (float) getY2();
 854:           result = SEG_QUADTO;
 855:           break;
 856:         default:
 857:           throw new NoSuchElementException("quad iterator out of bounds");
 858:         }
 859:       if (at != null)
 860:         at.transform(coords, 0, coords, 0, 2);
 861:       return result;
 862:     }
 863: 
 864:     public int currentSegment(double[] coords)
 865:     {
 866:       int result;
 867:       switch (current)
 868:         {
 869:         case 0:
 870:           coords[0] = getX1();
 871:           coords[1] = getY1();
 872:           result = SEG_MOVETO;
 873:           break;
 874:         case 1:
 875:           coords[0] = getCtrlX();
 876:           coords[1] = getCtrlY();
 877:           coords[2] = getX2();
 878:           coords[3] = getY2();
 879:           result = SEG_QUADTO;
 880:           break;
 881:         default:
 882:           throw new NoSuchElementException("quad iterator out of bounds");
 883:         }
 884:       if (at != null)
 885:         at.transform(coords, 0, coords, 0, 2);
 886:       return result;
 887:     }
 888:       };
 889:   }
 890: 
 891:   public PathIterator getPathIterator(AffineTransform at, double flatness)
 892:   {
 893:     return new FlatteningPathIterator(getPathIterator(at), flatness);
 894:   }
 895: 
 896:   /**
 897:    * Creates a new curve with the same contents as this one.
 898:    *
 899:    * @return the clone.
 900:    */
 901:   public Object clone()
 902:   {
 903:     try
 904:       {
 905:     return super.clone();
 906:       }
 907:     catch (CloneNotSupportedException e)
 908:       {
 909:     throw (Error) new InternalError().initCause(e); // Impossible
 910:       }
 911:   }
 912: 
 913:   /**
 914:    * Helper method used by contains() and intersects() methods
 915:    * Return the number of curve/line intersections on a given axis
 916:    * extending from a certain point. useYaxis is true for using the Y axis,
 917:    * @param x x coordinate of the origin point
 918:    * @param y y coordinate of the origin point
 919:    * @param useYaxis axis to follow, if true the positive Y axis is used,
 920:    * false uses the positive X axis.
 921:    *
 922:    * This is an implementation of the line-crossings algorithm,
 923:    * Detailed in an article on Eric Haines' page:
 924:    * http://www.acm.org/tog/editors/erich/ptinpoly/
 925:    */
 926:   private int getAxisIntersections(double x, double y, boolean useYaxis,
 927:                                    double distance)
 928:   {
 929:     int nCrossings = 0;
 930:     double a0;
 931:     double a1;
 932:     double a2;
 933:     double b0;
 934:     double b1;
 935:     double b2;
 936:     double[] r = new double[3];
 937:     int nRoots;
 938: 
 939:     a0 = a2 = 0.0;
 940: 
 941:     if (useYaxis)
 942:       {
 943:     a0 = getY1() - y;
 944:     a1 = getCtrlY() - y;
 945:     a2 = getY2() - y;
 946:     b0 = getX1() - x;
 947:     b1 = getCtrlX() - x;
 948:     b2 = getX2() - x;
 949:       }
 950:     else
 951:       {
 952:     a0 = getX1() - x;
 953:     a1 = getCtrlX() - x;
 954:     a2 = getX2() - x;
 955:     b0 = getY1() - y;
 956:     b1 = getCtrlY() - y;
 957:     b2 = getY2() - y;
 958:       }
 959: 
 960:     /* If the axis intersects a start/endpoint, shift it up by some small 
 961:        amount to guarantee the line is 'inside'
 962:        If this is not done,bad behaviour may result for points on that axis. */
 963:     if (a0 == 0.0 || a2 == 0.0)
 964:       {
 965:     double small = getFlatness() * EPSILON;
 966:     if (a0 == 0.0)
 967:       a0 -= small;
 968: 
 969:     if (a2 == 0.0)
 970:       a2 -= small;
 971:       }
 972: 
 973:     r[0] = a0;
 974:     r[1] = 2 * (a1 - a0);
 975:     r[2] = (a2 - 2 * a1 + a0);
 976: 
 977:     nRoots = solveQuadratic(r);
 978:     for (int i = 0; i < nRoots; i++)
 979:       {
 980:     double t = r[i];
 981:     if (t >= 0.0 && t <= 1.0)
 982:       {
 983:         double crossing = t * t * (b2 - 2 * b1 + b0) + 2 * t * (b1 - b0)
 984:                           + b0;
 985:         /* single root is always doubly degenerate in quads */
 986:         if (crossing > 0 && crossing < distance)
 987:           nCrossings += (nRoots == 1) ? 2 : 1;
 988:       }
 989:       }
 990: 
 991:     if (useYaxis)
 992:       {
 993:     if (Line2D.linesIntersect(b0, a0, b2, a2, EPSILON, 0.0, distance, 0.0))
 994:       nCrossings++;
 995:       }
 996:     else
 997:       {
 998:     if (Line2D.linesIntersect(a0, b0, a2, b2, 0.0, EPSILON, 0.0, distance))
 999:       nCrossings++;
1000:       }
1001: 
1002:     return (nCrossings);
1003:   }
1004: 
1005:   /**
1006:    * A two-dimensional curve that is parameterized with a quadratic
1007:    * function and stores coordinate values in double-precision
1008:    * floating-point format.
1009:    *
1010:    * @see QuadCurve2D.Float
1011:    *
1012:    * @author Eric Blake (ebb9@email.byu.edu)
1013:    * @author Sascha Brawer (brawer@dandelis.ch)
1014:    */
1015:   public static class Double extends QuadCurve2D
1016:   {
1017:     /**
1018:      * The <i>x</i> coordinate of the curve&#x2019;s start point.
1019:      */
1020:     public double x1;
1021: 
1022:     /**
1023:      * The <i>y</i> coordinate of the curve&#x2019;s start point.
1024:      */
1025:     public double y1;
1026: 
1027:     /**
1028:      * The <i>x</i> coordinate of the curve&#x2019;s control point.
1029:      */
1030:     public double ctrlx;
1031: 
1032:     /**
1033:      * The <i>y</i> coordinate of the curve&#x2019;s control point.
1034:      */
1035:     public double ctrly;
1036: 
1037:     /**
1038:      * The <i>x</i> coordinate of the curve&#x2019;s end point.
1039:      */
1040:     public double x2;
1041: 
1042:     /**
1043:      * The <i>y</i> coordinate of the curve&#x2019;s end point.
1044:      */
1045:     public double y2;
1046: 
1047:     /**
1048:      * Constructs a new QuadCurve2D that stores its coordinate values
1049:      * in double-precision floating-point format. All points are
1050:      * initially at position (0, 0).
1051:      */
1052:     public Double()
1053:     {
1054:     }
1055: 
1056:     /**
1057:      * Constructs a new QuadCurve2D that stores its coordinate values
1058:      * in double-precision floating-point format, specifying the
1059:      * initial position of each point.
1060:      *
1061:      * @param x1 the <i>x</i> coordinate of the curve&#x2019;s start
1062:      * point.
1063:      *
1064:      * @param y1 the <i>y</i> coordinate of the curve&#x2019;s start
1065:      * point.
1066:      *
1067:      * @param cx the <i>x</i> coordinate of the curve&#x2019;s control
1068:      * point.
1069:      *
1070:      * @param cy the <i>y</i> coordinate of the curve&#x2019;s control
1071:      * point.
1072:      *
1073:      * @param x2 the <i>x</i> coordinate of the curve&#x2019;s end
1074:      * point.
1075:      *
1076:      * @param y2 the <i>y</i> coordinate of the curve&#x2019;s end
1077:      * point.
1078:      */
1079:     public Double(double x1, double y1, double cx, double cy, double x2,
1080:                   double y2)
1081:     {
1082:       this.x1 = x1;
1083:       this.y1 = y1;
1084:       ctrlx = cx;
1085:       ctrly = cy;
1086:       this.x2 = x2;
1087:       this.y2 = y2;
1088:     }
1089: 
1090:     /**
1091:      * Returns the <i>x</i> coordinate of the curve&#x2019;s start
1092:      * point.
1093:      */
1094:     public double getX1()
1095:     {
1096:       return x1;
1097:     }
1098: 
1099:     /**
1100:      * Returns the <i>y</i> coordinate of the curve&#x2019;s start
1101:      * point.
1102:      */
1103:     public double getY1()
1104:     {
1105:       return y1;
1106:     }
1107: 
1108:     /**
1109:      * Returns the curve&#x2019;s start point.
1110:      */
1111:     public Point2D getP1()
1112:     {
1113:       return new Point2D.Double(x1, y1);
1114:     }
1115: 
1116:     /**
1117:      * Returns the <i>x</i> coordinate of the curve&#x2019;s control
1118:      * point.
1119:      */
1120:     public double getCtrlX()
1121:     {
1122:       return ctrlx;
1123:     }
1124: 
1125:     /**
1126:      * Returns the <i>y</i> coordinate of the curve&#x2019;s control
1127:      * point.
1128:      */
1129:     public double getCtrlY()
1130:     {
1131:       return ctrly;
1132:     }
1133: 
1134:     /**
1135:      * Returns the curve&#x2019;s control point.
1136:      */
1137:     public Point2D getCtrlPt()
1138:     {
1139:       return new Point2D.Double(ctrlx, ctrly);
1140:     }
1141: 
1142:     /**
1143:      * Returns the <i>x</i> coordinate of the curve&#x2019;s end
1144:      * point.
1145:      */
1146:     public double getX2()
1147:     {
1148:       return x2;
1149:     }
1150: 
1151:     /**
1152:      * Returns the <i>y</i> coordinate of the curve&#x2019;s end
1153:      * point.
1154:      */
1155:     public double getY2()
1156:     {
1157:       return y2;
1158:     }
1159: 
1160:     /**
1161:      * Returns the curve&#x2019;s end point.
1162:      */
1163:     public Point2D getP2()
1164:     {
1165:       return new Point2D.Double(x2, y2);
1166:     }
1167: 
1168:     /**
1169:      * Changes the geometry of the curve.
1170:      *
1171:      * @param x1 the <i>x</i> coordinate of the curve&#x2019;s new
1172:      * start point.
1173:      *
1174:      * @param y1 the <i>y</i> coordinate of the curve&#x2019;s new
1175:      * start point.
1176:      *
1177:      * @param cx the <i>x</i> coordinate of the curve&#x2019;s new
1178:      * control point.
1179:      *
1180:      * @param cy the <i>y</i> coordinate of the curve&#x2019;s new
1181:      * control point.
1182:      *
1183:      * @param x2 the <i>x</i> coordinate of the curve&#x2019;s new
1184:      * end point.
1185:      *
1186:      * @param y2 the <i>y</i> coordinate of the curve&#x2019;s new
1187:      * end point.
1188:      */
1189:     public void setCurve(double x1, double y1, double cx, double cy,
1190:                          double x2, double y2)
1191:     {
1192:       this.x1 = x1;
1193:       this.y1 = y1;
1194:       ctrlx = cx;
1195:       ctrly = cy;
1196:       this.x2 = x2;
1197:       this.y2 = y2;
1198:     }
1199: 
1200:     /**
1201:      * Determines the smallest rectangle that encloses the
1202:      * curve&#x2019;s start, end and control point. As the
1203:      * illustration below shows, the invisible control point may cause
1204:      * the bounds to be much larger than the area that is actually
1205:      * covered by the curve.
1206:      *
1207:      * <p><img src="doc-files/QuadCurve2D-2.png" width="350" height="180"
1208:      * alt="An illustration of the bounds of a QuadCurve2D" />
1209:      */
1210:     public Rectangle2D getBounds2D()
1211:     {
1212:       double nx1 = Math.min(Math.min(x1, ctrlx), x2);
1213:       double ny1 = Math.min(Math.min(y1, ctrly), y2);
1214:       double nx2 = Math.max(Math.max(x1, ctrlx), x2);
1215:       double ny2 = Math.max(Math.max(y1, ctrly), y2);
1216:       return new Rectangle2D.Double(nx1, ny1, nx2 - nx1, ny2 - ny1);
1217:     }
1218:   }
1219: 
1220:   /**
1221:    * A two-dimensional curve that is parameterized with a quadratic
1222:    * function and stores coordinate values in single-precision
1223:    * floating-point format.
1224:    *
1225:    * @see QuadCurve2D.Double
1226:    *
1227:    * @author Eric Blake (ebb9@email.byu.edu)
1228:    * @author Sascha Brawer (brawer@dandelis.ch)
1229:    */
1230:   public static class Float extends QuadCurve2D
1231:   {
1232:     /**
1233:      * The <i>x</i> coordinate of the curve&#x2019;s start point.
1234:      */
1235:     public float x1;
1236: 
1237:     /**
1238:      * The <i>y</i> coordinate of the curve&#x2019;s start point.
1239:      */
1240:     public float y1;
1241: 
1242:     /**
1243:      * The <i>x</i> coordinate of the curve&#x2019;s control point.
1244:      */
1245:     public float ctrlx;
1246: 
1247:     /**
1248:      * The <i>y</i> coordinate of the curve&#x2019;s control point.
1249:      */
1250:     public float ctrly;
1251: 
1252:     /**
1253:      * The <i>x</i> coordinate of the curve&#x2019;s end point.
1254:      */
1255:     public float x2;
1256: 
1257:     /**
1258:      * The <i>y</i> coordinate of the curve&#x2019;s end point.
1259:      */
1260:     public float y2;
1261: 
1262:     /**
1263:      * Constructs a new QuadCurve2D that stores its coordinate values
1264:      * in single-precision floating-point format. All points are
1265:      * initially at position (0, 0).
1266:      */
1267:     public Float()
1268:     {
1269:     }
1270: 
1271:     /**
1272:      * Constructs a new QuadCurve2D that stores its coordinate values
1273:      * in single-precision floating-point format, specifying the
1274:      * initial position of each point.
1275:      *
1276:      * @param x1 the <i>x</i> coordinate of the curve&#x2019;s start
1277:      * point.
1278:      *
1279:      * @param y1 the <i>y</i> coordinate of the curve&#x2019;s start
1280:      * point.
1281:      *
1282:      * @param cx the <i>x</i> coordinate of the curve&#x2019;s control
1283:      * point.
1284:      *
1285:      * @param cy the <i>y</i> coordinate of the curve&#x2019;s control
1286:      * point.
1287:      *
1288:      * @param x2 the <i>x</i> coordinate of the curve&#x2019;s end
1289:      * point.
1290:      *
1291:      * @param y2 the <i>y</i> coordinate of the curve&#x2019;s end
1292:      * point.
1293:      */
1294:     public Float(float x1, float y1, float cx, float cy, float x2, float y2)
1295:     {
1296:       this.x1 = x1;
1297:       this.y1 = y1;
1298:       ctrlx = cx;
1299:       ctrly = cy;
1300:       this.x2 = x2;
1301:       this.y2 = y2;
1302:     }
1303: 
1304:     /**
1305:      * Returns the <i>x</i> coordinate of the curve&#x2019;s start
1306:      * point.
1307:      */
1308:     public double getX1()
1309:     {
1310:       return x1;
1311:     }
1312: 
1313:     /**
1314:      * Returns the <i>y</i> coordinate of the curve&#x2019;s start
1315:      * point.
1316:      */
1317:     public double getY1()
1318:     {
1319:       return y1;
1320:     }
1321: 
1322:     /**
1323:      * Returns the curve&#x2019;s start point.
1324:      */
1325:     public Point2D getP1()
1326:     {
1327:       return new Point2D.Float(x1, y1);
1328:     }
1329: 
1330:     /**
1331:      * Returns the <i>x</i> coordinate of the curve&#x2019;s control
1332:      * point.
1333:      */
1334:     public double getCtrlX()
1335:     {
1336:       return ctrlx;
1337:     }
1338: 
1339:     /**
1340:      * Returns the <i>y</i> coordinate of the curve&#x2019;s control
1341:      * point.
1342:      */
1343:     public double getCtrlY()
1344:     {
1345:       return ctrly;
1346:     }
1347: 
1348:     /**
1349:      * Returns the curve&#x2019;s control point.
1350:      */
1351:     public Point2D getCtrlPt()
1352:     {
1353:       return new Point2D.Float(ctrlx, ctrly);
1354:     }
1355: 
1356:     /**
1357:      * Returns the <i>x</i> coordinate of the curve&#x2019;s end
1358:      * point.
1359:      */
1360:     public double getX2()
1361:     {
1362:       return x2;
1363:     }
1364: 
1365:     /**
1366:      * Returns the <i>y</i> coordinate of the curve&#x2019;s end
1367:      * point.
1368:      */
1369:     public double getY2()
1370:     {
1371:       return y2;
1372:     }
1373: 
1374:     /**
1375:      * Returns the curve&#x2019;s end point.
1376:      */
1377:     public Point2D getP2()
1378:     {
1379:       return new Point2D.Float(x2, y2);
1380:     }
1381: 
1382:     /**
1383:      * Changes the geometry of the curve, specifying coordinate values
1384:      * as double-precision floating-point numbers.
1385:      *
1386:      * @param x1 the <i>x</i> coordinate of the curve&#x2019;s new
1387:      * start point.
1388:      *
1389:      * @param y1 the <i>y</i> coordinate of the curve&#x2019;s new
1390:      * start point.
1391:      *
1392:      * @param cx the <i>x</i> coordinate of the curve&#x2019;s new
1393:      * control point.
1394:      *
1395:      * @param cy the <i>y</i> coordinate of the curve&#x2019;s new
1396:      * control point.
1397:      *
1398:      * @param x2 the <i>x</i> coordinate of the curve&#x2019;s new
1399:      * end point.
1400:      *
1401:      * @param y2 the <i>y</i> coordinate of the curve&#x2019;s new
1402:      * end point.
1403:      */
1404:     public void setCurve(double x1, double y1, double cx, double cy,
1405:                          double x2, double y2)
1406:     {
1407:       this.x1 = (float) x1;
1408:       this.y1 = (float) y1;
1409:       ctrlx = (float) cx;
1410:       ctrly = (float) cy;
1411:       this.x2 = (float) x2;
1412:       this.y2 = (float) y2;
1413:     }
1414: 
1415:     /**
1416:      * Changes the geometry of the curve, specifying coordinate values
1417:      * as single-precision floating-point numbers.
1418:      *
1419:      * @param x1 the <i>x</i> coordinate of the curve&#x2019;s new
1420:      * start point.
1421:      *
1422:      * @param y1 the <i>y</i> coordinate of the curve&#x2019;s new
1423:      * start point.
1424:      *
1425:      * @param cx the <i>x</i> coordinate of the curve&#x2019;s new
1426:      * control point.
1427:      *
1428:      * @param cy the <i>y</i> coordinate of the curve&#x2019;s new
1429:      * control point.
1430:      *
1431:      * @param x2 the <i>x</i> coordinate of the curve&#x2019;s new
1432:      * end point.
1433:      *
1434:      * @param y2 the <i>y</i> coordinate of the curve&#x2019;s new
1435:      * end point.
1436:      */
1437:     public void setCurve(float x1, float y1, float cx, float cy, float x2,
1438:                          float y2)
1439:     {
1440:       this.x1 = x1;
1441:       this.y1 = y1;
1442:       ctrlx = cx;
1443:       ctrly = cy;
1444:       this.x2 = x2;
1445:       this.y2 = y2;
1446:     }
1447: 
1448:     /**
1449:      * Determines the smallest rectangle that encloses the
1450:      * curve&#x2019;s start, end and control point. As the
1451:      * illustration below shows, the invisible control point may cause
1452:      * the bounds to be much larger than the area that is actually
1453:      * covered by the curve.
1454:      *
1455:      * <p><img src="doc-files/QuadCurve2D-2.png" width="350" height="180"
1456:      * alt="An illustration of the bounds of a QuadCurve2D" />
1457:      */
1458:     public Rectangle2D getBounds2D()
1459:     {
1460:       float nx1 = (float) Math.min(Math.min(x1, ctrlx), x2);
1461:       float ny1 = (float) Math.min(Math.min(y1, ctrly), y2);
1462:       float nx2 = (float) Math.max(Math.max(x1, ctrlx), x2);
1463:       float ny2 = (float) Math.max(Math.max(y1, ctrly), y2);
1464:       return new Rectangle2D.Float(nx1, ny1, nx2 - nx1, ny2 - ny1);
1465:     }
1466:   }
1467: }