OSDN Git Service

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