Line2D.java 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088
  1. /* Line2D.java -- represents a line in 2-D space, plus operations on a line
  2. Copyright (C) 2000, 2001, 2002 Free Software Foundation
  3. This file is part of GNU Classpath.
  4. GNU Classpath is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.
  8. GNU Classpath is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNU Classpath; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  15. 02111-1307 USA.
  16. Linking this library statically or dynamically with other modules is
  17. making a combined work based on this library. Thus, the terms and
  18. conditions of the GNU General Public License cover the whole
  19. combination.
  20. As a special exception, the copyright holders of this library give you
  21. permission to link this library with independent modules to produce an
  22. executable, regardless of the license terms of these independent
  23. modules, and to copy and distribute the resulting executable under
  24. terms of your choice, provided that you also meet, for each linked
  25. independent module, the terms and conditions of the license of that
  26. module. An independent module is a module which is not derived from
  27. or based on this library. If you modify this library, you may extend
  28. this exception to your version of the library, but you are not
  29. obligated to do so. If you do not wish to do so, delete this
  30. exception statement from your version. */
  31. package java.awt.geom;
  32. import java.awt.Rectangle;
  33. import java.awt.Shape;
  34. import java.util.NoSuchElementException;
  35. /**
  36. * Represents a directed line bewteen two points in (x,y) Cartesian space.
  37. * Remember, on-screen graphics have increasing x from left-to-right, and
  38. * increasing y from top-to-bottom. The storage is left to subclasses.
  39. *
  40. * @author Tom Tromey <tromey@cygnus.com>
  41. * @author Eric Blake <ebb9@email.byu.edu>
  42. * @since 1.2
  43. * @status updated to 1.4
  44. */
  45. public abstract class Line2D implements Shape, Cloneable
  46. {
  47. /**
  48. * The default constructor.
  49. */
  50. protected Line2D()
  51. {
  52. }
  53. /**
  54. * Return the x coordinate of the first point.
  55. *
  56. * @return the starting x coordinate
  57. */
  58. public abstract double getX1();
  59. /**
  60. * Return the y coordinate of the first point.
  61. *
  62. * @return the starting y coordinate
  63. */
  64. public abstract double getY1();
  65. /**
  66. * Return the first point.
  67. *
  68. * @return the starting point
  69. */
  70. public abstract Point2D getP1();
  71. /**
  72. * Return the x coordinate of the second point.
  73. *
  74. * @return the ending x coordinate
  75. */
  76. public abstract double getX2();
  77. /**
  78. * Return the y coordinate of the second point.
  79. *
  80. * @return the ending y coordinate
  81. */
  82. public abstract double getY2();
  83. /**
  84. * Return the second point.
  85. *
  86. * @return the ending point
  87. */
  88. public abstract Point2D getP2();
  89. /**
  90. * Set the coordinates of the line to the given coordinates. Loss of
  91. * precision may occur due to rounding issues.
  92. *
  93. * @param x1 the first x coordinate
  94. * @param y1 the first y coordinate
  95. * @param x2 the second x coordinate
  96. * @param y2 the second y coordinate
  97. */
  98. public abstract void setLine(double x1, double y1, double x2, double y2);
  99. /**
  100. * Set the coordinates to the given points.
  101. *
  102. * @param p1 the first point
  103. * @param p2 the second point
  104. * @throws NullPointerException if either point is null
  105. */
  106. public void setLine(Point2D p1, Point2D p2)
  107. {
  108. setLine(p1.getX(), p1.getY(), p2.getX(), p2.getY());
  109. }
  110. /**
  111. * Set the coordinates to those of the given line.
  112. *
  113. * @param l the line to copy
  114. * @throws NullPointerException if l is null
  115. */
  116. public void setLine(Line2D l)
  117. {
  118. setLine(l.getX1(), l.getY1(), l.getX2(), l.getY2());
  119. }
  120. /**
  121. * Computes the relative rotation direction needed to pivot the line about
  122. * the first point in order to have the second point colinear with point p.
  123. * Because of floating point rounding, don't expect this to be a perfect
  124. * measure of colinearity. The answer is 1 if the line has a shorter rotation
  125. * in the direction of the positive X axis to the negative Y axis
  126. * (counter-clockwise in the default Java coordinate system), or -1 if the
  127. * shortest rotation is in the opposite direction (clockwise). If p
  128. * is already colinear, the return value is -1 if it lies beyond the first
  129. * point, 0 if it lies in the segment, or 1 if it lies beyond the second
  130. * point. If the first and second point are coincident, this returns 0.
  131. *
  132. * @param x1 the first x coordinate
  133. * @param y1 the first y coordinate
  134. * @param x2 the second x coordinate
  135. * @param y2 the second y coordinate
  136. * @param px the reference x coordinate
  137. * @param py the reference y coordinate
  138. * @return the relative rotation direction
  139. */
  140. public static int relativeCCW(double x1, double y1, double x2, double y2,
  141. double px, double py)
  142. {
  143. if ((x1 == x2 && y1 == y2)
  144. || (x1 == px && y1 == py))
  145. return 0; // Coincident points.
  146. // Translate to the origin.
  147. x2 -= x1;
  148. y2 -= y1;
  149. px -= x1;
  150. py -= y1;
  151. double slope2 = y2 / x2;
  152. double slopep = py / px;
  153. if (slope2 == slopep || (x2 == 0 && px == 0))
  154. return y2 > 0 // Colinear.
  155. ? (py < 0 ? -1 : py > y2 ? 1 : 0)
  156. : (py > 0 ? -1 : py < y2 ? 1 : 0);
  157. if (x2 >= 0 && slope2 >= 0)
  158. return px >= 0 // Quadrant 1.
  159. ? (slope2 > slopep ? 1 : -1)
  160. : (slope2 < slopep ? 1 : -1);
  161. if (y2 > 0)
  162. return px < 0 // Quadrant 2.
  163. ? (slope2 > slopep ? 1 : -1)
  164. : (slope2 < slopep ? 1 : -1);
  165. if (slope2 >= 0.0)
  166. return px >= 0 // Quadrant 3.
  167. ? (slope2 < slopep ? 1 : -1)
  168. : (slope2 > slopep ? 1 : -1);
  169. return px < 0 // Quadrant 4.
  170. ? (slope2 < slopep ? 1 : -1)
  171. : (slope2 > slopep ? 1 : -1);
  172. }
  173. /**
  174. * Computes the relative rotation direction needed to pivot this line about
  175. * the first point in order to have the second point colinear with point p.
  176. * Because of floating point rounding, don't expect this to be a perfect
  177. * measure of colinearity. The answer is 1 if the line has a shorter rotation
  178. * in the direction of the positive X axis to the negative Y axis
  179. * (counter-clockwise in the default Java coordinate system), or -1 if the
  180. * shortest rotation is in the opposite direction (clockwise). If p
  181. * is already colinear, the return value is -1 if it lies beyond the first
  182. * point, 0 if it lies in the segment, or 1 if it lies beyond the second
  183. * point. If the first and second point are coincident, this returns 0.
  184. *
  185. * @param px the reference x coordinate
  186. * @param py the reference y coordinate
  187. * @return the relative rotation direction
  188. * @see #relativeCCW(double, double, double, double, double, double)
  189. */
  190. public int relativeCCW(double px, double py)
  191. {
  192. return relativeCCW(getX1(), getY1(), getX2(), getY2(), px, py);
  193. }
  194. /**
  195. * Computes the relative rotation direction needed to pivot this line about
  196. * the first point in order to have the second point colinear with point p.
  197. * Because of floating point rounding, don't expect this to be a perfect
  198. * measure of colinearity. The answer is 1 if the line has a shorter rotation
  199. * in the direction of the positive X axis to the negative Y axis
  200. * (counter-clockwise in the default Java coordinate system), or -1 if the
  201. * shortest rotation is in the opposite direction (clockwise). If p
  202. * is already colinear, the return value is -1 if it lies beyond the first
  203. * point, 0 if it lies in the segment, or 1 if it lies beyond the second
  204. * point. If the first and second point are coincident, this returns 0.
  205. *
  206. * @param p the reference point
  207. * @return the relative rotation direction
  208. * @throws NullPointerException if p is null
  209. * @see #relativeCCW(double, double, double, double, double, double)
  210. */
  211. public int relativeCCW(Point2D p)
  212. {
  213. return relativeCCW(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
  214. }
  215. /**
  216. * Test if the line segment (x1,y1)-&gt;(x2,y2) intersects the line segment
  217. * (x3,y3)-&gt;(x4,y4).
  218. *
  219. * @param x1 the first x coordinate of the first segment
  220. * @param y1 the first y coordinate of the first segment
  221. * @param x2 the second x coordinate of the first segment
  222. * @param y2 the second y coordinate of the first segment
  223. * @param x3 the first x coordinate of the second segment
  224. * @param y3 the first y coordinate of the second segment
  225. * @param x4 the second x coordinate of the second segment
  226. * @param y4 the second y coordinate of the second segment
  227. * @return true if the segments intersect
  228. */
  229. public static boolean linesIntersect(double x1, double y1,
  230. double x2, double y2,
  231. double x3, double y3,
  232. double x4, double y4)
  233. {
  234. double beta = (((y1 - y3) * (x4 - x3) + (x1 - x3) * (y4 - y3))
  235. / ((y2 - y1) * (x4 - x3) + (x2 - x1) * (y4 - y3)));
  236. if (beta < 0.0 || beta > 1.0)
  237. return false;
  238. double alpha = (x1 + beta * (x2 - x1) - x3) / (x4 - x3);
  239. return alpha >= 0.0 && alpha <= 1.0;
  240. }
  241. /**
  242. * Test if this line intersects the line given by (x1,y1)-&gt;(x2,y2).
  243. *
  244. * @param x1 the first x coordinate of the other segment
  245. * @param y1 the first y coordinate of the other segment
  246. * @param x2 the second x coordinate of the other segment
  247. * @param y2 the second y coordinate of the other segment
  248. * @return true if the segments intersect
  249. * @see #linesIntersect(double, double, double, double,
  250. * double, double, double, double)
  251. */
  252. public boolean intersectsLine(double x1, double y1, double x2, double y2)
  253. {
  254. return linesIntersect(getX1(), getY1(), getX2(), getY2(),
  255. x1, y1, x2, y2);
  256. }
  257. /**
  258. * Test if this line intersects the given line.
  259. *
  260. * @param l the other segment
  261. * @return true if the segments intersect
  262. * @throws NullPointerException if l is null
  263. * @see #linesIntersect(double, double, double, double,
  264. * double, double, double, double)
  265. */
  266. public boolean intersectsLine(Line2D l)
  267. {
  268. return linesIntersect(getX1(), getY1(), getX2(), getY2(),
  269. l.getX1(), l.getY1(), l.getX2(), l.getY2());
  270. }
  271. /**
  272. * Measures the square of the shortest distance from the reference point
  273. * to a point on the line segment. If the point is on the segment, the
  274. * result will be 0.
  275. *
  276. * @param x1 the first x coordinate of the segment
  277. * @param y1 the first y coordinate of the segment
  278. * @param x2 the second x coordinate of the segment
  279. * @param y2 the second y coordinate of the segment
  280. * @param px the x coordinate of the point
  281. * @param py the y coordinate of the point
  282. * @return the square of the distance from the point to the segment
  283. * @see #ptSegDist(double, double, double, double, double, double)
  284. * @see #ptLineDistSq(double, double, double, double, double, double)
  285. */
  286. public static double ptSegDistSq(double x1, double y1, double x2, double y2,
  287. double px, double py)
  288. {
  289. double pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
  290. double x, y;
  291. if (pd2 == 0)
  292. {
  293. // Points are coincident.
  294. x = x1;
  295. y = y2;
  296. }
  297. else
  298. {
  299. double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2;
  300. if (u < 0)
  301. {
  302. // "Off the end"
  303. x = x1;
  304. y = y1;
  305. }
  306. else if (u > 1.0)
  307. {
  308. x = x2;
  309. y = y2;
  310. }
  311. else
  312. {
  313. x = x1 + u * (x2 - x1);
  314. y = y1 + u * (y2 - y1);
  315. }
  316. }
  317. return (x - px) * (x - px) + (y - py) * (y - py);
  318. }
  319. /**
  320. * Measures the shortest distance from the reference point to a point on
  321. * the line segment. If the point is on the segment, the result will be 0.
  322. *
  323. * @param x1 the first x coordinate of the segment
  324. * @param y1 the first y coordinate of the segment
  325. * @param x2 the second x coordinate of the segment
  326. * @param y2 the second y coordinate of the segment
  327. * @param px the x coordinate of the point
  328. * @param py the y coordinate of the point
  329. * @return the distance from the point to the segment
  330. * @see #ptSegDistSq(double, double, double, double, double, double)
  331. * @see #ptLineDist(double, double, double, double, double, double)
  332. */
  333. public static double ptSegDist(double x1, double y1, double x2, double y2,
  334. double px, double py)
  335. {
  336. return Math.sqrt(ptSegDistSq(x1, y1, x2, y2, px, py));
  337. }
  338. /**
  339. * Measures the square of the shortest distance from the reference point
  340. * to a point on this line segment. If the point is on the segment, the
  341. * result will be 0.
  342. *
  343. * @param px the x coordinate of the point
  344. * @param py the y coordinate of the point
  345. * @return the square of the distance from the point to the segment
  346. * @see #ptSegDistSq(double, double, double, double, double, double)
  347. */
  348. public double ptSegDistSq(double px, double py)
  349. {
  350. return ptSegDistSq(getX1(), getY1(), getX2(), getY2(), px, py);
  351. }
  352. /**
  353. * Measures the square of the shortest distance from the reference point
  354. * to a point on this line segment. If the point is on the segment, the
  355. * result will be 0.
  356. *
  357. * @param p the point
  358. * @return the square of the distance from the point to the segment
  359. * @throws NullPointerException if p is null
  360. * @see #ptSegDistSq(double, double, double, double, double, double)
  361. */
  362. public double ptSegDistSq(Point2D p)
  363. {
  364. return ptSegDistSq(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
  365. }
  366. /**
  367. * Measures the shortest distance from the reference point to a point on
  368. * this line segment. If the point is on the segment, the result will be 0.
  369. *
  370. * @param px the x coordinate of the point
  371. * @param py the y coordinate of the point
  372. * @return the distance from the point to the segment
  373. * @see #ptSegDist(double, double, double, double, double, double)
  374. */
  375. public double ptSegDist(double px, double py)
  376. {
  377. return ptSegDist(getX1(), getY1(), getX2(), getY2(), px, py);
  378. }
  379. /**
  380. * Measures the shortest distance from the reference point to a point on
  381. * this line segment. If the point is on the segment, the result will be 0.
  382. *
  383. * @param p the point
  384. * @return the distance from the point to the segment
  385. * @throws NullPointerException if p is null
  386. * @see #ptSegDist(double, double, double, double, double, double)
  387. */
  388. public double ptSegDist(Point2D p)
  389. {
  390. return ptSegDist(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
  391. }
  392. /**
  393. * Measures the square of the shortest distance from the reference point
  394. * to a point on the infinite line extended from the segment. If the point
  395. * is on the segment, the result will be 0. If the segment is length 0,
  396. * the distance is to the common endpoint.
  397. *
  398. * @param x1 the first x coordinate of the segment
  399. * @param y1 the first y coordinate of the segment
  400. * @param x2 the second x coordinate of the segment
  401. * @param y2 the second y coordinate of the segment
  402. * @param px the x coordinate of the point
  403. * @param py the y coordinate of the point
  404. * @return the square of the distance from the point to the extended line
  405. * @see #ptLineDist(double, double, double, double, double, double)
  406. * @see #ptSegDistSq(double, double, double, double, double, double)
  407. */
  408. public static double ptLineDistSq(double x1, double y1, double x2, double y2,
  409. double px, double py)
  410. {
  411. double pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
  412. double x, y;
  413. if (pd2 == 0)
  414. {
  415. // Points are coincident.
  416. x = x1;
  417. y = y2;
  418. }
  419. else
  420. {
  421. double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2;
  422. x = x1 + u * (x2 - x1);
  423. y = y1 + u * (y2 - y1);
  424. }
  425. return (x - px) * (x - px) + (y - py) * (y - py);
  426. }
  427. /**
  428. * Measures the shortest distance from the reference point to a point on
  429. * the infinite line extended from the segment. If the point is on the
  430. * segment, the result will be 0. If the segment is length 0, the distance
  431. * is to the common endpoint.
  432. *
  433. * @param x1 the first x coordinate of the segment
  434. * @param y1 the first y coordinate of the segment
  435. * @param x2 the second x coordinate of the segment
  436. * @param y2 the second y coordinate of the segment
  437. * @param px the x coordinate of the point
  438. * @param py the y coordinate of the point
  439. * @return the distance from the point to the extended line
  440. * @see #ptLineDistSq(double, double, double, double, double, double)
  441. * @see #ptSegDist(double, double, double, double, double, double)
  442. */
  443. public static double ptLineDist(double x1, double y1,
  444. double x2, double y2,
  445. double px, double py)
  446. {
  447. return Math.sqrt(ptLineDistSq(x1, y1, x2, y2, px, py));
  448. }
  449. /**
  450. * Measures the square of the shortest distance from the reference point
  451. * to a point on the infinite line extended from this segment. If the point
  452. * is on the segment, the result will be 0. If the segment is length 0,
  453. * the distance is to the common endpoint.
  454. *
  455. * @param px the x coordinate of the point
  456. * @param py the y coordinate of the point
  457. * @return the square of the distance from the point to the extended line
  458. * @see #ptLineDistSq(double, double, double, double, double, double)
  459. */
  460. public double ptLineDistSq(double px, double py)
  461. {
  462. return ptLineDistSq(getX1(), getY1(), getX2(), getY2(), px, py);
  463. }
  464. /**
  465. * Measures the square of the shortest distance from the reference point
  466. * to a point on the infinite line extended from this segment. If the point
  467. * is on the segment, the result will be 0. If the segment is length 0,
  468. * the distance is to the common endpoint.
  469. *
  470. * @param p the point
  471. * @return the square of the distance from the point to the extended line
  472. * @throws NullPointerException if p is null
  473. * @see #ptLineDistSq(double, double, double, double, double, double)
  474. */
  475. public double ptLineDistSq(Point2D p)
  476. {
  477. return ptLineDistSq(getX1(), getY1(), getX2(), getY2(),
  478. p.getX(), p.getY());
  479. }
  480. /**
  481. * Measures the shortest distance from the reference point to a point on
  482. * the infinite line extended from this segment. If the point is on the
  483. * segment, the result will be 0. If the segment is length 0, the distance
  484. * is to the common endpoint.
  485. *
  486. * @param px the x coordinate of the point
  487. * @param py the y coordinate of the point
  488. * @return the distance from the point to the extended line
  489. * @see #ptLineDist(double, double, double, double, double, double)
  490. */
  491. public double ptLineDist(double px, double py)
  492. {
  493. return ptLineDist(getX1(), getY1(), getX2(), getY2(), px, py);
  494. }
  495. /**
  496. * Measures the shortest distance from the reference point to a point on
  497. * the infinite line extended from this segment. If the point is on the
  498. * segment, the result will be 0. If the segment is length 0, the distance
  499. * is to the common endpoint.
  500. *
  501. * @param p the point
  502. * @return the distance from the point to the extended line
  503. * @throws NullPointerException if p is null
  504. * @see #ptLineDist(double, double, double, double, double, double)
  505. */
  506. public double ptLineDist(Point2D p)
  507. {
  508. return ptLineDist(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
  509. }
  510. /**
  511. * Test if a point is contained inside the line. Since a line has no area,
  512. * this returns false.
  513. *
  514. * @param x the x coordinate
  515. * @param y the y coordinate
  516. * @return false; the line does not contain points
  517. */
  518. public boolean contains(double x, double y)
  519. {
  520. return false;
  521. }
  522. /**
  523. * Test if a point is contained inside the line. Since a line has no area,
  524. * this returns false.
  525. *
  526. * @param p the point
  527. * @return false; the line does not contain points
  528. */
  529. public boolean contains(Point2D p)
  530. {
  531. return false;
  532. }
  533. /**
  534. * Tests if this line intersects the interior of the specified rectangle.
  535. *
  536. * @param x the x coordinate of the rectangle
  537. * @param y the y coordinate of the rectangle
  538. * @param w the width of the rectangle
  539. * @param h the height of the rectangle
  540. * @return true if the line intersects the rectangle
  541. */
  542. public boolean intersects(double x, double y, double w, double h)
  543. {
  544. if (w <= 0 || h <= 0)
  545. return false;
  546. double x1 = getX1();
  547. double y1 = getY1();
  548. double x2 = getX2();
  549. double y2 = getY2();
  550. if (x1 >= x && x1 <= x + w && y1 >= y && y1 <= y + h)
  551. return true;
  552. if (x2 >= x && x2 <= x + w && y2 >= y && y2 <= y + h)
  553. return true;
  554. double x3 = x + w;
  555. double y3 = y + h;
  556. return (linesIntersect(x1, y1, x2, y2, x, y, x, y3)
  557. || linesIntersect(x1, y1, x2, y2, x, y3, x3, y3)
  558. || linesIntersect(x1, y1, x2, y2, x3, y3, x3, y)
  559. || linesIntersect(x1, y1, x2, y2, x3, y, x, y));
  560. }
  561. /**
  562. * Tests if this line intersects the interior of the specified rectangle.
  563. *
  564. * @param r the rectangle
  565. * @return true if the line intersects the rectangle
  566. * @throws NullPointerException if r is null
  567. */
  568. public boolean intersects(Rectangle2D r)
  569. {
  570. return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
  571. }
  572. /**
  573. * Tests if the line contains a rectangle. Since lines have no area, this
  574. * always returns false.
  575. *
  576. * @param x the x coordinate of the rectangle
  577. * @param y the y coordinate of the rectangle
  578. * @param w the width of the rectangle
  579. * @param h the height of the rectangle
  580. * @return false; the line does not contain points
  581. */
  582. public boolean contains(double x, double y, double w, double h)
  583. {
  584. return false;
  585. }
  586. /**
  587. * Tests if the line contains a rectangle. Since lines have no area, this
  588. * always returns false.
  589. *
  590. * @param r the rectangle
  591. * @return false; the line does not contain points
  592. */
  593. public boolean contains(Rectangle2D r)
  594. {
  595. return false;
  596. }
  597. /**
  598. * Gets a bounding box (not necessarily minimal) for this line.
  599. *
  600. * @return the integer bounding box
  601. * @see #getBounds2D()
  602. */
  603. public Rectangle getBounds()
  604. {
  605. return getBounds2D().getBounds();
  606. }
  607. /**
  608. * Return a path iterator, possibly applying a transform on the result. This
  609. * iterator is not threadsafe.
  610. *
  611. * @param at the transform, or null
  612. * @return a new path iterator
  613. */
  614. public PathIterator getPathIterator(final AffineTransform at)
  615. {
  616. return new PathIterator()
  617. {
  618. /** Current coordinate. */
  619. private int current;
  620. public int getWindingRule()
  621. {
  622. return WIND_NON_ZERO;
  623. }
  624. public boolean isDone()
  625. {
  626. return current < 2;
  627. }
  628. public void next()
  629. {
  630. current++;
  631. }
  632. public int currentSegment(float[] coords)
  633. {
  634. int result;
  635. switch (current)
  636. {
  637. case 0:
  638. coords[0] = (float) getX1();
  639. coords[1] = (float) getY1();
  640. result = SEG_MOVETO;
  641. break;
  642. case 1:
  643. coords[0] = (float) getX2();
  644. coords[1] = (float) getY2();
  645. result = SEG_LINETO;
  646. break;
  647. default:
  648. throw new NoSuchElementException("line iterator out of bounds");
  649. }
  650. if (at != null)
  651. at.transform(coords, 0, coords, 0, 1);
  652. return result;
  653. }
  654. public int currentSegment(double[] coords)
  655. {
  656. int result;
  657. switch (current)
  658. {
  659. case 0:
  660. coords[0] = getX1();
  661. coords[1] = getY1();
  662. result = SEG_MOVETO;
  663. break;
  664. case 1:
  665. coords[0] = getX2();
  666. coords[1] = getY2();
  667. result = SEG_LINETO;
  668. break;
  669. default:
  670. throw new NoSuchElementException("line iterator out of bounds");
  671. }
  672. if (at != null)
  673. at.transform(coords, 0, coords, 0, 1);
  674. return result;
  675. }
  676. };
  677. }
  678. /**
  679. * Return a flat path iterator, possibly applying a transform on the result.
  680. * This iterator is not threadsafe.
  681. *
  682. * @param at the transform, or null
  683. * @param flatness ignored, since lines are already flat
  684. * @return a new path iterator
  685. * @see #getPathIterator(AffineTransform)
  686. */
  687. public PathIterator getPathIterator(AffineTransform at, double flatness)
  688. {
  689. return getPathIterator(at);
  690. }
  691. /**
  692. * Create a new line of the same run-time type with the same contents as
  693. * this one.
  694. *
  695. * @return the clone
  696. *
  697. * @exception OutOfMemoryError If there is not enough memory available.
  698. *
  699. * @since 1.2
  700. */
  701. public Object clone()
  702. {
  703. try
  704. {
  705. return super.clone();
  706. }
  707. catch (CloneNotSupportedException e)
  708. {
  709. throw (Error) new InternalError().initCause(e); // Impossible
  710. }
  711. }
  712. /**
  713. * This class defines a point in <code>double</code> precision.
  714. *
  715. * @author Eric Blake <ebb9@email.byu.edu>
  716. * @since 1.2
  717. * @status updated to 1.4
  718. */
  719. public static class Double extends Line2D
  720. {
  721. /** The x coordinate of the first point. */
  722. public double x1;
  723. /** The y coordinate of the first point. */
  724. public double y1;
  725. /** The x coordinate of the second point. */
  726. public double x2;
  727. /** The y coordinate of the second point. */
  728. public double y2;
  729. /**
  730. * Construct the line segment (0,0)-&gt;(0,0).
  731. */
  732. public Double()
  733. {
  734. }
  735. /**
  736. * Construct the line segment with the specified points.
  737. *
  738. * @param x1 the x coordinate of the first point
  739. * @param y1 the y coordinate of the first point
  740. * @param x2 the x coordinate of the second point
  741. * @param y2 the y coordinate of the second point
  742. */
  743. public Double(double x1, double y1, double x2, double y2)
  744. {
  745. this.x1 = x1;
  746. this.y1 = y1;
  747. this.x2 = x2;
  748. this.y2 = y2;
  749. }
  750. /**
  751. * Construct the line segment with the specified points.
  752. *
  753. * @param p1 the first point
  754. * @param p2 the second point
  755. * @throws NullPointerException if either point is null
  756. */
  757. public Double(Point2D p1, Point2D p2)
  758. {
  759. x1 = p1.getX();
  760. y1 = p1.getY();
  761. x2 = p2.getX();
  762. y2 = p2.getY();
  763. }
  764. /**
  765. * Return the x coordinate of the first point.
  766. *
  767. * @return the value of x1
  768. */
  769. public double getX1()
  770. {
  771. return x1;
  772. }
  773. /**
  774. * Return the y coordinate of the first point.
  775. *
  776. * @return the value of y1
  777. */
  778. public double getY1()
  779. {
  780. return y1;
  781. }
  782. /**
  783. * Return the first point.
  784. *
  785. * @return the point (x1,y1)
  786. */
  787. public Point2D getP1()
  788. {
  789. return new Point2D.Double(x1, y1);
  790. }
  791. /**
  792. * Return the x coordinate of the second point.
  793. *
  794. * @return the value of x2
  795. */
  796. public double getX2()
  797. {
  798. return x2;
  799. }
  800. /**
  801. * Return the y coordinate of the second point.
  802. *
  803. * @return the value of y2
  804. */
  805. public double getY2()
  806. {
  807. return y2;
  808. }
  809. /**
  810. * Return the second point.
  811. *
  812. * @return the point (x2,y2)
  813. */
  814. public Point2D getP2()
  815. {
  816. return new Point2D.Double(x2, y2);
  817. }
  818. /**
  819. * Set this line to the given points.
  820. *
  821. * @param x1 the new x coordinate of the first point
  822. * @param y1 the new y coordinate of the first point
  823. * @param x2 the new x coordinate of the second point
  824. * @param y2 the new y coordinate of the second point
  825. */
  826. public void setLine(double x1, double y1, double x2, double y2)
  827. {
  828. this.x1 = x1;
  829. this.y1 = y1;
  830. this.x2 = x2;
  831. this.y2 = y2;
  832. }
  833. /**
  834. * Return the exact bounds of this line segment.
  835. *
  836. * @return the bounding box
  837. */
  838. public Rectangle2D getBounds2D()
  839. {
  840. double x = Math.min(x1, x2);
  841. double y = Math.min(y1, y2);
  842. double w = Math.abs(x1 - x2);
  843. double h = Math.abs(y1 - y2);
  844. return new Rectangle2D.Double(x, y, w, h);
  845. }
  846. } // class Double
  847. /**
  848. * This class defines a point in <code>float</code> precision.
  849. *
  850. * @author Eric Blake <ebb9@email.byu.edu>
  851. * @since 1.2
  852. * @status updated to 1.4
  853. */
  854. public static class Float extends Line2D
  855. {
  856. /** The x coordinate of the first point. */
  857. public float x1;
  858. /** The y coordinate of the first point. */
  859. public float y1;
  860. /** The x coordinate of the second point. */
  861. public float x2;
  862. /** The y coordinate of the second point. */
  863. public float y2;
  864. /**
  865. * Construct the line segment (0,0)-&gt;(0,0).
  866. */
  867. public Float()
  868. {
  869. }
  870. /**
  871. * Construct the line segment with the specified points.
  872. *
  873. * @param x1 the x coordinate of the first point
  874. * @param y1 the y coordinate of the first point
  875. * @param x2 the x coordinate of the second point
  876. * @param y2 the y coordinate of the second point
  877. */
  878. public Float(float x1, float y1, float x2, float y2)
  879. {
  880. this.x1 = x1;
  881. this.y1 = y1;
  882. this.x2 = x2;
  883. this.y2 = y2;
  884. }
  885. /**
  886. * Construct the line segment with the specified points.
  887. *
  888. * @param p1 the first point
  889. * @param p2 the second point
  890. * @throws NullPointerException if either point is null
  891. */
  892. public Float(Point2D p1, Point2D p2)
  893. {
  894. x1 = (float) p1.getX();
  895. y1 = (float) p1.getY();
  896. x2 = (float) p2.getX();
  897. y2 = (float) p2.getY();
  898. }
  899. /**
  900. * Return the x coordinate of the first point.
  901. *
  902. * @return the value of x1
  903. */
  904. public double getX1()
  905. {
  906. return x1;
  907. }
  908. /**
  909. * Return the y coordinate of the first point.
  910. *
  911. * @return the value of y1
  912. */
  913. public double getY1()
  914. {
  915. return y1;
  916. }
  917. /**
  918. * Return the first point.
  919. *
  920. * @return the point (x1,y1)
  921. */
  922. public Point2D getP1()
  923. {
  924. return new Point2D.Float(x1, y1);
  925. }
  926. /**
  927. * Return the x coordinate of the second point.
  928. *
  929. * @return the value of x2
  930. */
  931. public double getX2()
  932. {
  933. return x2;
  934. }
  935. /**
  936. * Return the y coordinate of the second point.
  937. *
  938. * @return the value of y2
  939. */
  940. public double getY2()
  941. {
  942. return y2;
  943. }
  944. /**
  945. * Return the second point.
  946. *
  947. * @return the point (x2,y2)
  948. */
  949. public Point2D getP2()
  950. {
  951. return new Point2D.Float(x2, y2);
  952. }
  953. /**
  954. * Set this line to the given points.
  955. *
  956. * @param x1 the new x coordinate of the first point
  957. * @param y1 the new y coordinate of the first point
  958. * @param x2 the new x coordinate of the second point
  959. * @param y2 the new y coordinate of the second point
  960. */
  961. public void setLine(double x1, double y1, double x2, double y2)
  962. {
  963. this.x1 = (float) x1;
  964. this.y1 = (float) y1;
  965. this.x2 = (float) x2;
  966. this.y2 = (float) y2;
  967. }
  968. /**
  969. * Set this line to the given points.
  970. *
  971. * @param x1 the new x coordinate of the first point
  972. * @param y1 the new y coordinate of the first point
  973. * @param x2 the new x coordinate of the second point
  974. * @param y2 the new y coordinate of the second point
  975. */
  976. public void setLine(float x1, float y1, float x2, float y2)
  977. {
  978. this.x1 = x1;
  979. this.y1 = y1;
  980. this.x2 = x2;
  981. this.y2 = y2;
  982. }
  983. /**
  984. * Return the exact bounds of this line segment.
  985. *
  986. * @return the bounding box
  987. */
  988. public Rectangle2D getBounds2D()
  989. {
  990. float x = Math.min(x1, x2);
  991. float y = Math.min(y1, y2);
  992. float w = Math.abs(x1 - x2);
  993. float h = Math.abs(y1 - y2);
  994. return new Rectangle2D.Float(x, y, w, h);
  995. }
  996. } // class Float
  997. } // class Line2D