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