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