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} 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 }