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