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