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