1/*
2 * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package java.awt.geom;
27
28import java.awt.Shape;
29import java.awt.Rectangle;
30import java.io.Serializable;
31
32/**
33 * This {@code Line2D} represents a line segment in {@code (x,y)}
34 * coordinate space.
35 * <p>
36 * This class is only the abstract superclass for all objects that
37 * store a 2D line segment.
38 * The actual storage representation of the coordinates is left to
39 * the subclass.
40 *
41 * @author      Jim Graham
42 * @since 1.2
43 */
44public abstract class Line2D implements Shape, Cloneable {
45
46    /**
47     * A line segment specified with float coordinates.
48     * @since 1.2
49     */
50    public static class Float extends Line2D implements Serializable {
51        /**
52         * The X coordinate of the start point of the line segment.
53         * @since 1.2
54         * @serial
55         */
56        public float x1;
57
58        /**
59         * The Y coordinate of the start point of the line segment.
60         * @since 1.2
61         * @serial
62         */
63        public float y1;
64
65        /**
66         * The X coordinate of the end point of the line segment.
67         * @since 1.2
68         * @serial
69         */
70        public float x2;
71
72        /**
73         * The Y coordinate of the end point of the line segment.
74         * @since 1.2
75         * @serial
76         */
77        public float y2;
78
79        /**
80         * Constructs and initializes a Line with coordinates (0, 0) &rarr; (0, 0).
81         * @since 1.2
82         */
83        public Float() {
84        }
85
86        /**
87         * Constructs and initializes a Line from the specified coordinates.
88         * @param x1 the X coordinate of the start point
89         * @param y1 the Y coordinate of the start point
90         * @param x2 the X coordinate of the end point
91         * @param y2 the Y coordinate of the end point
92         * @since 1.2
93         */
94        public Float(float x1, float y1, float x2, float y2) {
95            setLine(x1, y1, x2, y2);
96        }
97
98        /**
99         * Constructs and initializes a {@code Line2D} from the
100         * specified {@code Point2D} objects.
101         * @param p1 the start {@code Point2D} of this line segment
102         * @param p2 the end {@code Point2D} of this line segment
103         * @since 1.2
104         */
105        public Float(Point2D p1, Point2D p2) {
106            setLine(p1, p2);
107        }
108
109        /**
110         * {@inheritDoc}
111         * @since 1.2
112         */
113        public double getX1() {
114            return (double) x1;
115        }
116
117        /**
118         * {@inheritDoc}
119         * @since 1.2
120         */
121        public double getY1() {
122            return (double) y1;
123        }
124
125        /**
126         * {@inheritDoc}
127         * @since 1.2
128         */
129        public Point2D getP1() {
130            return new Point2D.Float(x1, y1);
131        }
132
133        /**
134         * {@inheritDoc}
135         * @since 1.2
136         */
137        public double getX2() {
138            return (double) x2;
139        }
140
141        /**
142         * {@inheritDoc}
143         * @since 1.2
144         */
145        public double getY2() {
146            return (double) y2;
147        }
148
149        /**
150         * {@inheritDoc}
151         * @since 1.2
152         */
153        public Point2D getP2() {
154            return new Point2D.Float(x2, y2);
155        }
156
157        /**
158         * {@inheritDoc}
159         * @since 1.2
160         */
161        public void setLine(double x1, double y1, double x2, double y2) {
162            this.x1 = (float) x1;
163            this.y1 = (float) y1;
164            this.x2 = (float) x2;
165            this.y2 = (float) y2;
166        }
167
168        /**
169         * Sets the location of the end points of this {@code Line2D}
170         * to the specified float coordinates.
171         * @param x1 the X coordinate of the start point
172         * @param y1 the Y coordinate of the start point
173         * @param x2 the X coordinate of the end point
174         * @param y2 the Y coordinate of the end point
175         * @since 1.2
176         */
177        public void setLine(float x1, float y1, float x2, float y2) {
178            this.x1 = x1;
179            this.y1 = y1;
180            this.x2 = x2;
181            this.y2 = y2;
182        }
183
184        /**
185         * {@inheritDoc}
186         * @since 1.2
187         */
188        public Rectangle2D getBounds2D() {
189            float x, y, w, h;
190            if (x1 < x2) {
191                x = x1;
192                w = x2 - x1;
193            } else {
194                x = x2;
195                w = x1 - x2;
196            }
197            if (y1 < y2) {
198                y = y1;
199                h = y2 - y1;
200            } else {
201                y = y2;
202                h = y1 - y2;
203            }
204            return new Rectangle2D.Float(x, y, w, h);
205        }
206
207        /*
208         * JDK 1.6 serialVersionUID
209         */
210        private static final long serialVersionUID = 6161772511649436349L;
211    }
212
213    /**
214     * A line segment specified with double coordinates.
215     * @since 1.2
216     */
217    public static class Double extends Line2D implements Serializable {
218        /**
219         * The X coordinate of the start point of the line segment.
220         * @since 1.2
221         * @serial
222         */
223        public double x1;
224
225        /**
226         * The Y coordinate of the start point of the line segment.
227         * @since 1.2
228         * @serial
229         */
230        public double y1;
231
232        /**
233         * The X coordinate of the end point of the line segment.
234         * @since 1.2
235         * @serial
236         */
237        public double x2;
238
239        /**
240         * The Y coordinate of the end point of the line segment.
241         * @since 1.2
242         * @serial
243         */
244        public double y2;
245
246        /**
247         * Constructs and initializes a Line with coordinates (0, 0) &rarr; (0, 0).
248         * @since 1.2
249         */
250        public Double() {
251        }
252
253        /**
254         * Constructs and initializes a {@code Line2D} from the
255         * specified coordinates.
256         * @param x1 the X coordinate of the start point
257         * @param y1 the Y coordinate of the start point
258         * @param x2 the X coordinate of the end point
259         * @param y2 the Y coordinate of the end point
260         * @since 1.2
261         */
262        public Double(double x1, double y1, double x2, double y2) {
263            setLine(x1, y1, x2, y2);
264        }
265
266        /**
267         * Constructs and initializes a {@code Line2D} from the
268         * specified {@code Point2D} objects.
269         * @param p1 the start {@code Point2D} of this line segment
270         * @param p2 the end {@code Point2D} of this line segment
271         * @since 1.2
272         */
273        public Double(Point2D p1, Point2D p2) {
274            setLine(p1, p2);
275        }
276
277        /**
278         * {@inheritDoc}
279         * @since 1.2
280         */
281        public double getX1() {
282            return x1;
283        }
284
285        /**
286         * {@inheritDoc}
287         * @since 1.2
288         */
289        public double getY1() {
290            return y1;
291        }
292
293        /**
294         * {@inheritDoc}
295         * @since 1.2
296         */
297        public Point2D getP1() {
298            return new Point2D.Double(x1, y1);
299        }
300
301        /**
302         * {@inheritDoc}
303         * @since 1.2
304         */
305        public double getX2() {
306            return x2;
307        }
308
309        /**
310         * {@inheritDoc}
311         * @since 1.2
312         */
313        public double getY2() {
314            return y2;
315        }
316
317        /**
318         * {@inheritDoc}
319         * @since 1.2
320         */
321        public Point2D getP2() {
322            return new Point2D.Double(x2, y2);
323        }
324
325        /**
326         * {@inheritDoc}
327         * @since 1.2
328         */
329        public void setLine(double x1, double y1, double x2, double y2) {
330            this.x1 = x1;
331            this.y1 = y1;
332            this.x2 = x2;
333            this.y2 = y2;
334        }
335
336        /**
337         * {@inheritDoc}
338         * @since 1.2
339         */
340        public Rectangle2D getBounds2D() {
341            double x, y, w, h;
342            if (x1 < x2) {
343                x = x1;
344                w = x2 - x1;
345            } else {
346                x = x2;
347                w = x1 - x2;
348            }
349            if (y1 < y2) {
350                y = y1;
351                h = y2 - y1;
352            } else {
353                y = y2;
354                h = y1 - y2;
355            }
356            return new Rectangle2D.Double(x, y, w, h);
357        }
358
359        /*
360         * JDK 1.6 serialVersionUID
361         */
362        private static final long serialVersionUID = 7979627399746467499L;
363    }
364
365    /**
366     * This is an abstract class that cannot be instantiated directly.
367     * Type-specific implementation subclasses are available for
368     * instantiation and provide a number of formats for storing
369     * the information necessary to satisfy the various accessory
370     * methods below.
371     *
372     * @see java.awt.geom.Line2D.Float
373     * @see java.awt.geom.Line2D.Double
374     * @since 1.2
375     */
376    protected Line2D() {
377    }
378
379    /**
380     * Returns the X coordinate of the start point in double precision.
381     * @return the X coordinate of the start point of this
382     *         {@code Line2D} object.
383     * @since 1.2
384     */
385    public abstract double getX1();
386
387    /**
388     * Returns the Y coordinate of the start point in double precision.
389     * @return the Y coordinate of the start point of this
390     *         {@code Line2D} object.
391     * @since 1.2
392     */
393    public abstract double getY1();
394
395    /**
396     * Returns the start {@code Point2D} of this {@code Line2D}.
397     * @return the start {@code Point2D} of this {@code Line2D}.
398     * @since 1.2
399     */
400    public abstract Point2D getP1();
401
402    /**
403     * Returns the X coordinate of the end point in double precision.
404     * @return the X coordinate of the end point of this
405     *         {@code Line2D} object.
406     * @since 1.2
407     */
408    public abstract double getX2();
409
410    /**
411     * Returns the Y coordinate of the end point in double precision.
412     * @return the Y coordinate of the end point of this
413     *         {@code Line2D} object.
414     * @since 1.2
415     */
416    public abstract double getY2();
417
418    /**
419     * Returns the end {@code Point2D} of this {@code Line2D}.
420     * @return the end {@code Point2D} of this {@code Line2D}.
421     * @since 1.2
422     */
423    public abstract Point2D getP2();
424
425    /**
426     * Sets the location of the end points of this {@code Line2D} to
427     * the specified double coordinates.
428     * @param x1 the X coordinate of the start point
429     * @param y1 the Y coordinate of the start point
430     * @param x2 the X coordinate of the end point
431     * @param y2 the Y coordinate of the end point
432     * @since 1.2
433     */
434    public abstract void setLine(double x1, double y1, double x2, double y2);
435
436    /**
437     * Sets the location of the end points of this {@code Line2D} to
438     * the specified {@code Point2D} coordinates.
439     * @param p1 the start {@code Point2D} of the line segment
440     * @param p2 the end {@code Point2D} of the line segment
441     * @since 1.2
442     */
443    public void setLine(Point2D p1, Point2D p2) {
444        setLine(p1.getX(), p1.getY(), p2.getX(), p2.getY());
445    }
446
447    /**
448     * Sets the location of the end points of this {@code Line2D} to
449     * the same as those end points of the specified {@code Line2D}.
450     * @param l the specified {@code Line2D}
451     * @since 1.2
452     */
453    public void setLine(Line2D l) {
454        setLine(l.getX1(), l.getY1(), l.getX2(), l.getY2());
455    }
456
457    /**
458     * Returns an indicator of where the specified point
459     * {@code (px,py)} lies with respect to the line segment from
460     * {@code (x1,y1)} to {@code (x2,y2)}.
461     * The return value can be either 1, -1, or 0 and indicates
462     * in which direction the specified line must pivot around its
463     * first end point, {@code (x1,y1)}, in order to point at the
464     * specified point {@code (px,py)}.
465     * <p>A return value of 1 indicates that the line segment must
466     * turn in the direction that takes the positive X axis towards
467     * the negative Y axis.  In the default coordinate system used by
468     * Java 2D, this direction is counterclockwise.
469     * <p>A return value of -1 indicates that the line segment must
470     * turn in the direction that takes the positive X axis towards
471     * the positive Y axis.  In the default coordinate system, this
472     * direction is clockwise.
473     * <p>A return value of 0 indicates that the point lies
474     * exactly on the line segment.  Note that an indicator value
475     * of 0 is rare and not useful for determining collinearity
476     * because of floating point rounding issues.
477     * <p>If the point is colinear with the line segment, but
478     * not between the end points, then the value will be -1 if the point
479     * lies "beyond {@code (x1,y1)}" or 1 if the point lies
480     * "beyond {@code (x2,y2)}".
481     *
482     * @param x1 the X coordinate of the start point of the
483     *           specified line segment
484     * @param y1 the Y coordinate of the start point of the
485     *           specified line segment
486     * @param x2 the X coordinate of the end point of the
487     *           specified line segment
488     * @param y2 the Y coordinate of the end point of the
489     *           specified line segment
490     * @param px the X coordinate of the specified point to be
491     *           compared with the specified line segment
492     * @param py the Y coordinate of the specified point to be
493     *           compared with the specified line segment
494     * @return an integer that indicates the position of the third specified
495     *                  coordinates with respect to the line segment formed
496     *                  by the first two specified coordinates.
497     * @since 1.2
498     */
499    public static int relativeCCW(double x1, double y1,
500                                  double x2, double y2,
501                                  double px, double py)
502    {
503        x2 -= x1;
504        y2 -= y1;
505        px -= x1;
506        py -= y1;
507        double ccw = px * y2 - py * x2;
508        if (ccw == 0.0) {
509            // The point is colinear, classify based on which side of
510            // the segment the point falls on.  We can calculate a
511            // relative value using the projection of px,py onto the
512            // segment - a negative value indicates the point projects
513            // outside of the segment in the direction of the particular
514            // endpoint used as the origin for the projection.
515            ccw = px * x2 + py * y2;
516            if (ccw > 0.0) {
517                // Reverse the projection to be relative to the original x2,y2
518                // x2 and y2 are simply negated.
519                // px and py need to have (x2 - x1) or (y2 - y1) subtracted
520                //    from them (based on the original values)
521                // Since we really want to get a positive answer when the
522                //    point is "beyond (x2,y2)", then we want to calculate
523                //    the inverse anyway - thus we leave x2 & y2 negated.
524                px -= x2;
525                py -= y2;
526                ccw = px * x2 + py * y2;
527                if (ccw < 0.0) {
528                    ccw = 0.0;
529                }
530            }
531        }
532        return (ccw < 0.0) ? -1 : ((ccw > 0.0) ? 1 : 0);
533    }
534
535    /**
536     * Returns an indicator of where the specified point
537     * {@code (px,py)} lies with respect to this line segment.
538     * See the method comments of
539     * {@link #relativeCCW(double, double, double, double, double, double)}
540     * to interpret the return value.
541     * @param px the X coordinate of the specified point
542     *           to be compared with this {@code Line2D}
543     * @param py the Y coordinate of the specified point
544     *           to be compared with this {@code Line2D}
545     * @return an integer that indicates the position of the specified
546     *         coordinates with respect to this {@code Line2D}
547     * @see #relativeCCW(double, double, double, double, double, double)
548     * @since 1.2
549     */
550    public int relativeCCW(double px, double py) {
551        return relativeCCW(getX1(), getY1(), getX2(), getY2(), px, py);
552    }
553
554    /**
555     * Returns an indicator of where the specified {@code Point2D}
556     * lies with respect to this line segment.
557     * See the method comments of
558     * {@link #relativeCCW(double, double, double, double, double, double)}
559     * to interpret the return value.
560     * @param p the specified {@code Point2D} to be compared
561     *          with this {@code Line2D}
562     * @return an integer that indicates the position of the specified
563     *         {@code Point2D} with respect to this {@code Line2D}
564     * @see #relativeCCW(double, double, double, double, double, double)
565     * @since 1.2
566     */
567    public int relativeCCW(Point2D p) {
568        return relativeCCW(getX1(), getY1(), getX2(), getY2(),
569                           p.getX(), p.getY());
570    }
571
572    /**
573     * Tests if the line segment from {@code (x1,y1)} to
574     * {@code (x2,y2)} intersects the line segment from {@code (x3,y3)}
575     * to {@code (x4,y4)}.
576     *
577     * @param x1 the X coordinate of the start point of the first
578     *           specified line segment
579     * @param y1 the Y coordinate of the start point of the first
580     *           specified line segment
581     * @param x2 the X coordinate of the end point of the first
582     *           specified line segment
583     * @param y2 the Y coordinate of the end point of the first
584     *           specified line segment
585     * @param x3 the X coordinate of the start point of the second
586     *           specified line segment
587     * @param y3 the Y coordinate of the start point of the second
588     *           specified line segment
589     * @param x4 the X coordinate of the end point of the second
590     *           specified line segment
591     * @param y4 the Y coordinate of the end point of the second
592     *           specified line segment
593     * @return {@code true} if the first specified line segment
594     *                  and the second specified line segment intersect
595     *                  each other; {@code false} otherwise.
596     * @since 1.2
597     */
598    public static boolean linesIntersect(double x1, double y1,
599                                         double x2, double y2,
600                                         double x3, double y3,
601                                         double x4, double y4)
602    {
603        return ((relativeCCW(x1, y1, x2, y2, x3, y3) *
604                 relativeCCW(x1, y1, x2, y2, x4, y4) <= 0)
605                && (relativeCCW(x3, y3, x4, y4, x1, y1) *
606                    relativeCCW(x3, y3, x4, y4, x2, y2) <= 0));
607    }
608
609    /**
610     * Tests if the line segment from {@code (x1,y1)} to
611     * {@code (x2,y2)} intersects this line segment.
612     *
613     * @param x1 the X coordinate of the start point of the
614     *           specified line segment
615     * @param y1 the Y coordinate of the start point of the
616     *           specified line segment
617     * @param x2 the X coordinate of the end point of the
618     *           specified line segment
619     * @param y2 the Y coordinate of the end point of the
620     *           specified line segment
621     * @return {@code true} if this line segment and the specified line segment
622     *                  intersect each other; {@code false} otherwise.
623     * @since 1.2
624     */
625    public boolean intersectsLine(double x1, double y1, double x2, double y2) {
626        return linesIntersect(x1, y1, x2, y2,
627                              getX1(), getY1(), getX2(), getY2());
628    }
629
630    /**
631     * Tests if the specified line segment intersects this line segment.
632     * @param l the specified {@code Line2D}
633     * @return {@code true} if this line segment and the specified line
634     *                  segment intersect each other;
635     *                  {@code false} otherwise.
636     * @since 1.2
637     */
638    public boolean intersectsLine(Line2D l) {
639        return linesIntersect(l.getX1(), l.getY1(), l.getX2(), l.getY2(),
640                              getX1(), getY1(), getX2(), getY2());
641    }
642
643    /**
644     * Returns the square of the distance from a point to a line segment.
645     * The distance measured is the distance between the specified
646     * point and the closest point between the specified end points.
647     * If the specified point intersects the line segment in between the
648     * end points, this method returns 0.0.
649     *
650     * @param x1 the X coordinate of the start point of the
651     *           specified line segment
652     * @param y1 the Y coordinate of the start point of the
653     *           specified line segment
654     * @param x2 the X coordinate of the end point of the
655     *           specified line segment
656     * @param y2 the Y coordinate of the end point of the
657     *           specified line segment
658     * @param px the X coordinate of the specified point being
659     *           measured against the specified line segment
660     * @param py the Y coordinate of the specified point being
661     *           measured against the specified line segment
662     * @return a double value that is the square of the distance from the
663     *                  specified point to the specified line segment.
664     * @see #ptLineDistSq(double, double, double, double, double, double)
665     * @since 1.2
666     */
667    public static double ptSegDistSq(double x1, double y1,
668                                     double x2, double y2,
669                                     double px, double py)
670    {
671        // Adjust vectors relative to x1,y1
672        // x2,y2 becomes relative vector from x1,y1 to end of segment
673        x2 -= x1;
674        y2 -= y1;
675        // px,py becomes relative vector from x1,y1 to test point
676        px -= x1;
677        py -= y1;
678        double dotprod = px * x2 + py * y2;
679        double projlenSq;
680        if (dotprod <= 0.0) {
681            // px,py is on the side of x1,y1 away from x2,y2
682            // distance to segment is length of px,py vector
683            // "length of its (clipped) projection" is now 0.0
684            projlenSq = 0.0;
685        } else {
686            // switch to backwards vectors relative to x2,y2
687            // x2,y2 are already the negative of x1,y1=>x2,y2
688            // to get px,py to be the negative of px,py=>x2,y2
689            // the dot product of two negated vectors is the same
690            // as the dot product of the two normal vectors
691            px = x2 - px;
692            py = y2 - py;
693            dotprod = px * x2 + py * y2;
694            if (dotprod <= 0.0) {
695                // px,py is on the side of x2,y2 away from x1,y1
696                // distance to segment is length of (backwards) px,py vector
697                // "length of its (clipped) projection" is now 0.0
698                projlenSq = 0.0;
699            } else {
700                // px,py is between x1,y1 and x2,y2
701                // dotprod is the length of the px,py vector
702                // projected on the x2,y2=>x1,y1 vector times the
703                // length of the x2,y2=>x1,y1 vector
704                projlenSq = dotprod * dotprod / (x2 * x2 + y2 * y2);
705            }
706        }
707        // Distance to line is now the length of the relative point
708        // vector minus the length of its projection onto the line
709        // (which is zero if the projection falls outside the range
710        //  of the line segment).
711        double lenSq = px * px + py * py - projlenSq;
712        if (lenSq < 0) {
713            lenSq = 0;
714        }
715        return lenSq;
716    }
717
718    /**
719     * Returns the distance from a point to a line segment.
720     * The distance measured is the distance between the specified
721     * point and the closest point between the specified end points.
722     * If the specified point intersects the line segment in between the
723     * end points, this method returns 0.0.
724     *
725     * @param x1 the X coordinate of the start point of the
726     *           specified line segment
727     * @param y1 the Y coordinate of the start point of the
728     *           specified line segment
729     * @param x2 the X coordinate of the end point of the
730     *           specified line segment
731     * @param y2 the Y coordinate of the end point of the
732     *           specified line segment
733     * @param px the X coordinate of the specified point being
734     *           measured against the specified line segment
735     * @param py the Y coordinate of the specified point being
736     *           measured against the specified line segment
737     * @return a double value that is the distance from the specified point
738     *                          to the specified line segment.
739     * @see #ptLineDist(double, double, double, double, double, double)
740     * @since 1.2
741     */
742    public static double ptSegDist(double x1, double y1,
743                                   double x2, double y2,
744                                   double px, double py)
745    {
746        return Math.sqrt(ptSegDistSq(x1, y1, x2, y2, px, py));
747    }
748
749    /**
750     * Returns the square of the distance from a point to this line segment.
751     * The distance measured is the distance between the specified
752     * point and the closest point between the current line's end points.
753     * If the specified point intersects the line segment in between the
754     * end points, this method returns 0.0.
755     *
756     * @param px the X coordinate of the specified point being
757     *           measured against this line segment
758     * @param py the Y coordinate of the specified point being
759     *           measured against this line segment
760     * @return a double value that is the square of the distance from the
761     *                  specified point to the current line segment.
762     * @see #ptLineDistSq(double, double)
763     * @since 1.2
764     */
765    public double ptSegDistSq(double px, double py) {
766        return ptSegDistSq(getX1(), getY1(), getX2(), getY2(), px, py);
767    }
768
769    /**
770     * Returns the square of the distance from a {@code Point2D} to
771     * this line segment.
772     * The distance measured is the distance between the specified
773     * point and the closest point between the current line's end points.
774     * If the specified point intersects the line segment in between the
775     * end points, this method returns 0.0.
776     * @param pt the specified {@code Point2D} being measured against
777     *           this line segment.
778     * @return a double value that is the square of the distance from the
779     *                  specified {@code Point2D} to the current
780     *                  line segment.
781     * @see #ptLineDistSq(Point2D)
782     * @since 1.2
783     */
784    public double ptSegDistSq(Point2D pt) {
785        return ptSegDistSq(getX1(), getY1(), getX2(), getY2(),
786                           pt.getX(), pt.getY());
787    }
788
789    /**
790     * Returns the distance from a point to this line segment.
791     * The distance measured is the distance between the specified
792     * point and the closest point between the current line's end points.
793     * If the specified point intersects the line segment in between the
794     * end points, this method returns 0.0.
795     *
796     * @param px the X coordinate of the specified point being
797     *           measured against this line segment
798     * @param py the Y coordinate of the specified point being
799     *           measured against this line segment
800     * @return a double value that is the distance from the specified
801     *                  point to the current line segment.
802     * @see #ptLineDist(double, double)
803     * @since 1.2
804     */
805    public double ptSegDist(double px, double py) {
806        return ptSegDist(getX1(), getY1(), getX2(), getY2(), px, py);
807    }
808
809    /**
810     * Returns the distance from a {@code Point2D} to this line
811     * segment.
812     * The distance measured is the distance between the specified
813     * point and the closest point between the current line's end points.
814     * If the specified point intersects the line segment in between the
815     * end points, this method returns 0.0.
816     * @param pt the specified {@code Point2D} being measured
817     *          against this line segment
818     * @return a double value that is the distance from the specified
819     *                          {@code Point2D} to the current line
820     *                          segment.
821     * @see #ptLineDist(Point2D)
822     * @since 1.2
823     */
824    public double ptSegDist(Point2D pt) {
825        return ptSegDist(getX1(), getY1(), getX2(), getY2(),
826                         pt.getX(), pt.getY());
827    }
828
829    /**
830     * Returns the square of the distance from a point to a line.
831     * The distance measured is the distance between the specified
832     * point and the closest point on the infinitely-extended line
833     * defined by the specified coordinates.  If the specified point
834     * intersects the line, this method returns 0.0.
835     *
836     * @param x1 the X coordinate of the start point of the specified line
837     * @param y1 the Y coordinate of the start point of the specified line
838     * @param x2 the X coordinate of the end point of the specified line
839     * @param y2 the Y coordinate of the end point of the specified line
840     * @param px the X coordinate of the specified point being
841     *           measured against the specified line
842     * @param py the Y coordinate of the specified point being
843     *           measured against the specified line
844     * @return a double value that is the square of the distance from the
845     *                  specified point to the specified line.
846     * @see #ptSegDistSq(double, double, double, double, double, double)
847     * @since 1.2
848     */
849    public static double ptLineDistSq(double x1, double y1,
850                                      double x2, double y2,
851                                      double px, double py)
852    {
853        // Adjust vectors relative to x1,y1
854        // x2,y2 becomes relative vector from x1,y1 to end of segment
855        x2 -= x1;
856        y2 -= y1;
857        // px,py becomes relative vector from x1,y1 to test point
858        px -= x1;
859        py -= y1;
860        double dotprod = px * x2 + py * y2;
861        // dotprod is the length of the px,py vector
862        // projected on the x1,y1=>x2,y2 vector times the
863        // length of the x1,y1=>x2,y2 vector
864        double projlenSq = dotprod * dotprod / (x2 * x2 + y2 * y2);
865        // Distance to line is now the length of the relative point
866        // vector minus the length of its projection onto the line
867        double lenSq = px * px + py * py - projlenSq;
868        if (lenSq < 0) {
869            lenSq = 0;
870        }
871        return lenSq;
872    }
873
874    /**
875     * Returns the distance from a point to a line.
876     * The distance measured is the distance between the specified
877     * point and the closest point on the infinitely-extended line
878     * defined by the specified coordinates.  If the specified point
879     * intersects the line, this method returns 0.0.
880     *
881     * @param x1 the X coordinate of the start point of the specified line
882     * @param y1 the Y coordinate of the start point of the specified line
883     * @param x2 the X coordinate of the end point of the specified line
884     * @param y2 the Y coordinate of the end point of the specified line
885     * @param px the X coordinate of the specified point being
886     *           measured against the specified line
887     * @param py the Y coordinate of the specified point being
888     *           measured against the specified line
889     * @return a double value that is the distance from the specified
890     *                   point to the specified line.
891     * @see #ptSegDist(double, double, double, double, double, double)
892     * @since 1.2
893     */
894    public static double ptLineDist(double x1, double y1,
895                                    double x2, double y2,
896                                    double px, double py)
897    {
898        return Math.sqrt(ptLineDistSq(x1, y1, x2, y2, px, py));
899    }
900
901    /**
902     * Returns the square of the distance from a point to this line.
903     * The distance measured is the distance between the specified
904     * point and the closest point on the infinitely-extended line
905     * defined by this {@code Line2D}.  If the specified point
906     * intersects the line, this method returns 0.0.
907     *
908     * @param px the X coordinate of the specified point being
909     *           measured against this line
910     * @param py the Y coordinate of the specified point being
911     *           measured against this line
912     * @return a double value that is the square of the distance from a
913     *                  specified point to the current line.
914     * @see #ptSegDistSq(double, double)
915     * @since 1.2
916     */
917    public double ptLineDistSq(double px, double py) {
918        return ptLineDistSq(getX1(), getY1(), getX2(), getY2(), px, py);
919    }
920
921    /**
922     * Returns the square of the distance from a specified
923     * {@code Point2D} to this line.
924     * The distance measured is the distance between the specified
925     * point and the closest point on the infinitely-extended line
926     * defined by this {@code Line2D}.  If the specified point
927     * intersects the line, this method returns 0.0.
928     * @param pt the specified {@code Point2D} being measured
929     *           against this line
930     * @return a double value that is the square of the distance from a
931     *                  specified {@code Point2D} to the current
932     *                  line.
933     * @see #ptSegDistSq(Point2D)
934     * @since 1.2
935     */
936    public double ptLineDistSq(Point2D pt) {
937        return ptLineDistSq(getX1(), getY1(), getX2(), getY2(),
938                            pt.getX(), pt.getY());
939    }
940
941    /**
942     * Returns the distance from a point to this line.
943     * The distance measured is the distance between the specified
944     * point and the closest point on the infinitely-extended line
945     * defined by this {@code Line2D}.  If the specified point
946     * intersects the line, this method returns 0.0.
947     *
948     * @param px the X coordinate of the specified point being
949     *           measured against this line
950     * @param py the Y coordinate of the specified point being
951     *           measured against this line
952     * @return a double value that is the distance from a specified point
953     *                  to the current line.
954     * @see #ptSegDist(double, double)
955     * @since 1.2
956     */
957    public double ptLineDist(double px, double py) {
958        return ptLineDist(getX1(), getY1(), getX2(), getY2(), px, py);
959    }
960
961    /**
962     * Returns the distance from a {@code Point2D} to this line.
963     * The distance measured is the distance between the specified
964     * point and the closest point on the infinitely-extended line
965     * defined by this {@code Line2D}.  If the specified point
966     * intersects the line, this method returns 0.0.
967     * @param pt the specified {@code Point2D} being measured
968     * @return a double value that is the distance from a specified
969     *                  {@code Point2D} to the current line.
970     * @see #ptSegDist(Point2D)
971     * @since 1.2
972     */
973    public double ptLineDist(Point2D pt) {
974        return ptLineDist(getX1(), getY1(), getX2(), getY2(),
975                         pt.getX(), pt.getY());
976    }
977
978    /**
979     * Tests if a specified coordinate is inside the boundary of this
980     * {@code Line2D}.  This method is required to implement the
981     * {@link Shape} interface, but in the case of {@code Line2D}
982     * objects it always returns {@code false} since a line contains
983     * no area.
984     * @param x the X coordinate of the specified point to be tested
985     * @param y the Y coordinate of the specified point to be tested
986     * @return {@code false} because a {@code Line2D} contains
987     * no area.
988     * @since 1.2
989     */
990    public boolean contains(double x, double y) {
991        return false;
992    }
993
994    /**
995     * Tests if a given {@code Point2D} is inside the boundary of
996     * this {@code Line2D}.
997     * This method is required to implement the {@link Shape} interface,
998     * but in the case of {@code Line2D} objects it always returns
999     * {@code false} since a line contains no area.
1000     * @param p the specified {@code Point2D} to be tested
1001     * @return {@code false} because a {@code Line2D} contains
1002     * no area.
1003     * @since 1.2
1004     */
1005    public boolean contains(Point2D p) {
1006        return false;
1007    }
1008
1009    /**
1010     * {@inheritDoc}
1011     * @since 1.2
1012     */
1013    public boolean intersects(double x, double y, double w, double h) {
1014        return intersects(new Rectangle2D.Double(x, y, w, h));
1015    }
1016
1017    /**
1018     * {@inheritDoc}
1019     * @since 1.2
1020     */
1021    public boolean intersects(Rectangle2D r) {
1022        return r.intersectsLine(getX1(), getY1(), getX2(), getY2());
1023    }
1024
1025    /**
1026     * Tests if the interior of this {@code Line2D} entirely contains
1027     * the specified set of rectangular coordinates.
1028     * This method is required to implement the {@code Shape} interface,
1029     * but in the case of {@code Line2D} objects it always returns
1030     * false since a line contains no area.
1031     * @param x the X coordinate of the upper-left corner of the
1032     *          specified rectangular area
1033     * @param y the Y coordinate of the upper-left corner of the
1034     *          specified rectangular area
1035     * @param w the width of the specified rectangular area
1036     * @param h the height of the specified rectangular area
1037     * @return {@code false} because a {@code Line2D} contains
1038     * no area.
1039     * @since 1.2
1040     */
1041    public boolean contains(double x, double y, double w, double h) {
1042        return false;
1043    }
1044
1045    /**
1046     * Tests if the interior of this {@code Line2D} entirely contains
1047     * the specified {@code Rectangle2D}.
1048     * This method is required to implement the {@code Shape} interface,
1049     * but in the case of {@code Line2D} objects it always returns
1050     * {@code false} since a line contains no area.
1051     * @param r the specified {@code Rectangle2D} to be tested
1052     * @return {@code false} because a {@code Line2D} contains
1053     * no area.
1054     * @since 1.2
1055     */
1056    public boolean contains(Rectangle2D r) {
1057        return false;
1058    }
1059
1060    /**
1061     * {@inheritDoc}
1062     * @since 1.2
1063     */
1064    public Rectangle getBounds() {
1065        return getBounds2D().getBounds();
1066    }
1067
1068    /**
1069     * Returns an iteration object that defines the boundary of this
1070     * {@code Line2D}.
1071     * The iterator for this class is not multi-threaded safe,
1072     * which means that this {@code Line2D} class does not
1073     * guarantee that modifications to the geometry of this
1074     * {@code Line2D} object do not affect any iterations of that
1075     * geometry that are already in process.
1076     * @param at the specified {@link AffineTransform}
1077     * @return a {@link PathIterator} that defines the boundary of this
1078     *          {@code Line2D}.
1079     * @since 1.2
1080     */
1081    public PathIterator getPathIterator(AffineTransform at) {
1082        return new LineIterator(this, at);
1083    }
1084
1085    /**
1086     * Returns an iteration object that defines the boundary of this
1087     * flattened {@code Line2D}.
1088     * The iterator for this class is not multi-threaded safe,
1089     * which means that this {@code Line2D} class does not
1090     * guarantee that modifications to the geometry of this
1091     * {@code Line2D} object do not affect any iterations of that
1092     * geometry that are already in process.
1093     * @param at the specified {@code AffineTransform}
1094     * @param flatness the maximum amount that the control points for a
1095     *          given curve can vary from colinear before a subdivided
1096     *          curve is replaced by a straight line connecting the
1097     *          end points.  Since a {@code Line2D} object is
1098     *          always flat, this parameter is ignored.
1099     * @return a {@code PathIterator} that defines the boundary of the
1100     *                  flattened {@code Line2D}
1101     * @since 1.2
1102     */
1103    public PathIterator getPathIterator(AffineTransform at, double flatness) {
1104        return new LineIterator(this, at);
1105    }
1106
1107    /**
1108     * Creates a new object of the same class as this object.
1109     *
1110     * @return     a clone of this instance.
1111     * @exception  OutOfMemoryError            if there is not enough memory.
1112     * @see        java.lang.Cloneable
1113     * @since      1.2
1114     */
1115    public Object clone() {
1116        try {
1117            return super.clone();
1118        } catch (CloneNotSupportedException e) {
1119            // this shouldn't happen, since we are Cloneable
1120            throw new InternalError(e);
1121        }
1122    }
1123}
1124