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