QuadCurve2D.java revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17/**
18 * @author Denis M. Kishenko
19 * @version $Revision$
20 */
21
22package java.awt.geom;
23
24import java.awt.Rectangle;
25import java.awt.Shape;
26import java.util.NoSuchElementException;
27
28import org.apache.harmony.awt.gl.Crossing;
29import org.apache.harmony.awt.internal.nls.Messages;
30
31/**
32 * The Class QuadCurve2D is a Shape that represents a segment of a quadratic
33 * (Bezier) curve. The curved segment is determined by three points: a start
34 * point, an end point, and a control point. The line from the control point to
35 * the starting point gives the tangent to the curve at the starting point, and
36 * the line from the control point to the end point gives the tangent to the
37 * curve at the end point.
38 *
39 * @since Android 1.0
40 */
41public abstract class QuadCurve2D implements Shape, Cloneable {
42
43    /**
44     * The Class Float is the subclass of QuadCurve2D that has all of its data
45     * values stored with float-level precision.
46     *
47     * @since Android 1.0
48     */
49    public static class Float extends QuadCurve2D {
50
51        /**
52         * The x coordinate of the starting point of the curved segment.
53         */
54        public float x1;
55
56        /**
57         * The y coordinate of the starting point of the curved segment.
58         */
59        public float y1;
60
61        /**
62         * The x coordinate of the control point.
63         */
64        public float ctrlx;
65
66        /**
67         * The y coordinate of the control point.
68         */
69        public float ctrly;
70
71        /**
72         * The x coordinate of the end point of the curved segment.
73         */
74        public float x2;
75
76        /**
77         * The y coordinate of the end point of the curved segment.
78         */
79        public float y2;
80
81        /**
82         * Instantiates a new float-valued QuadCurve2D with all coordinate
83         * values set to zero.
84         */
85        public Float() {
86        }
87
88        /**
89         * Instantiates a new float-valued QuadCurve2D with the specified
90         * coordinate values.
91         *
92         * @param x1
93         *            the x coordinate of the starting point of the curved
94         *            segment.
95         * @param y1
96         *            the y coordinate of the starting point of the curved
97         *            segment.
98         * @param ctrlx
99         *            the x coordinate of the control point.
100         * @param ctrly
101         *            the y coordinate of the control point.
102         * @param x2
103         *            the x coordinate of the end point of the curved segment.
104         * @param y2
105         *            the y coordinate of the end point of the curved segment.
106         */
107        public Float(float x1, float y1, float ctrlx, float ctrly, float x2, float y2) {
108            setCurve(x1, y1, ctrlx, ctrly, x2, y2);
109        }
110
111        @Override
112        public double getX1() {
113            return x1;
114        }
115
116        @Override
117        public double getY1() {
118            return y1;
119        }
120
121        @Override
122        public double getCtrlX() {
123            return ctrlx;
124        }
125
126        @Override
127        public double getCtrlY() {
128            return ctrly;
129        }
130
131        @Override
132        public double getX2() {
133            return x2;
134        }
135
136        @Override
137        public double getY2() {
138            return y2;
139        }
140
141        @Override
142        public Point2D getP1() {
143            return new Point2D.Float(x1, y1);
144        }
145
146        @Override
147        public Point2D getCtrlPt() {
148            return new Point2D.Float(ctrlx, ctrly);
149        }
150
151        @Override
152        public Point2D getP2() {
153            return new Point2D.Float(x2, y2);
154        }
155
156        @Override
157        public void setCurve(double x1, double y1, double ctrlx, double ctrly, double x2, double y2) {
158            this.x1 = (float)x1;
159            this.y1 = (float)y1;
160            this.ctrlx = (float)ctrlx;
161            this.ctrly = (float)ctrly;
162            this.x2 = (float)x2;
163            this.y2 = (float)y2;
164        }
165
166        /**
167         * Sets the data values of the curve.
168         *
169         * @param x1
170         *            the x coordinate of the starting point of the curved
171         *            segment.
172         * @param y1
173         *            the y coordinate of the starting point of the curved
174         *            segment.
175         * @param ctrlx
176         *            the x coordinate of the control point.
177         * @param ctrly
178         *            the y coordinate of the control point.
179         * @param x2
180         *            the x coordinate of the end point of the curved segment.
181         * @param y2
182         *            the y coordinate of the end point of the curved segment.
183         */
184        public void setCurve(float x1, float y1, float ctrlx, float ctrly, float x2, float y2) {
185            this.x1 = x1;
186            this.y1 = y1;
187            this.ctrlx = ctrlx;
188            this.ctrly = ctrly;
189            this.x2 = x2;
190            this.y2 = y2;
191        }
192
193        public Rectangle2D getBounds2D() {
194            float rx0 = Math.min(Math.min(x1, x2), ctrlx);
195            float ry0 = Math.min(Math.min(y1, y2), ctrly);
196            float rx1 = Math.max(Math.max(x1, x2), ctrlx);
197            float ry1 = Math.max(Math.max(y1, y2), ctrly);
198            return new Rectangle2D.Float(rx0, ry0, rx1 - rx0, ry1 - ry0);
199        }
200    }
201
202    /**
203     * The Class Double is the subclass of QuadCurve2D that has all of its data
204     * values stored with double-level precision.
205     *
206     * @since Android 1.0
207     */
208    public static class Double extends QuadCurve2D {
209
210        /**
211         * The x coordinate of the starting point of the curved segment.
212         */
213        public double x1;
214
215        /**
216         * The y coordinate of the starting point of the curved segment.
217         */
218        public double y1;
219
220        /**
221         * The x coordinate of the control point.
222         */
223        public double ctrlx;
224
225        /**
226         * The y coordinate of the control point.
227         */
228        public double ctrly;
229
230        /**
231         * The x coordinate of the end point of the curved segment.
232         */
233        public double x2;
234
235        /**
236         * The y coordinate of the end point of the curved segment.
237         */
238        public double y2;
239
240        /**
241         * Instantiates a new double-valued QuadCurve2D with all coordinate
242         * values set to zero.
243         */
244        public Double() {
245        }
246
247        /**
248         * Instantiates a new double-valued QuadCurve2D with the specified
249         * coordinate values.
250         *
251         * @param x1
252         *            the x coordinate of the starting point of the curved
253         *            segment.
254         * @param y1
255         *            the y coordinate of the starting point of the curved
256         *            segment.
257         * @param ctrlx
258         *            the x coordinate of the control point.
259         * @param ctrly
260         *            the y coordinate of the control point.
261         * @param x2
262         *            the x coordinate of the end point of the curved segment.
263         * @param y2
264         *            the y coordinate of the end point of the curved segment.
265         */
266        public Double(double x1, double y1, double ctrlx, double ctrly, double x2, double y2) {
267            setCurve(x1, y1, ctrlx, ctrly, x2, y2);
268        }
269
270        @Override
271        public double getX1() {
272            return x1;
273        }
274
275        @Override
276        public double getY1() {
277            return y1;
278        }
279
280        @Override
281        public double getCtrlX() {
282            return ctrlx;
283        }
284
285        @Override
286        public double getCtrlY() {
287            return ctrly;
288        }
289
290        @Override
291        public double getX2() {
292            return x2;
293        }
294
295        @Override
296        public double getY2() {
297            return y2;
298        }
299
300        @Override
301        public Point2D getP1() {
302            return new Point2D.Double(x1, y1);
303        }
304
305        @Override
306        public Point2D getCtrlPt() {
307            return new Point2D.Double(ctrlx, ctrly);
308        }
309
310        @Override
311        public Point2D getP2() {
312            return new Point2D.Double(x2, y2);
313        }
314
315        @Override
316        public void setCurve(double x1, double y1, double ctrlx, double ctrly, double x2, double y2) {
317            this.x1 = x1;
318            this.y1 = y1;
319            this.ctrlx = ctrlx;
320            this.ctrly = ctrly;
321            this.x2 = x2;
322            this.y2 = y2;
323        }
324
325        public Rectangle2D getBounds2D() {
326            double rx0 = Math.min(Math.min(x1, x2), ctrlx);
327            double ry0 = Math.min(Math.min(y1, y2), ctrly);
328            double rx1 = Math.max(Math.max(x1, x2), ctrlx);
329            double ry1 = Math.max(Math.max(y1, y2), ctrly);
330            return new Rectangle2D.Double(rx0, ry0, rx1 - rx0, ry1 - ry0);
331        }
332    }
333
334    /*
335     * QuadCurve2D path iterator
336     */
337    /**
338     * The PathIterator for a Quad2D curve.
339     */
340    class Iterator implements PathIterator {
341
342        /**
343         * The source QuadCurve2D object.
344         */
345        QuadCurve2D c;
346
347        /**
348         * The path iterator transformation.
349         */
350        AffineTransform t;
351
352        /**
353         * The current segment index.
354         */
355        int index;
356
357        /**
358         * Constructs a new QuadCurve2D.Iterator for given curve and
359         * transformation
360         *
361         * @param q
362         *            the source QuadCurve2D object.
363         * @param t
364         *            the AffineTransform that acts on the coordinates before
365         *            returning them (or null).
366         */
367        Iterator(QuadCurve2D q, AffineTransform t) {
368            this.c = q;
369            this.t = t;
370        }
371
372        public int getWindingRule() {
373            return WIND_NON_ZERO;
374        }
375
376        public boolean isDone() {
377            return (index > 1);
378        }
379
380        public void next() {
381            index++;
382        }
383
384        public int currentSegment(double[] coords) {
385            if (isDone()) {
386                // awt.4B=Iterator out of bounds
387                throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
388            }
389            int type;
390            int count;
391            if (index == 0) {
392                type = SEG_MOVETO;
393                coords[0] = c.getX1();
394                coords[1] = c.getY1();
395                count = 1;
396            } else {
397                type = SEG_QUADTO;
398                coords[0] = c.getCtrlX();
399                coords[1] = c.getCtrlY();
400                coords[2] = c.getX2();
401                coords[3] = c.getY2();
402                count = 2;
403            }
404            if (t != null) {
405                t.transform(coords, 0, coords, 0, count);
406            }
407            return type;
408        }
409
410        public int currentSegment(float[] coords) {
411            if (isDone()) {
412                // awt.4B=Iterator out of bounds
413                throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
414            }
415            int type;
416            int count;
417            if (index == 0) {
418                type = SEG_MOVETO;
419                coords[0] = (float)c.getX1();
420                coords[1] = (float)c.getY1();
421                count = 1;
422            } else {
423                type = SEG_QUADTO;
424                coords[0] = (float)c.getCtrlX();
425                coords[1] = (float)c.getCtrlY();
426                coords[2] = (float)c.getX2();
427                coords[3] = (float)c.getY2();
428                count = 2;
429            }
430            if (t != null) {
431                t.transform(coords, 0, coords, 0, count);
432            }
433            return type;
434        }
435
436    }
437
438    /**
439     * Instantiates a new quadratic curve.
440     */
441    protected QuadCurve2D() {
442    }
443
444    /**
445     * Gets the x coordinate of the starting point.
446     *
447     * @return the x coordinate of the starting point.
448     */
449    public abstract double getX1();
450
451    /**
452     * Gets the y coordinate of the starting point.
453     *
454     * @return the y coordinate of the starting point.
455     */
456    public abstract double getY1();
457
458    /**
459     * Gets the starting point.
460     *
461     * @return the starting point.
462     */
463    public abstract Point2D getP1();
464
465    /**
466     * Gets the x coordinate of the control point.
467     *
468     * @return the x coordinate of the control point.
469     */
470    public abstract double getCtrlX();
471
472    /**
473     * Gets the y coordinate of the control point.
474     *
475     * @return y coordinate of the control point.
476     */
477    public abstract double getCtrlY();
478
479    /**
480     * Gets the control point.
481     *
482     * @return the control point.
483     */
484    public abstract Point2D getCtrlPt();
485
486    /**
487     * Gets the x coordinate of the end point.
488     *
489     * @return the x coordinate of the end point.
490     */
491    public abstract double getX2();
492
493    /**
494     * Gets the y coordinate of the end point.
495     *
496     * @return the y coordinate of the end point.
497     */
498    public abstract double getY2();
499
500    /**
501     * Gets the end point.
502     *
503     * @return the end point.
504     */
505    public abstract Point2D getP2();
506
507    /**
508     * Sets the data of the curve.
509     *
510     * @param x1
511     *            the x coordinate of the starting point of the curved segment.
512     * @param y1
513     *            the y coordinate of the starting point of the curved segment.
514     * @param ctrlx
515     *            the x coordinate of the control point.
516     * @param ctrly
517     *            the y coordinate of the control point.
518     * @param x2
519     *            the x coordinate of the end point of the curved segment.
520     * @param y2
521     *            the y coordinate of the end point of the curved segment.
522     */
523    public abstract void setCurve(double x1, double y1, double ctrlx, double ctrly, double x2,
524            double y2);
525
526    /**
527     * Sets the data of the curve.
528     *
529     * @param p1
530     *            the starting point of the curved segment.
531     * @param cp
532     *            the control point.
533     * @param p2
534     *            the end point of the curved segment.
535     * @throws NullPointerException
536     *             if any of the three points is null.
537     */
538    public void setCurve(Point2D p1, Point2D cp, Point2D p2) {
539        setCurve(p1.getX(), p1.getY(), cp.getX(), cp.getY(), p2.getX(), p2.getY());
540    }
541
542    /**
543     * Sets the data of the curve by reading the data from an array of values.
544     * The values are read in the same order as the arguments of the method
545     * {@link QuadCurve2D#setCurve(double, double, double, double, double, double)}
546     * .
547     *
548     * @param coords
549     *            the array of values containing the new coordinates.
550     * @param offset
551     *            the offset of the data to read within the array.
552     * @throws ArrayIndexOutOfBoundsException
553     *             if {@code coords.length} < offset + 6.
554     * @throws NullPointerException
555     *             if the coordinate array is null.
556     */
557    public void setCurve(double[] coords, int offset) {
558        setCurve(coords[offset + 0], coords[offset + 1], coords[offset + 2], coords[offset + 3],
559                coords[offset + 4], coords[offset + 5]);
560    }
561
562    /**
563     * Sets the data of the curve by reading the data from an array of points.
564     * The values are read in the same order as the arguments of the method
565     * {@link QuadCurve2D#setCurve(Point2D, Point2D, Point2D)}.
566     *
567     * @param points
568     *            the array of points containing the new coordinates.
569     * @param offset
570     *            the offset of the data to read within the array.
571     * @throws ArrayIndexOutOfBoundsException
572     *             if points.length < offset + 3.
573     * @throws NullPointerException
574     *             if the point array is null.
575     */
576    public void setCurve(Point2D[] points, int offset) {
577        setCurve(points[offset + 0].getX(), points[offset + 0].getY(), points[offset + 1].getX(),
578                points[offset + 1].getY(), points[offset + 2].getX(), points[offset + 2].getY());
579    }
580
581    /**
582     * Sets the data of the curve by copying it from another QuadCurve2D.
583     *
584     * @param curve
585     *            the curve to copy the data points from.
586     * @throws NullPointerException
587     *             if the curve is null.
588     */
589    public void setCurve(QuadCurve2D curve) {
590        setCurve(curve.getX1(), curve.getY1(), curve.getCtrlX(), curve.getCtrlY(), curve.getX2(),
591                curve.getY2());
592    }
593
594    /**
595     * Gets the square of the distance from the control point to the straight
596     * line segment connecting the start point and the end point for this curve.
597     *
598     * @return the square of the distance from the control point to the straight
599     *         line segment connecting the start point and the end point.
600     */
601    public double getFlatnessSq() {
602        return Line2D.ptSegDistSq(getX1(), getY1(), getX2(), getY2(), getCtrlX(), getCtrlY());
603    }
604
605    /**
606     * Gets the square of the distance from the control point to the straight
607     * line segment connecting the start point and the end point.
608     *
609     * @param x1
610     *            the x coordinate of the starting point of the curved segment.
611     * @param y1
612     *            the y coordinate of the starting point of the curved segment.
613     * @param ctrlx
614     *            the x coordinate of the control point.
615     * @param ctrly
616     *            the y coordinate of the control point.
617     * @param x2
618     *            the x coordinate of the end point of the curved segment.
619     * @param y2
620     *            the y coordinate of the end point of the curved segment.
621     * @return the square of the distance from the control point to the straight
622     *         line segment connecting the start point and the end point.
623     */
624    public static double getFlatnessSq(double x1, double y1, double ctrlx, double ctrly, double x2,
625            double y2) {
626        return Line2D.ptSegDistSq(x1, y1, x2, y2, ctrlx, ctrly);
627    }
628
629    /**
630     * Gets the square of the distance from the control point to the straight
631     * line segment connecting the start point and the end point by reading the
632     * coordinates of the points from an array of values. The values are read in
633     * the same order as the arguments of the method
634     * {@link QuadCurve2D#getFlatnessSq(double, double, double, double, double, double)}
635     * .
636     *
637     * @param coords
638     *            the array of points containing the coordinates to use for the
639     *            calculation
640     * @param offset
641     *            the offset of the data to read within the array
642     * @return the square of the distance from the control point to the straight
643     *         line segment connecting the start point and the end point.
644     * @throws ArrayIndexOutOfBoundsException
645     *             if {@code coords.length} < offset + 6.
646     * @throws NullPointerException
647     *             if the coordinate array is null.
648     */
649    public static double getFlatnessSq(double coords[], int offset) {
650        return Line2D.ptSegDistSq(coords[offset + 0], coords[offset + 1], coords[offset + 4],
651                coords[offset + 5], coords[offset + 2], coords[offset + 3]);
652    }
653
654    /**
655     * Gets the distance from the control point to the straight line segment
656     * connecting the start point and the end point of this QuadCurve2D.
657     *
658     * @return the the distance from the control point to the straight line
659     *         segment connecting the start point and the end point of this
660     *         QuadCurve2D.
661     */
662    public double getFlatness() {
663        return Line2D.ptSegDist(getX1(), getY1(), getX2(), getY2(), getCtrlX(), getCtrlY());
664    }
665
666    /**
667     * Gets the distance from the control point to the straight line segment
668     * connecting the start point and the end point.
669     *
670     * @param x1
671     *            the x coordinate of the starting point of the curved segment.
672     * @param y1
673     *            the y coordinate of the starting point of the curved segment.
674     * @param ctrlx
675     *            the x coordinate of the control point.
676     * @param ctrly
677     *            the y coordinate of the control point.
678     * @param x2
679     *            the x coordinate of the end point of the curved segment.
680     * @param y2
681     *            the y coordinate of the end point of the curved segment.
682     * @return the the distance from the control point to the straight line
683     *         segment connecting the start point and the end point.
684     */
685    public static double getFlatness(double x1, double y1, double ctrlx, double ctrly, double x2,
686            double y2) {
687        return Line2D.ptSegDist(x1, y1, x2, y2, ctrlx, ctrly);
688    }
689
690    /**
691     * Gets the the distance from the control point to the straight line segment
692     * connecting the start point and the end point. The values are read in the
693     * same order as the arguments of the method
694     * {@link QuadCurve2D#getFlatness(double, double, double, double, double, double)}
695     * .
696     *
697     * @param coords
698     *            the array of points containing the coordinates to use for the
699     *            calculation.
700     * @param offset
701     *            the offset of the data to read within the array.
702     * @return the the distance from the control point to the straight line
703     *         segment connecting the start point and the end point.
704     * @throws ArrayIndexOutOfBoundsException
705     *             if {code coords.length} < offset + 6.
706     * @throws NullPointerException
707     *             if the coordinate array is null.
708     */
709    public static double getFlatness(double coords[], int offset) {
710        return Line2D.ptSegDist(coords[offset + 0], coords[offset + 1], coords[offset + 4],
711                coords[offset + 5], coords[offset + 2], coords[offset + 3]);
712    }
713
714    /**
715     * Creates the data for two quadratic curves by dividing this curve in two.
716     * The division point is the point on the curve that is closest to this
717     * curve's control point. The data of this curve is left unchanged.
718     *
719     * @param left
720     *            the QuadCurve2D where the left (start) segment's data is
721     *            written.
722     * @param right
723     *            the QuadCurve2D where the right (end) segment's data is
724     *            written.
725     * @throws NullPointerException
726     *             if either curve is null.
727     */
728    public void subdivide(QuadCurve2D left, QuadCurve2D right) {
729        subdivide(this, left, right);
730    }
731
732    /**
733     * Creates the data for two quadratic curves by dividing a source curve in
734     * two. The division point is the point on the curve that is closest to the
735     * source curve's control point. The data of the source curve is left
736     * unchanged.
737     *
738     * @param src
739     *            the curve that provides the initial data.
740     * @param left
741     *            the QuadCurve2D where the left (start) segment's data is
742     *            written.
743     * @param right
744     *            the QuadCurve2D where the right (end) segment's data is
745     *            written.
746     * @throws NullPointerException
747     *             if one of the curves is null.
748     */
749    public static void subdivide(QuadCurve2D src, QuadCurve2D left, QuadCurve2D right) {
750        double x1 = src.getX1();
751        double y1 = src.getY1();
752        double cx = src.getCtrlX();
753        double cy = src.getCtrlY();
754        double x2 = src.getX2();
755        double y2 = src.getY2();
756        double cx1 = (x1 + cx) / 2.0;
757        double cy1 = (y1 + cy) / 2.0;
758        double cx2 = (x2 + cx) / 2.0;
759        double cy2 = (y2 + cy) / 2.0;
760        cx = (cx1 + cx2) / 2.0;
761        cy = (cy1 + cy2) / 2.0;
762        if (left != null) {
763            left.setCurve(x1, y1, cx1, cy1, cx, cy);
764        }
765        if (right != null) {
766            right.setCurve(cx, cy, cx2, cy2, x2, y2);
767        }
768    }
769
770    /**
771     * Creates the data for two quadratic curves by dividing a source curve in
772     * two. The division point is the point on the curve that is closest to the
773     * source curve's control point. The data for the three curves is read and
774     * written from arrays of values in the usual order: x1, y1, cx, cy, x2, y2.
775     *
776     * @param src
777     *            the array that gives the data values for the source curve.
778     * @param srcoff
779     *            the offset in the src array to read the values from.
780     * @param left
781     *            the array where the coordinates of the start curve should be
782     *            written.
783     * @param leftOff
784     *            the offset in the left array to start writing the values.
785     * @param right
786     *            the array where the coordinates of the end curve should be
787     *            written.
788     * @param rightOff
789     *            the offset in the right array to start writing the values.
790     * @throws ArrayIndexOutOfBoundsException
791     *             if {@code src.length} < srcoff + 6 or if {@code left.length}
792     *             < leftOff + 6 or if {@code right.length} < rightOff + 6.
793     * @throws NullPointerException
794     *             if one of the arrays is null.
795     */
796    public static void subdivide(double src[], int srcoff, double left[], int leftOff,
797            double right[], int rightOff) {
798        double x1 = src[srcoff + 0];
799        double y1 = src[srcoff + 1];
800        double cx = src[srcoff + 2];
801        double cy = src[srcoff + 3];
802        double x2 = src[srcoff + 4];
803        double y2 = src[srcoff + 5];
804        double cx1 = (x1 + cx) / 2.0;
805        double cy1 = (y1 + cy) / 2.0;
806        double cx2 = (x2 + cx) / 2.0;
807        double cy2 = (y2 + cy) / 2.0;
808        cx = (cx1 + cx2) / 2.0;
809        cy = (cy1 + cy2) / 2.0;
810        if (left != null) {
811            left[leftOff + 0] = x1;
812            left[leftOff + 1] = y1;
813            left[leftOff + 2] = cx1;
814            left[leftOff + 3] = cy1;
815            left[leftOff + 4] = cx;
816            left[leftOff + 5] = cy;
817        }
818        if (right != null) {
819            right[rightOff + 0] = cx;
820            right[rightOff + 1] = cy;
821            right[rightOff + 2] = cx2;
822            right[rightOff + 3] = cy2;
823            right[rightOff + 4] = x2;
824            right[rightOff + 5] = y2;
825        }
826    }
827
828    /**
829     * Finds the roots of the quadratic polynomial. This is accomplished by
830     * finding the (real) values of x that solve the following equation:
831     * eqn[2]*x*x + eqn[1]*x + eqn[0] = 0. The solutions are written back into
832     * the array eqn starting from the index 0 in the array. The return value
833     * tells how many array elements have been changed by this method call.
834     *
835     * @param eqn
836     *            an array containing the coefficients of the quadratic
837     *            polynomial to solve.
838     * @return the number of roots of the quadratic polynomial.
839     * @throws ArrayIndexOutOfBoundsException
840     *             if {@code eqn.length} < 3.
841     * @throws NullPointerException
842     *             if the array is null.
843     */
844    public static int solveQuadratic(double eqn[]) {
845        return solveQuadratic(eqn, eqn);
846    }
847
848    /**
849     * Finds the roots of the quadratic polynomial. This is accomplished by
850     * finding the (real) values of x that solve the following equation:
851     * eqn[2]*x*x + eqn[1]*x + eqn[0] = 0. The solutions are written into the
852     * array res starting from the index 0 in the array. The return value tells
853     * how many array elements have been written by this method call.
854     *
855     * @param eqn
856     *            an array containing the coefficients of the quadratic
857     *            polynomial to solve.
858     * @param res
859     *            the array that this method writes the results into.
860     * @return the number of roots of the quadratic polynomial.
861     * @throws ArrayIndexOutOfBoundsException
862     *             if {@code eqn.length} < 3 or if {@code res.length} is less
863     *             than the number of roots.
864     * @throws NullPointerException
865     *             if either array is null.
866     */
867    public static int solveQuadratic(double eqn[], double res[]) {
868        return Crossing.solveQuad(eqn, res);
869    }
870
871    public boolean contains(double px, double py) {
872        return Crossing.isInsideEvenOdd(Crossing.crossShape(this, px, py));
873    }
874
875    public boolean contains(double rx, double ry, double rw, double rh) {
876        int cross = Crossing.intersectShape(this, rx, ry, rw, rh);
877        return cross != Crossing.CROSSING && Crossing.isInsideEvenOdd(cross);
878    }
879
880    public boolean intersects(double rx, double ry, double rw, double rh) {
881        int cross = Crossing.intersectShape(this, rx, ry, rw, rh);
882        return cross == Crossing.CROSSING || Crossing.isInsideEvenOdd(cross);
883    }
884
885    public boolean contains(Point2D p) {
886        return contains(p.getX(), p.getY());
887    }
888
889    public boolean intersects(Rectangle2D r) {
890        return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
891    }
892
893    public boolean contains(Rectangle2D r) {
894        return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
895    }
896
897    public Rectangle getBounds() {
898        return getBounds2D().getBounds();
899    }
900
901    public PathIterator getPathIterator(AffineTransform t) {
902        return new Iterator(this, t);
903    }
904
905    public PathIterator getPathIterator(AffineTransform t, double flatness) {
906        return new FlatteningPathIterator(getPathIterator(t), flatness);
907    }
908
909    @Override
910    public Object clone() {
911        try {
912            return super.clone();
913        } catch (CloneNotSupportedException e) {
914            throw new InternalError();
915        }
916    }
917
918}
919