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