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 
26 package java.awt.geom;
27 
28 import java.awt.Shape;
29 import java.awt.Rectangle;
30 import 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  */
44 public 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          */
Float()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          */
Float(float x1, float y1, float x2, float y2)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          */
Float(Point2D p1, Point2D p2)105         public Float(Point2D p1, Point2D p2) {
106             setLine(p1, p2);
107         }
108 
109         /**
110          * {@inheritDoc}
111          * @since 1.2
112          */
getX1()113         public double getX1() {
114             return (double) x1;
115         }
116 
117         /**
118          * {@inheritDoc}
119          * @since 1.2
120          */
getY1()121         public double getY1() {
122             return (double) y1;
123         }
124 
125         /**
126          * {@inheritDoc}
127          * @since 1.2
128          */
getP1()129         public Point2D getP1() {
130             return new Point2D.Float(x1, y1);
131         }
132 
133         /**
134          * {@inheritDoc}
135          * @since 1.2
136          */
getX2()137         public double getX2() {
138             return (double) x2;
139         }
140 
141         /**
142          * {@inheritDoc}
143          * @since 1.2
144          */
getY2()145         public double getY2() {
146             return (double) y2;
147         }
148 
149         /**
150          * {@inheritDoc}
151          * @since 1.2
152          */
getP2()153         public Point2D getP2() {
154             return new Point2D.Float(x2, y2);
155         }
156 
157         /**
158          * {@inheritDoc}
159          * @since 1.2
160          */
setLine(double x1, double y1, double x2, double y2)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          */
setLine(float x1, float y1, float x2, float y2)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          */
getBounds2D()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          */
Double()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          */
Double(double x1, double y1, double x2, double y2)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          */
Double(Point2D p1, Point2D p2)273         public Double(Point2D p1, Point2D p2) {
274             setLine(p1, p2);
275         }
276 
277         /**
278          * {@inheritDoc}
279          * @since 1.2
280          */
getX1()281         public double getX1() {
282             return x1;
283         }
284 
285         /**
286          * {@inheritDoc}
287          * @since 1.2
288          */
getY1()289         public double getY1() {
290             return y1;
291         }
292 
293         /**
294          * {@inheritDoc}
295          * @since 1.2
296          */
getP1()297         public Point2D getP1() {
298             return new Point2D.Double(x1, y1);
299         }
300 
301         /**
302          * {@inheritDoc}
303          * @since 1.2
304          */
getX2()305         public double getX2() {
306             return x2;
307         }
308 
309         /**
310          * {@inheritDoc}
311          * @since 1.2
312          */
getY2()313         public double getY2() {
314             return y2;
315         }
316 
317         /**
318          * {@inheritDoc}
319          * @since 1.2
320          */
getP2()321         public Point2D getP2() {
322             return new Point2D.Double(x2, y2);
323         }
324 
325         /**
326          * {@inheritDoc}
327          * @since 1.2
328          */
setLine(double x1, double y1, double x2, double y2)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          */
getBounds2D()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      */
Line2D()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      */
getX1()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      */
getY1()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      */
getP1()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      */
getX2()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      */
getY2()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      */
getP2()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      */
setLine(double x1, double y1, double x2, double y2)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      */
setLine(Point2D p1, Point2D p2)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      */
setLine(Line2D l)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      */
relativeCCW(double x1, double y1, double x2, double y2, double px, double py)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      */
relativeCCW(double px, double py)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      */
relativeCCW(Point2D p)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      */
linesIntersect(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)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      */
intersectsLine(double x1, double y1, double x2, double y2)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      */
intersectsLine(Line2D l)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      */
ptSegDistSq(double x1, double y1, double x2, double y2, double px, double py)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      */
ptSegDist(double x1, double y1, double x2, double y2, double px, double py)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      */
ptSegDistSq(double px, double py)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      */
ptSegDistSq(Point2D pt)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      */
ptSegDist(double px, double py)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      */
ptSegDist(Point2D pt)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      */
ptLineDistSq(double x1, double y1, double x2, double y2, double px, double py)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      */
ptLineDist(double x1, double y1, double x2, double y2, double px, double py)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      */
ptLineDistSq(double px, double py)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      */
ptLineDistSq(Point2D pt)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      */
ptLineDist(double px, double py)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      */
ptLineDist(Point2D pt)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      */
contains(double x, double y)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      */
contains(Point2D p)1005     public boolean contains(Point2D p) {
1006         return false;
1007     }
1008 
1009     /**
1010      * {@inheritDoc}
1011      * @since 1.2
1012      */
intersects(double x, double y, double w, double h)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      */
intersects(Rectangle2D r)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      */
contains(double x, double y, double w, double h)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      */
contains(Rectangle2D r)1056     public boolean contains(Rectangle2D r) {
1057         return false;
1058     }
1059 
1060     /**
1061      * {@inheritDoc}
1062      * @since 1.2
1063      */
getBounds()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      */
getPathIterator(AffineTransform at)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      */
getPathIterator(AffineTransform at, double flatness)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      */
clone()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