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