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