0001 /*
0002 * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025
0026 package java.awt.geom;
0027
0028 import java.awt.Shape;
0029 import java.awt.Rectangle;
0030 import java.io.Serializable;
0031
0032 /**
0033 * This <code>Line2D</code> represents a line segment in {@code (x,y)}
0034 * coordinate space. This class, like all of the Java 2D API, uses a
0035 * default coordinate system called <i>user space</i> in which the y-axis
0036 * values increase downward and x-axis values increase to the right. For
0037 * more information on the user space coordinate system, see the
0038 * <a href="http://java.sun.com/j2se/1.3/docs/guide/2d/spec/j2d-intro.fm2.html#61857">
0039 * Coordinate Systems</a> section of the Java 2D Programmer's Guide.
0040 * <p>
0041 * This class is only the abstract superclass for all objects that
0042 * store a 2D line segment.
0043 * The actual storage representation of the coordinates is left to
0044 * the subclass.
0045 *
0046 * @version 1.37, 05/05/07
0047 * @author Jim Graham
0048 * @since 1.2
0049 */
0050 public abstract class Line2D implements Shape, Cloneable {
0051
0052 /**
0053 * A line segment specified with float coordinates.
0054 * @since 1.2
0055 */
0056 public static class Float extends Line2D implements Serializable {
0057 /**
0058 * The X coordinate of the start point of the line segment.
0059 * @since 1.2
0060 * @serial
0061 */
0062 public float x1;
0063
0064 /**
0065 * The Y coordinate of the start point of the line segment.
0066 * @since 1.2
0067 * @serial
0068 */
0069 public float y1;
0070
0071 /**
0072 * The X coordinate of the end point of the line segment.
0073 * @since 1.2
0074 * @serial
0075 */
0076 public float x2;
0077
0078 /**
0079 * The Y coordinate of the end point of the line segment.
0080 * @since 1.2
0081 * @serial
0082 */
0083 public float y2;
0084
0085 /**
0086 * Constructs and initializes a Line with coordinates (0, 0) -> (0, 0).
0087 * @since 1.2
0088 */
0089 public Float() {
0090 }
0091
0092 /**
0093 * Constructs and initializes a Line from the specified coordinates.
0094 * @param x1 the X coordinate of the start point
0095 * @param y1 the Y coordinate of the start point
0096 * @param x2 the X coordinate of the end point
0097 * @param y2 the Y coordinate of the end point
0098 * @since 1.2
0099 */
0100 public Float(float x1, float y1, float x2, float y2) {
0101 setLine(x1, y1, x2, y2);
0102 }
0103
0104 /**
0105 * Constructs and initializes a <code>Line2D</code> from the
0106 * specified <code>Point2D</code> objects.
0107 * @param p1 the start <code>Point2D</code> of this line segment
0108 * @param p2 the end <code>Point2D</code> of this line segment
0109 * @since 1.2
0110 */
0111 public Float(Point2D p1, Point2D p2) {
0112 setLine(p1, p2);
0113 }
0114
0115 /**
0116 * {@inheritDoc}
0117 * @since 1.2
0118 */
0119 public double getX1() {
0120 return (double) x1;
0121 }
0122
0123 /**
0124 * {@inheritDoc}
0125 * @since 1.2
0126 */
0127 public double getY1() {
0128 return (double) y1;
0129 }
0130
0131 /**
0132 * {@inheritDoc}
0133 * @since 1.2
0134 */
0135 public Point2D getP1() {
0136 return new Point2D.Float(x1, y1);
0137 }
0138
0139 /**
0140 * {@inheritDoc}
0141 * @since 1.2
0142 */
0143 public double getX2() {
0144 return (double) x2;
0145 }
0146
0147 /**
0148 * {@inheritDoc}
0149 * @since 1.2
0150 */
0151 public double getY2() {
0152 return (double) y2;
0153 }
0154
0155 /**
0156 * {@inheritDoc}
0157 * @since 1.2
0158 */
0159 public Point2D getP2() {
0160 return new Point2D.Float(x2, y2);
0161 }
0162
0163 /**
0164 * {@inheritDoc}
0165 * @since 1.2
0166 */
0167 public void setLine(double x1, double y1, double x2, double y2) {
0168 this .x1 = (float) x1;
0169 this .y1 = (float) y1;
0170 this .x2 = (float) x2;
0171 this .y2 = (float) y2;
0172 }
0173
0174 /**
0175 * Sets the location of the end points of this <code>Line2D</code>
0176 * to the specified float coordinates.
0177 * @param x1 the X coordinate of the start point
0178 * @param y1 the Y coordinate of the start point
0179 * @param x2 the X coordinate of the end point
0180 * @param y2 the Y coordinate of the end point
0181 * @since 1.2
0182 */
0183 public void setLine(float x1, float y1, float x2, float y2) {
0184 this .x1 = x1;
0185 this .y1 = y1;
0186 this .x2 = x2;
0187 this .y2 = y2;
0188 }
0189
0190 /**
0191 * {@inheritDoc}
0192 * @since 1.2
0193 */
0194 public Rectangle2D getBounds2D() {
0195 float x, y, w, h;
0196 if (x1 < x2) {
0197 x = x1;
0198 w = x2 - x1;
0199 } else {
0200 x = x2;
0201 w = x1 - x2;
0202 }
0203 if (y1 < y2) {
0204 y = y1;
0205 h = y2 - y1;
0206 } else {
0207 y = y2;
0208 h = y1 - y2;
0209 }
0210 return new Rectangle2D.Float(x, y, w, h);
0211 }
0212
0213 /*
0214 * JDK 1.6 serialVersionUID
0215 */
0216 private static final long serialVersionUID = 6161772511649436349L;
0217 }
0218
0219 /**
0220 * A line segment specified with double coordinates.
0221 * @since 1.2
0222 */
0223 public static class Double extends Line2D implements Serializable {
0224 /**
0225 * The X coordinate of the start point of the line segment.
0226 * @since 1.2
0227 * @serial
0228 */
0229 public double x1;
0230
0231 /**
0232 * The Y coordinate of the start point of the line segment.
0233 * @since 1.2
0234 * @serial
0235 */
0236 public double y1;
0237
0238 /**
0239 * The X coordinate of the end point of the line segment.
0240 * @since 1.2
0241 * @serial
0242 */
0243 public double x2;
0244
0245 /**
0246 * The Y coordinate of the end point of the line segment.
0247 * @since 1.2
0248 * @serial
0249 */
0250 public double y2;
0251
0252 /**
0253 * Constructs and initializes a Line with coordinates (0, 0) -> (0, 0).
0254 * @since 1.2
0255 */
0256 public Double() {
0257 }
0258
0259 /**
0260 * Constructs and initializes a <code>Line2D</code> from the
0261 * specified coordinates.
0262 * @param x1 the X coordinate of the start point
0263 * @param y1 the Y coordinate of the start point
0264 * @param x2 the X coordinate of the end point
0265 * @param y2 the Y coordinate of the end point
0266 * @since 1.2
0267 */
0268 public Double(double x1, double y1, double x2, double y2) {
0269 setLine(x1, y1, x2, y2);
0270 }
0271
0272 /**
0273 * Constructs and initializes a <code>Line2D</code> from the
0274 * specified <code>Point2D</code> objects.
0275 * @param p1 the start <code>Point2D</code> of this line segment
0276 * @param p2 the end <code>Point2D</code> of this line segment
0277 * @since 1.2
0278 */
0279 public Double(Point2D p1, Point2D p2) {
0280 setLine(p1, p2);
0281 }
0282
0283 /**
0284 * {@inheritDoc}
0285 * @since 1.2
0286 */
0287 public double getX1() {
0288 return x1;
0289 }
0290
0291 /**
0292 * {@inheritDoc}
0293 * @since 1.2
0294 */
0295 public double getY1() {
0296 return y1;
0297 }
0298
0299 /**
0300 * {@inheritDoc}
0301 * @since 1.2
0302 */
0303 public Point2D getP1() {
0304 return new Point2D.Double(x1, y1);
0305 }
0306
0307 /**
0308 * {@inheritDoc}
0309 * @since 1.2
0310 */
0311 public double getX2() {
0312 return x2;
0313 }
0314
0315 /**
0316 * {@inheritDoc}
0317 * @since 1.2
0318 */
0319 public double getY2() {
0320 return y2;
0321 }
0322
0323 /**
0324 * {@inheritDoc}
0325 * @since 1.2
0326 */
0327 public Point2D getP2() {
0328 return new Point2D.Double(x2, y2);
0329 }
0330
0331 /**
0332 * {@inheritDoc}
0333 * @since 1.2
0334 */
0335 public void setLine(double x1, double y1, double x2, double y2) {
0336 this .x1 = x1;
0337 this .y1 = y1;
0338 this .x2 = x2;
0339 this .y2 = y2;
0340 }
0341
0342 /**
0343 * {@inheritDoc}
0344 * @since 1.2
0345 */
0346 public Rectangle2D getBounds2D() {
0347 double x, y, w, h;
0348 if (x1 < x2) {
0349 x = x1;
0350 w = x2 - x1;
0351 } else {
0352 x = x2;
0353 w = x1 - x2;
0354 }
0355 if (y1 < y2) {
0356 y = y1;
0357 h = y2 - y1;
0358 } else {
0359 y = y2;
0360 h = y1 - y2;
0361 }
0362 return new Rectangle2D.Double(x, y, w, h);
0363 }
0364
0365 /*
0366 * JDK 1.6 serialVersionUID
0367 */
0368 private static final long serialVersionUID = 7979627399746467499L;
0369 }
0370
0371 /**
0372 * This is an abstract class that cannot be instantiated directly.
0373 * Type-specific implementation subclasses are available for
0374 * instantiation and provide a number of formats for storing
0375 * the information necessary to satisfy the various accessory
0376 * methods below.
0377 *
0378 * @see java.awt.geom.Line2D.Float
0379 * @see java.awt.geom.Line2D.Double
0380 * @since 1.2
0381 */
0382 protected Line2D() {
0383 }
0384
0385 /**
0386 * Returns the X coordinate of the start point in double precision.
0387 * @return the X coordinate of the start point of this
0388 * {@code Line2D} object.
0389 * @since 1.2
0390 */
0391 public abstract double getX1();
0392
0393 /**
0394 * Returns the Y coordinate of the start point in double precision.
0395 * @return the Y coordinate of the start point of this
0396 * {@code Line2D} object.
0397 * @since 1.2
0398 */
0399 public abstract double getY1();
0400
0401 /**
0402 * Returns the start <code>Point2D</code> of this <code>Line2D</code>.
0403 * @return the start <code>Point2D</code> of this <code>Line2D</code>.
0404 * @since 1.2
0405 */
0406 public abstract Point2D getP1();
0407
0408 /**
0409 * Returns the X coordinate of the end point in double precision.
0410 * @return the X coordinate of the end point of this
0411 * {@code Line2D} object.
0412 * @since 1.2
0413 */
0414 public abstract double getX2();
0415
0416 /**
0417 * Returns the Y coordinate of the end point in double precision.
0418 * @return the Y coordinate of the end point of this
0419 * {@code Line2D} object.
0420 * @since 1.2
0421 */
0422 public abstract double getY2();
0423
0424 /**
0425 * Returns the end <code>Point2D</code> of this <code>Line2D</code>.
0426 * @return the end <code>Point2D</code> of this <code>Line2D</code>.
0427 * @since 1.2
0428 */
0429 public abstract Point2D getP2();
0430
0431 /**
0432 * Sets the location of the end points of this <code>Line2D</code> to
0433 * the specified double coordinates.
0434 * @param x1 the X coordinate of the start point
0435 * @param y1 the Y coordinate of the start point
0436 * @param x2 the X coordinate of the end point
0437 * @param y2 the Y coordinate of the end point
0438 * @since 1.2
0439 */
0440 public abstract void setLine(double x1, double y1, double x2,
0441 double y2);
0442
0443 /**
0444 * Sets the location of the end points of this <code>Line2D</code> to
0445 * the specified <code>Point2D</code> coordinates.
0446 * @param p1 the start <code>Point2D</code> of the line segment
0447 * @param p2 the end <code>Point2D</code> of the line segment
0448 * @since 1.2
0449 */
0450 public void setLine(Point2D p1, Point2D p2) {
0451 setLine(p1.getX(), p1.getY(), p2.getX(), p2.getY());
0452 }
0453
0454 /**
0455 * Sets the location of the end points of this <code>Line2D</code> to
0456 * the same as those end points of the specified <code>Line2D</code>.
0457 * @param l the specified <code>Line2D</code>
0458 * @since 1.2
0459 */
0460 public void setLine(Line2D l) {
0461 setLine(l.getX1(), l.getY1(), l.getX2(), l.getY2());
0462 }
0463
0464 /**
0465 * Returns an indicator of where the specified point
0466 * {@code (px,py)} lies with respect to the line segment from
0467 * {@code (x1,y1)} to {@code (x2,y2)}.
0468 * The return value can be either 1, -1, or 0 and indicates
0469 * in which direction the specified line must pivot around its
0470 * first end point, {@code (x1,y1)}, in order to point at the
0471 * specified point {@code (px,py)}.
0472 * <p>A return value of 1 indicates that the line segment must
0473 * turn in the direction that takes the positive X axis towards
0474 * the negative Y axis. In the default coordinate system used by
0475 * Java 2D, this direction is counterclockwise.
0476 * <p>A return value of -1 indicates that the line segment must
0477 * turn in the direction that takes the positive X axis towards
0478 * the positive Y axis. In the default coordinate system, this
0479 * direction is clockwise.
0480 * <p>A return value of 0 indicates that the point lies
0481 * exactly on the line segment. Note that an indicator value
0482 * of 0 is rare and not useful for determining colinearity
0483 * because of floating point rounding issues.
0484 * <p>If the point is colinear with the line segment, but
0485 * not between the end points, then the value will be -1 if the point
0486 * lies "beyond {@code (x1,y1)}" or 1 if the point lies
0487 * "beyond {@code (x2,y2)}".
0488 *
0489 * @param x1 the X coordinate of the start point of the
0490 * specified line segment
0491 * @param y1 the Y coordinate of the start point of the
0492 * specified line segment
0493 * @param x2 the X coordinate of the end point of the
0494 * specified line segment
0495 * @param y2 the Y coordinate of the end point of the
0496 * specified line segment
0497 * @param px the X coordinate of the specified point to be
0498 * compared with the specified line segment
0499 * @param py the Y coordinate of the specified point to be
0500 * compared with the specified line segment
0501 * @return an integer that indicates the position of the third specified
0502 * coordinates with respect to the line segment formed
0503 * by the first two specified coordinates.
0504 * @since 1.2
0505 */
0506 public static int relativeCCW(double x1, double y1, double x2,
0507 double y2, double px, double py) {
0508 x2 -= x1;
0509 y2 -= y1;
0510 px -= x1;
0511 py -= y1;
0512 double ccw = px * y2 - py * x2;
0513 if (ccw == 0.0) {
0514 // The point is colinear, classify based on which side of
0515 // the segment the point falls on. We can calculate a
0516 // relative value using the projection of px,py onto the
0517 // segment - a negative value indicates the point projects
0518 // outside of the segment in the direction of the particular
0519 // endpoint used as the origin for the projection.
0520 ccw = px * x2 + py * y2;
0521 if (ccw > 0.0) {
0522 // Reverse the projection to be relative to the original x2,y2
0523 // x2 and y2 are simply negated.
0524 // px and py need to have (x2 - x1) or (y2 - y1) subtracted
0525 // from them (based on the original values)
0526 // Since we really want to get a positive answer when the
0527 // point is "beyond (x2,y2)", then we want to calculate
0528 // the inverse anyway - thus we leave x2 & y2 negated.
0529 px -= x2;
0530 py -= y2;
0531 ccw = px * x2 + py * y2;
0532 if (ccw < 0.0) {
0533 ccw = 0.0;
0534 }
0535 }
0536 }
0537 return (ccw < 0.0) ? -1 : ((ccw > 0.0) ? 1 : 0);
0538 }
0539
0540 /**
0541 * Returns an indicator of where the specified point
0542 * {@code (px,py)} lies with respect to this line segment.
0543 * See the method comments of
0544 * {@link #relativeCCW(double, double, double, double, double, double)}
0545 * to interpret the return value.
0546 * @param px the X coordinate of the specified point
0547 * to be compared with this <code>Line2D</code>
0548 * @param py the Y coordinate of the specified point
0549 * to be compared with this <code>Line2D</code>
0550 * @return an integer that indicates the position of the specified
0551 * coordinates with respect to this <code>Line2D</code>
0552 * @see #relativeCCW(double, double, double, double, double, double)
0553 * @since 1.2
0554 */
0555 public int relativeCCW(double px, double py) {
0556 return relativeCCW(getX1(), getY1(), getX2(), getY2(), px, py);
0557 }
0558
0559 /**
0560 * Returns an indicator of where the specified <code>Point2D</code>
0561 * lies with respect to this line segment.
0562 * See the method comments of
0563 * {@link #relativeCCW(double, double, double, double, double, double)}
0564 * to interpret the return value.
0565 * @param p the specified <code>Point2D</code> to be compared
0566 * with this <code>Line2D</code>
0567 * @return an integer that indicates the position of the specified
0568 * <code>Point2D</code> with respect to this <code>Line2D</code>
0569 * @see #relativeCCW(double, double, double, double, double, double)
0570 * @since 1.2
0571 */
0572 public int relativeCCW(Point2D p) {
0573 return relativeCCW(getX1(), getY1(), getX2(), getY2(),
0574 p.getX(), p.getY());
0575 }
0576
0577 /**
0578 * Tests if the line segment from {@code (x1,y1)} to
0579 * {@code (x2,y2)} intersects the line segment from {@code (x3,y3)}
0580 * to {@code (x4,y4)}.
0581 *
0582 * @param x1 the X coordinate of the start point of the first
0583 * specified line segment
0584 * @param y1 the Y coordinate of the start point of the first
0585 * specified line segment
0586 * @param x2 the X coordinate of the end point of the first
0587 * specified line segment
0588 * @param y2 the Y coordinate of the end point of the first
0589 * specified line segment
0590 * @param x3 the X coordinate of the start point of the second
0591 * specified line segment
0592 * @param y3 the Y coordinate of the start point of the second
0593 * specified line segment
0594 * @param x4 the X coordinate of the end point of the second
0595 * specified line segment
0596 * @param y4 the Y coordinate of the end point of the second
0597 * specified line segment
0598 * @return <code>true</code> if the first specified line segment
0599 * and the second specified line segment intersect
0600 * each other; <code>false</code> otherwise.
0601 * @since 1.2
0602 */
0603 public static boolean linesIntersect(double x1, double y1,
0604 double x2, double y2, double x3, double y3, double x4,
0605 double y4) {
0606 return ((relativeCCW(x1, y1, x2, y2, x3, y3)
0607 * relativeCCW(x1, y1, x2, y2, x4, y4) <= 0) && (relativeCCW(
0608 x3, y3, x4, y4, x1, y1)
0609 * relativeCCW(x3, y3, x4, y4, x2, y2) <= 0));
0610 }
0611
0612 /**
0613 * Tests if the line segment from {@code (x1,y1)} to
0614 * {@code (x2,y2)} intersects this line segment.
0615 *
0616 * @param x1 the X coordinate of the start point of the
0617 * specified line segment
0618 * @param y1 the Y coordinate of the start point of the
0619 * specified line segment
0620 * @param x2 the X coordinate of the end point of the
0621 * specified line segment
0622 * @param y2 the Y coordinate of the end point of the
0623 * specified line segment
0624 * @return <true> if this line segment and the specified line segment
0625 * intersect each other; <code>false</code> otherwise.
0626 * @since 1.2
0627 */
0628 public boolean intersectsLine(double x1, double y1, double x2,
0629 double y2) {
0630 return linesIntersect(x1, y1, x2, y2, getX1(), getY1(),
0631 getX2(), getY2());
0632 }
0633
0634 /**
0635 * Tests if the specified line segment intersects this line segment.
0636 * @param l the specified <code>Line2D</code>
0637 * @return <code>true</code> if this line segment and the specified line
0638 * segment intersect each other;
0639 * <code>false</code> otherwise.
0640 * @since 1.2
0641 */
0642 public boolean intersectsLine(Line2D l) {
0643 return linesIntersect(l.getX1(), l.getY1(), l.getX2(), l
0644 .getY2(), getX1(), getY1(), getX2(), getY2());
0645 }
0646
0647 /**
0648 * Returns the square of the distance from a point to a line segment.
0649 * The distance measured is the distance between the specified
0650 * point and the closest point between the specified end points.
0651 * If the specified point intersects the line segment in between the
0652 * end points, this method returns 0.0.
0653 *
0654 * @param x1 the X coordinate of the start point of the
0655 * specified line segment
0656 * @param y1 the Y coordinate of the start point of the
0657 * specified line segment
0658 * @param x2 the X coordinate of the end point of the
0659 * specified line segment
0660 * @param y2 the Y coordinate of the end point of the
0661 * specified line segment
0662 * @param px the X coordinate of the specified point being
0663 * measured against the specified line segment
0664 * @param py the Y coordinate of the specified point being
0665 * measured against the specified line segment
0666 * @return a double value that is the square of the distance from the
0667 * specified point to the specified line segment.
0668 * @see #ptLineDistSq(double, double, double, double, double, double)
0669 * @since 1.2
0670 */
0671 public static double ptSegDistSq(double x1, double y1, double x2,
0672 double y2, double px, double py) {
0673 // Adjust vectors relative to x1,y1
0674 // x2,y2 becomes relative vector from x1,y1 to end of segment
0675 x2 -= x1;
0676 y2 -= y1;
0677 // px,py becomes relative vector from x1,y1 to test point
0678 px -= x1;
0679 py -= y1;
0680 double dotprod = px * x2 + py * y2;
0681 double projlenSq;
0682 if (dotprod <= 0.0) {
0683 // px,py is on the side of x1,y1 away from x2,y2
0684 // distance to segment is length of px,py vector
0685 // "length of its (clipped) projection" is now 0.0
0686 projlenSq = 0.0;
0687 } else {
0688 // switch to backwards vectors relative to x2,y2
0689 // x2,y2 are already the negative of x1,y1=>x2,y2
0690 // to get px,py to be the negative of px,py=>x2,y2
0691 // the dot product of two negated vectors is the same
0692 // as the dot product of the two normal vectors
0693 px = x2 - px;
0694 py = y2 - py;
0695 dotprod = px * x2 + py * y2;
0696 if (dotprod <= 0.0) {
0697 // px,py is on the side of x2,y2 away from x1,y1
0698 // distance to segment is length of (backwards) px,py vector
0699 // "length of its (clipped) projection" is now 0.0
0700 projlenSq = 0.0;
0701 } else {
0702 // px,py is between x1,y1 and x2,y2
0703 // dotprod is the length of the px,py vector
0704 // projected on the x2,y2=>x1,y1 vector times the
0705 // length of the x2,y2=>x1,y1 vector
0706 projlenSq = dotprod * dotprod / (x2 * x2 + y2 * y2);
0707 }
0708 }
0709 // Distance to line is now the length of the relative point
0710 // vector minus the length of its projection onto the line
0711 // (which is zero if the projection falls outside the range
0712 // of the line segment).
0713 double lenSq = px * px + py * py - projlenSq;
0714 if (lenSq < 0) {
0715 lenSq = 0;
0716 }
0717 return lenSq;
0718 }
0719
0720 /**
0721 * Returns the distance from a point to a line segment.
0722 * The distance measured is the distance between the specified
0723 * point and the closest point between the specified end points.
0724 * If the specified point intersects the line segment in between the
0725 * end points, this method returns 0.0.
0726 *
0727 * @param x1 the X coordinate of the start point of the
0728 * specified line segment
0729 * @param y1 the Y coordinate of the start point of the
0730 * specified line segment
0731 * @param x2 the X coordinate of the end point of the
0732 * specified line segment
0733 * @param y2 the Y coordinate of the end point of the
0734 * specified line segment
0735 * @param px the X coordinate of the specified point being
0736 * measured against the specified line segment
0737 * @param py the Y coordinate of the specified point being
0738 * measured against the specified line segment
0739 * @return a double value that is the distance from the specified point
0740 * to the specified line segment.
0741 * @see #ptLineDist(double, double, double, double, double, double)
0742 * @since 1.2
0743 */
0744 public static double ptSegDist(double x1, double y1, double x2,
0745 double y2, double px, double py) {
0746 return Math.sqrt(ptSegDistSq(x1, y1, x2, y2, px, py));
0747 }
0748
0749 /**
0750 * Returns the square of the distance from a point to this line segment.
0751 * The distance measured is the distance between the specified
0752 * point and the closest point between the current line's end points.
0753 * If the specified point intersects the line segment in between the
0754 * end points, this method returns 0.0.
0755 *
0756 * @param px the X coordinate of the specified point being
0757 * measured against this line segment
0758 * @param py the Y coordinate of the specified point being
0759 * measured against this line segment
0760 * @return a double value that is the square of the distance from the
0761 * specified point to the current line segment.
0762 * @see #ptLineDistSq(double, double)
0763 * @since 1.2
0764 */
0765 public double ptSegDistSq(double px, double py) {
0766 return ptSegDistSq(getX1(), getY1(), getX2(), getY2(), px, py);
0767 }
0768
0769 /**
0770 * Returns the square of the distance from a <code>Point2D</code> to
0771 * this line segment.
0772 * The distance measured is the distance between the specified
0773 * point and the closest point between the current line's end points.
0774 * If the specified point intersects the line segment in between the
0775 * end points, this method returns 0.0.
0776 * @param pt the specified <code>Point2D</code> being measured against
0777 * this line segment.
0778 * @return a double value that is the square of the distance from the
0779 * specified <code>Point2D</code> to the current
0780 * line segment.
0781 * @see #ptLineDistSq(Point2D)
0782 * @since 1.2
0783 */
0784 public double ptSegDistSq(Point2D pt) {
0785 return ptSegDistSq(getX1(), getY1(), getX2(), getY2(), pt
0786 .getX(), pt.getY());
0787 }
0788
0789 /**
0790 * Returns the distance from a point to this line segment.
0791 * The distance measured is the distance between the specified
0792 * point and the closest point between the current line's end points.
0793 * If the specified point intersects the line segment in between the
0794 * end points, this method returns 0.0.
0795 *
0796 * @param px the X coordinate of the specified point being
0797 * measured against this line segment
0798 * @param py the Y coordinate of the specified point being
0799 * measured against this line segment
0800 * @return a double value that is the distance from the specified
0801 * point to the current line segment.
0802 * @see #ptLineDist(double, double)
0803 * @since 1.2
0804 */
0805 public double ptSegDist(double px, double py) {
0806 return ptSegDist(getX1(), getY1(), getX2(), getY2(), px, py);
0807 }
0808
0809 /**
0810 * Returns the distance from a <code>Point2D</code> to this line
0811 * segment.
0812 * The distance measured is the distance between the specified
0813 * point and the closest point between the current line's end points.
0814 * If the specified point intersects the line segment in between the
0815 * end points, this method returns 0.0.
0816 * @param pt the specified <code>Point2D</code> being measured
0817 * against this line segment
0818 * @return a double value that is the distance from the specified
0819 * <code>Point2D</code> to the current line
0820 * segment.
0821 * @see #ptLineDist(Point2D)
0822 * @since 1.2
0823 */
0824 public double ptSegDist(Point2D pt) {
0825 return ptSegDist(getX1(), getY1(), getX2(), getY2(), pt.getX(),
0826 pt.getY());
0827 }
0828
0829 /**
0830 * Returns the square of the distance from a point to a line.
0831 * The distance measured is the distance between the specified
0832 * point and the closest point on the infinitely-extended line
0833 * defined by the specified coordinates. If the specified point
0834 * intersects the line, this method returns 0.0.
0835 *
0836 * @param x1 the X coordinate of the start point of the specified line
0837 * @param y1 the Y coordinate of the start point of the specified line
0838 * @param x2 the X coordinate of the end point of the specified line
0839 * @param y2 the Y coordinate of the end point of the specified line
0840 * @param px the X coordinate of the specified point being
0841 * measured against the specified line
0842 * @param py the Y coordinate of the specified point being
0843 * measured against the specified line
0844 * @return a double value that is the square of the distance from the
0845 * specified point to the specified line.
0846 * @see #ptSegDistSq(double, double, double, double, double, double)
0847 * @since 1.2
0848 */
0849 public static double ptLineDistSq(double x1, double y1, double x2,
0850 double y2, double px, double py) {
0851 // Adjust vectors relative to x1,y1
0852 // x2,y2 becomes relative vector from x1,y1 to end of segment
0853 x2 -= x1;
0854 y2 -= y1;
0855 // px,py becomes relative vector from x1,y1 to test point
0856 px -= x1;
0857 py -= y1;
0858 double dotprod = px * x2 + py * y2;
0859 // dotprod is the length of the px,py vector
0860 // projected on the x1,y1=>x2,y2 vector times the
0861 // length of the x1,y1=>x2,y2 vector
0862 double projlenSq = dotprod * dotprod / (x2 * x2 + y2 * y2);
0863 // Distance to line is now the length of the relative point
0864 // vector minus the length of its projection onto the line
0865 double lenSq = px * px + py * py - projlenSq;
0866 if (lenSq < 0) {
0867 lenSq = 0;
0868 }
0869 return lenSq;
0870 }
0871
0872 /**
0873 * Returns the distance from a point to a line.
0874 * The distance measured is the distance between the specified
0875 * point and the closest point on the infinitely-extended line
0876 * defined by the specified coordinates. If the specified point
0877 * intersects the line, this method returns 0.0.
0878 *
0879 * @param x1 the X coordinate of the start point of the specified line
0880 * @param y1 the Y coordinate of the start point of the specified line
0881 * @param x2 the X coordinate of the end point of the specified line
0882 * @param y2 the Y coordinate of the end point of the specified line
0883 * @param px the X coordinate of the specified point being
0884 * measured against the specified line
0885 * @param py the Y coordinate of the specified point being
0886 * measured against the specified line
0887 * @return a double value that is the distance from the specified
0888 * point to the specified line.
0889 * @see #ptSegDist(double, double, double, double, double, double)
0890 * @since 1.2
0891 */
0892 public static double ptLineDist(double x1, double y1, double x2,
0893 double y2, double px, double py) {
0894 return Math.sqrt(ptLineDistSq(x1, y1, x2, y2, px, py));
0895 }
0896
0897 /**
0898 * Returns the square of the distance from a point to this line.
0899 * The distance measured is the distance between the specified
0900 * point and the closest point on the infinitely-extended line
0901 * defined by this <code>Line2D</code>. If the specified point
0902 * intersects the line, this method returns 0.0.
0903 *
0904 * @param px the X coordinate of the specified point being
0905 * measured against this line
0906 * @param py the Y coordinate of the specified point being
0907 * measured against this line
0908 * @return a double value that is the square of the distance from a
0909 * specified point to the current line.
0910 * @see #ptSegDistSq(double, double)
0911 * @since 1.2
0912 */
0913 public double ptLineDistSq(double px, double py) {
0914 return ptLineDistSq(getX1(), getY1(), getX2(), getY2(), px, py);
0915 }
0916
0917 /**
0918 * Returns the square of the distance from a specified
0919 * <code>Point2D</code> to this line.
0920 * The distance measured is the distance between the specified
0921 * point and the closest point on the infinitely-extended line
0922 * defined by this <code>Line2D</code>. If the specified point
0923 * intersects the line, this method returns 0.0.
0924 * @param pt the specified <code>Point2D</code> being measured
0925 * against this line
0926 * @return a double value that is the square of the distance from a
0927 * specified <code>Point2D</code> to the current
0928 * line.
0929 * @see #ptSegDistSq(Point2D)
0930 * @since 1.2
0931 */
0932 public double ptLineDistSq(Point2D pt) {
0933 return ptLineDistSq(getX1(), getY1(), getX2(), getY2(), pt
0934 .getX(), pt.getY());
0935 }
0936
0937 /**
0938 * Returns the distance from a point to this line.
0939 * The distance measured is the distance between the specified
0940 * point and the closest point on the infinitely-extended line
0941 * defined by this <code>Line2D</code>. If the specified point
0942 * intersects the line, this method returns 0.0.
0943 *
0944 * @param px the X coordinate of the specified point being
0945 * measured against this line
0946 * @param py the Y coordinate of the specified point being
0947 * measured against this line
0948 * @return a double value that is the distance from a specified point
0949 * to the current line.
0950 * @see #ptSegDist(double, double)
0951 * @since 1.2
0952 */
0953 public double ptLineDist(double px, double py) {
0954 return ptLineDist(getX1(), getY1(), getX2(), getY2(), px, py);
0955 }
0956
0957 /**
0958 * Returns the distance from a <code>Point2D</code> to this line.
0959 * The distance measured is the distance between the specified
0960 * point and the closest point on the infinitely-extended line
0961 * defined by this <code>Line2D</code>. If the specified point
0962 * intersects the line, this method returns 0.0.
0963 * @param pt the specified <code>Point2D</code> being measured
0964 * @return a double value that is the distance from a specified
0965 * <code>Point2D</code> to the current line.
0966 * @see #ptSegDist(Point2D)
0967 * @since 1.2
0968 */
0969 public double ptLineDist(Point2D pt) {
0970 return ptLineDist(getX1(), getY1(), getX2(), getY2(),
0971 pt.getX(), pt.getY());
0972 }
0973
0974 /**
0975 * Tests if a specified coordinate is inside the boundary of this
0976 * <code>Line2D</code>. This method is required to implement the
0977 * {@link Shape} interface, but in the case of <code>Line2D</code>
0978 * objects it always returns <code>false</code> since a line contains
0979 * no area.
0980 * @param x the X coordinate of the specified point to be tested
0981 * @param y the Y coordinate of the specified point to be tested
0982 * @return <code>false</code> because a <code>Line2D</code> contains
0983 * no area.
0984 * @since 1.2
0985 */
0986 public boolean contains(double x, double y) {
0987 return false;
0988 }
0989
0990 /**
0991 * Tests if a given <code>Point2D</code> is inside the boundary of
0992 * this <code>Line2D</code>.
0993 * This method is required to implement the {@link Shape} interface,
0994 * but in the case of <code>Line2D</code> objects it always returns
0995 * <code>false</code> since a line contains no area.
0996 * @param p the specified <code>Point2D</code> to be tested
0997 * @return <code>false</code> because a <code>Line2D</code> contains
0998 * no area.
0999 * @since 1.2
1000 */
1001 public boolean contains(Point2D p) {
1002 return false;
1003 }
1004
1005 /**
1006 * {@inheritDoc}
1007 * @since 1.2
1008 */
1009 public boolean intersects(double x, double y, double w, double h) {
1010 return intersects(new Rectangle2D.Double(x, y, w, h));
1011 }
1012
1013 /**
1014 * {@inheritDoc}
1015 * @since 1.2
1016 */
1017 public boolean intersects(Rectangle2D r) {
1018 return r.intersectsLine(getX1(), getY1(), getX2(), getY2());
1019 }
1020
1021 /**
1022 * Tests if the interior of this <code>Line2D</code> entirely contains
1023 * the specified set of rectangular coordinates.
1024 * This method is required to implement the <code>Shape</code> interface,
1025 * but in the case of <code>Line2D</code> objects it always returns
1026 * false since a line contains no area.
1027 * @param x the X coordinate of the upper-left corner of the
1028 * specified rectangular area
1029 * @param y the Y coordinate of the upper-left corner of the
1030 * specified rectangular area
1031 * @param w the width of the specified rectangular area
1032 * @param h the height of the specified rectangular area
1033 * @return <code>false</code> because a <code>Line2D</code> contains
1034 * no area.
1035 * @since 1.2
1036 */
1037 public boolean contains(double x, double y, double w, double h) {
1038 return false;
1039 }
1040
1041 /**
1042 * Tests if the interior of this <code>Line2D</code> entirely contains
1043 * the specified <code>Rectangle2D</code>.
1044 * This method is required to implement the <code>Shape</code> interface,
1045 * but in the case of <code>Line2D</code> objects it always returns
1046 * <code>false</code> since a line contains no area.
1047 * @param r the specified <code>Rectangle2D</code> to be tested
1048 * @return <code>false</code> because a <code>Line2D</code> contains
1049 * no area.
1050 * @since 1.2
1051 */
1052 public boolean contains(Rectangle2D r) {
1053 return false;
1054 }
1055
1056 /**
1057 * {@inheritDoc}
1058 * @since 1.2
1059 */
1060 public Rectangle getBounds() {
1061 return getBounds2D().getBounds();
1062 }
1063
1064 /**
1065 * Returns an iteration object that defines the boundary of this
1066 * <code>Line2D</code>.
1067 * The iterator for this class is not multi-threaded safe,
1068 * which means that this <code>Line2D</code> class does not
1069 * guarantee that modifications to the geometry of this
1070 * <code>Line2D</code> object do not affect any iterations of that
1071 * geometry that are already in process.
1072 * @param at the specified {@link AffineTransform}
1073 * @return a {@link PathIterator} that defines the boundary of this
1074 * <code>Line2D</code>.
1075 * @since 1.2
1076 */
1077 public PathIterator getPathIterator(AffineTransform at) {
1078 return new LineIterator(this , at);
1079 }
1080
1081 /**
1082 * Returns an iteration object that defines the boundary of this
1083 * flattened <code>Line2D</code>.
1084 * The iterator for this class is not multi-threaded safe,
1085 * which means that this <code>Line2D</code> class does not
1086 * guarantee that modifications to the geometry of this
1087 * <code>Line2D</code> object do not affect any iterations of that
1088 * geometry that are already in process.
1089 * @param at the specified <code>AffineTransform</code>
1090 * @param flatness the maximum amount that the control points for a
1091 * given curve can vary from colinear before a subdivided
1092 * curve is replaced by a straight line connecting the
1093 * end points. Since a <code>Line2D</code> object is
1094 * always flat, this parameter is ignored.
1095 * @return a <code>PathIterator</code> that defines the boundary of the
1096 * flattened <code>Line2D</code>
1097 * @since 1.2
1098 */
1099 public PathIterator getPathIterator(AffineTransform at,
1100 double flatness) {
1101 return new LineIterator(this , at);
1102 }
1103
1104 /**
1105 * Creates a new object of the same class as this object.
1106 *
1107 * @return a clone of this instance.
1108 * @exception OutOfMemoryError if there is not enough memory.
1109 * @see java.lang.Cloneable
1110 * @since 1.2
1111 */
1112 public Object clone() {
1113 try {
1114 return super .clone();
1115 } catch (CloneNotSupportedException e) {
1116 // this shouldn't happen, since we are Cloneable
1117 throw new InternalError();
1118 }
1119 }
1120 }
|