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