1 /* 2 * Copyright (c) 1997, 2006, 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="http://java.sun.com/j2se/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 */ 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 */ 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 */ 110 public Float(Point2D p1, Point2D p2) { 111 setLine(p1, p2); 112 } 113 114 /** 115 * {@inheritDoc} 116 * @since 1.2 117 */ 118 public double getX1() { 119 return (double) x1; 120 } 121 122 /** 123 * {@inheritDoc} 124 * @since 1.2 125 */ 126 public double getY1() { 127 return (double) y1; 128 } 129 130 /** 131 * {@inheritDoc} 132 * @since 1.2 133 */ 134 public Point2D getP1() { 135 return new Point2D.Float(x1, y1); 136 } 137 138 /** 139 * {@inheritDoc} 140 * @since 1.2 141 */ 142 public double getX2() { 143 return (double) x2; 144 } 145 146 /** 147 * {@inheritDoc} 148 * @since 1.2 149 */ 150 public double getY2() { 151 return (double) y2; 152 } 153 154 /** 155 * {@inheritDoc} 156 * @since 1.2 157 */ 158 public Point2D getP2() { 159 return new Point2D.Float(x2, y2); 160 } 161 162 /** 163 * {@inheritDoc} 164 * @since 1.2 165 */ 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 */ 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 */ 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 */ 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 */ 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 */ 278 public Double(Point2D p1, Point2D p2) { 279 setLine(p1, p2); 280 } 281 282 /** 283 * {@inheritDoc} 284 * @since 1.2 285 */ 286 public double getX1() { 287 return x1; 288 } 289 290 /** 291 * {@inheritDoc} 292 * @since 1.2 293 */ 294 public double getY1() { 295 return y1; 296 } 297 298 /** 299 * {@inheritDoc} 300 * @since 1.2 301 */ 302 public Point2D getP1() { 303 return new Point2D.Double(x1, y1); 304 } 305 306 /** 307 * {@inheritDoc} 308 * @since 1.2 309 */ 310 public double getX2() { 311 return x2; 312 } 313 314 /** 315 * {@inheritDoc} 316 * @since 1.2 317 */ 318 public double getY2() { 319 return y2; 320 } 321 322 /** 323 * {@inheritDoc} 324 * @since 1.2 325 */ 326 public Point2D getP2() { 327 return new Point2D.Double(x2, y2); 328 } 329 330 /** 331 * {@inheritDoc} 332 * @since 1.2 333 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 colinearity 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 */ 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 */ 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 */ 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 */ 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 <true> if this line segment and the specified line segment 627 * intersect each other; <code>false</code> otherwise. 628 * @since 1.2 629 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 1010 public boolean contains(Point2D p) { 1011 return false; 1012 } 1013 1014 /** 1015 * {@inheritDoc} 1016 * @since 1.2 1017 */ 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 */ 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 */ 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 */ 1061 public boolean contains(Rectangle2D r) { 1062 return false; 1063 } 1064 1065 /** 1066 * {@inheritDoc} 1067 * @since 1.2 1068 */ 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 */ 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 */ 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 */ 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 }