LineSegment.java 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. /*
  2. * Copyright (c) 2009-2010 jMonkeyEngine
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are
  7. * met:
  8. *
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. *
  12. * * Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
  17. * may be used to endorse or promote products derived from this software
  18. * without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  22. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  23. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  24. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  25. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  26. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  27. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  28. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  29. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  30. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. */
  32. package com.jme3.math;
  33. import com.jme3.export.InputCapsule;
  34. import com.jme3.export.JmeExporter;
  35. import com.jme3.export.JmeImporter;
  36. import com.jme3.export.OutputCapsule;
  37. import com.jme3.export.Savable;
  38. import com.jme3.util.TempVars;
  39. import java.io.IOException;
  40. /**
  41. * <p>LineSegment represents a segment in the space. This is a portion of a Line
  42. * that has a limited start and end points.</p>
  43. * <p>A LineSegment is defined by an origin, a direction and an extent (or length).
  44. * Direction should be a normalized vector. It is not internally normalized.</p>
  45. * <p>This class provides methods to calculate distances between LineSegments, Rays and Vectors.
  46. * It is also possible to retrieve both end points of the segment {@link LineSegment#getPositiveEnd(Vector3f)}
  47. * and {@link LineSegment#getNegativeEnd(Vector3f)}. There are also methods to check whether
  48. * a point is within the segment bounds.</p>
  49. *
  50. * @see Ray
  51. * @author Mark Powell
  52. * @author Joshua Slack
  53. */
  54. public class LineSegment implements Cloneable, Savable, java.io.Serializable {
  55. static final long serialVersionUID = 1;
  56. private Vector3f origin;
  57. private Vector3f direction;
  58. private float extent;
  59. public LineSegment() {
  60. origin = new Vector3f();
  61. direction = new Vector3f();
  62. }
  63. public LineSegment(LineSegment ls) {
  64. this.origin = new Vector3f(ls.getOrigin());
  65. this.direction = new Vector3f(ls.getDirection());
  66. this.extent = ls.getExtent();
  67. }
  68. /**
  69. * <p>Creates a new LineSegment with the given origin, direction and extent.</p>
  70. * <p>Note that the origin is not one of the ends of the LineSegment, but its center.</p>
  71. */
  72. public LineSegment(Vector3f origin, Vector3f direction, float extent) {
  73. this.origin = origin;
  74. this.direction = direction;
  75. this.extent = extent;
  76. }
  77. /**
  78. * <p>Creates a new LineSegment with a given origin and end. This constructor will calculate the
  79. * center, the direction and the extent.</p>
  80. */
  81. public LineSegment(Vector3f start, Vector3f end) {
  82. this.origin = new Vector3f(0.5f * (start.x + end.x), 0.5f * (start.y + end.y), 0.5f * (start.z + end.z));
  83. this.direction = end.subtract(start);
  84. this.extent = direction.length() * 0.5f;
  85. direction.normalizeLocal();
  86. }
  87. public void set(LineSegment ls) {
  88. this.origin = new Vector3f(ls.getOrigin());
  89. this.direction = new Vector3f(ls.getDirection());
  90. this.extent = ls.getExtent();
  91. }
  92. public float distance(Vector3f point) {
  93. return FastMath.sqrt(distanceSquared(point));
  94. }
  95. public float distance(LineSegment ls) {
  96. return FastMath.sqrt(distanceSquared(ls));
  97. }
  98. public float distance(Ray r) {
  99. return FastMath.sqrt(distanceSquared(r));
  100. }
  101. public float distanceSquared(Vector3f point) {
  102. TempVars vars = TempVars.get();
  103. Vector3f compVec1 = vars.vect1;
  104. point.subtract(origin, compVec1);
  105. float segmentParameter = direction.dot(compVec1);
  106. if (-extent < segmentParameter) {
  107. if (segmentParameter < extent) {
  108. origin.add(direction.mult(segmentParameter, compVec1),
  109. compVec1);
  110. } else {
  111. origin.add(direction.mult(extent, compVec1), compVec1);
  112. }
  113. } else {
  114. origin.subtract(direction.mult(extent, compVec1), compVec1);
  115. }
  116. compVec1.subtractLocal(point);
  117. float len = compVec1.lengthSquared();
  118. vars.release();
  119. return len;
  120. }
  121. public float distanceSquared(LineSegment test) {
  122. TempVars vars = TempVars.get();
  123. Vector3f compVec1 = vars.vect1;
  124. origin.subtract(test.getOrigin(), compVec1);
  125. float negativeDirectionDot = -(direction.dot(test.getDirection()));
  126. float diffThisDot = compVec1.dot(direction);
  127. float diffTestDot = -(compVec1.dot(test.getDirection()));
  128. float lengthOfDiff = compVec1.lengthSquared();
  129. vars.release();
  130. float determinant = FastMath.abs(1.0f - negativeDirectionDot
  131. * negativeDirectionDot);
  132. float s0, s1, squareDistance, extentDeterminant0, extentDeterminant1, tempS0, tempS1;
  133. if (determinant >= FastMath.FLT_EPSILON) {
  134. // segments are not parallel
  135. s0 = negativeDirectionDot * diffTestDot - diffThisDot;
  136. s1 = negativeDirectionDot * diffThisDot - diffTestDot;
  137. extentDeterminant0 = extent * determinant;
  138. extentDeterminant1 = test.getExtent() * determinant;
  139. if (s0 >= -extentDeterminant0) {
  140. if (s0 <= extentDeterminant0) {
  141. if (s1 >= -extentDeterminant1) {
  142. if (s1 <= extentDeterminant1) // region 0 (interior)
  143. {
  144. // minimum at two interior points of 3D lines
  145. float inverseDeterminant = ((float) 1.0)
  146. / determinant;
  147. s0 *= inverseDeterminant;
  148. s1 *= inverseDeterminant;
  149. squareDistance = s0
  150. * (s0 + negativeDirectionDot * s1 + (2.0f) * diffThisDot)
  151. + s1
  152. * (negativeDirectionDot * s0 + s1 + (2.0f) * diffTestDot)
  153. + lengthOfDiff;
  154. } else // region 3 (side)
  155. {
  156. s1 = test.getExtent();
  157. tempS0 = -(negativeDirectionDot * s1 + diffThisDot);
  158. if (tempS0 < -extent) {
  159. s0 = -extent;
  160. squareDistance = s0 * (s0 - (2.0f) * tempS0)
  161. + s1 * (s1 + (2.0f) * diffTestDot)
  162. + lengthOfDiff;
  163. } else if (tempS0 <= extent) {
  164. s0 = tempS0;
  165. squareDistance = -s0 * s0 + s1
  166. * (s1 + (2.0f) * diffTestDot)
  167. + lengthOfDiff;
  168. } else {
  169. s0 = extent;
  170. squareDistance = s0 * (s0 - (2.0f) * tempS0)
  171. + s1 * (s1 + (2.0f) * diffTestDot)
  172. + lengthOfDiff;
  173. }
  174. }
  175. } else // region 7 (side)
  176. {
  177. s1 = -test.getExtent();
  178. tempS0 = -(negativeDirectionDot * s1 + diffThisDot);
  179. if (tempS0 < -extent) {
  180. s0 = -extent;
  181. squareDistance = s0 * (s0 - (2.0f) * tempS0) + s1
  182. * (s1 + (2.0f) * diffTestDot)
  183. + lengthOfDiff;
  184. } else if (tempS0 <= extent) {
  185. s0 = tempS0;
  186. squareDistance = -s0 * s0 + s1
  187. * (s1 + (2.0f) * diffTestDot)
  188. + lengthOfDiff;
  189. } else {
  190. s0 = extent;
  191. squareDistance = s0 * (s0 - (2.0f) * tempS0) + s1
  192. * (s1 + (2.0f) * diffTestDot)
  193. + lengthOfDiff;
  194. }
  195. }
  196. } else {
  197. if (s1 >= -extentDeterminant1) {
  198. if (s1 <= extentDeterminant1) // region 1 (side)
  199. {
  200. s0 = extent;
  201. tempS1 = -(negativeDirectionDot * s0 + diffTestDot);
  202. if (tempS1 < -test.getExtent()) {
  203. s1 = -test.getExtent();
  204. squareDistance = s1 * (s1 - (2.0f) * tempS1)
  205. + s0 * (s0 + (2.0f) * diffThisDot)
  206. + lengthOfDiff;
  207. } else if (tempS1 <= test.getExtent()) {
  208. s1 = tempS1;
  209. squareDistance = -s1 * s1 + s0
  210. * (s0 + (2.0f) * diffThisDot)
  211. + lengthOfDiff;
  212. } else {
  213. s1 = test.getExtent();
  214. squareDistance = s1 * (s1 - (2.0f) * tempS1)
  215. + s0 * (s0 + (2.0f) * diffThisDot)
  216. + lengthOfDiff;
  217. }
  218. } else // region 2 (corner)
  219. {
  220. s1 = test.getExtent();
  221. tempS0 = -(negativeDirectionDot * s1 + diffThisDot);
  222. if (tempS0 < -extent) {
  223. s0 = -extent;
  224. squareDistance = s0 * (s0 - (2.0f) * tempS0)
  225. + s1 * (s1 + (2.0f) * diffTestDot)
  226. + lengthOfDiff;
  227. } else if (tempS0 <= extent) {
  228. s0 = tempS0;
  229. squareDistance = -s0 * s0 + s1
  230. * (s1 + (2.0f) * diffTestDot)
  231. + lengthOfDiff;
  232. } else {
  233. s0 = extent;
  234. tempS1 = -(negativeDirectionDot * s0 + diffTestDot);
  235. if (tempS1 < -test.getExtent()) {
  236. s1 = -test.getExtent();
  237. squareDistance = s1
  238. * (s1 - (2.0f) * tempS1) + s0
  239. * (s0 + (2.0f) * diffThisDot)
  240. + lengthOfDiff;
  241. } else if (tempS1 <= test.getExtent()) {
  242. s1 = tempS1;
  243. squareDistance = -s1 * s1 + s0
  244. * (s0 + (2.0f) * diffThisDot)
  245. + lengthOfDiff;
  246. } else {
  247. s1 = test.getExtent();
  248. squareDistance = s1
  249. * (s1 - (2.0f) * tempS1) + s0
  250. * (s0 + (2.0f) * diffThisDot)
  251. + lengthOfDiff;
  252. }
  253. }
  254. }
  255. } else // region 8 (corner)
  256. {
  257. s1 = -test.getExtent();
  258. tempS0 = -(negativeDirectionDot * s1 + diffThisDot);
  259. if (tempS0 < -extent) {
  260. s0 = -extent;
  261. squareDistance = s0 * (s0 - (2.0f) * tempS0) + s1
  262. * (s1 + (2.0f) * diffTestDot)
  263. + lengthOfDiff;
  264. } else if (tempS0 <= extent) {
  265. s0 = tempS0;
  266. squareDistance = -s0 * s0 + s1
  267. * (s1 + (2.0f) * diffTestDot)
  268. + lengthOfDiff;
  269. } else {
  270. s0 = extent;
  271. tempS1 = -(negativeDirectionDot * s0 + diffTestDot);
  272. if (tempS1 > test.getExtent()) {
  273. s1 = test.getExtent();
  274. squareDistance = s1 * (s1 - (2.0f) * tempS1)
  275. + s0 * (s0 + (2.0f) * diffThisDot)
  276. + lengthOfDiff;
  277. } else if (tempS1 >= -test.getExtent()) {
  278. s1 = tempS1;
  279. squareDistance = -s1 * s1 + s0
  280. * (s0 + (2.0f) * diffThisDot)
  281. + lengthOfDiff;
  282. } else {
  283. s1 = -test.getExtent();
  284. squareDistance = s1 * (s1 - (2.0f) * tempS1)
  285. + s0 * (s0 + (2.0f) * diffThisDot)
  286. + lengthOfDiff;
  287. }
  288. }
  289. }
  290. }
  291. } else {
  292. if (s1 >= -extentDeterminant1) {
  293. if (s1 <= extentDeterminant1) // region 5 (side)
  294. {
  295. s0 = -extent;
  296. tempS1 = -(negativeDirectionDot * s0 + diffTestDot);
  297. if (tempS1 < -test.getExtent()) {
  298. s1 = -test.getExtent();
  299. squareDistance = s1 * (s1 - (2.0f) * tempS1) + s0
  300. * (s0 + (2.0f) * diffThisDot)
  301. + lengthOfDiff;
  302. } else if (tempS1 <= test.getExtent()) {
  303. s1 = tempS1;
  304. squareDistance = -s1 * s1 + s0
  305. * (s0 + (2.0f) * diffThisDot)
  306. + lengthOfDiff;
  307. } else {
  308. s1 = test.getExtent();
  309. squareDistance = s1 * (s1 - (2.0f) * tempS1) + s0
  310. * (s0 + (2.0f) * diffThisDot)
  311. + lengthOfDiff;
  312. }
  313. } else // region 4 (corner)
  314. {
  315. s1 = test.getExtent();
  316. tempS0 = -(negativeDirectionDot * s1 + diffThisDot);
  317. if (tempS0 > extent) {
  318. s0 = extent;
  319. squareDistance = s0 * (s0 - (2.0f) * tempS0) + s1
  320. * (s1 + (2.0f) * diffTestDot)
  321. + lengthOfDiff;
  322. } else if (tempS0 >= -extent) {
  323. s0 = tempS0;
  324. squareDistance = -s0 * s0 + s1
  325. * (s1 + (2.0f) * diffTestDot)
  326. + lengthOfDiff;
  327. } else {
  328. s0 = -extent;
  329. tempS1 = -(negativeDirectionDot * s0 + diffTestDot);
  330. if (tempS1 < -test.getExtent()) {
  331. s1 = -test.getExtent();
  332. squareDistance = s1 * (s1 - (2.0f) * tempS1)
  333. + s0 * (s0 + (2.0f) * diffThisDot)
  334. + lengthOfDiff;
  335. } else if (tempS1 <= test.getExtent()) {
  336. s1 = tempS1;
  337. squareDistance = -s1 * s1 + s0
  338. * (s0 + (2.0f) * diffThisDot)
  339. + lengthOfDiff;
  340. } else {
  341. s1 = test.getExtent();
  342. squareDistance = s1 * (s1 - (2.0f) * tempS1)
  343. + s0 * (s0 + (2.0f) * diffThisDot)
  344. + lengthOfDiff;
  345. }
  346. }
  347. }
  348. } else // region 6 (corner)
  349. {
  350. s1 = -test.getExtent();
  351. tempS0 = -(negativeDirectionDot * s1 + diffThisDot);
  352. if (tempS0 > extent) {
  353. s0 = extent;
  354. squareDistance = s0 * (s0 - (2.0f) * tempS0) + s1
  355. * (s1 + (2.0f) * diffTestDot) + lengthOfDiff;
  356. } else if (tempS0 >= -extent) {
  357. s0 = tempS0;
  358. squareDistance = -s0 * s0 + s1
  359. * (s1 + (2.0f) * diffTestDot) + lengthOfDiff;
  360. } else {
  361. s0 = -extent;
  362. tempS1 = -(negativeDirectionDot * s0 + diffTestDot);
  363. if (tempS1 < -test.getExtent()) {
  364. s1 = -test.getExtent();
  365. squareDistance = s1 * (s1 - (2.0f) * tempS1) + s0
  366. * (s0 + (2.0f) * diffThisDot)
  367. + lengthOfDiff;
  368. } else if (tempS1 <= test.getExtent()) {
  369. s1 = tempS1;
  370. squareDistance = -s1 * s1 + s0
  371. * (s0 + (2.0f) * diffThisDot)
  372. + lengthOfDiff;
  373. } else {
  374. s1 = test.getExtent();
  375. squareDistance = s1 * (s1 - (2.0f) * tempS1) + s0
  376. * (s0 + (2.0f) * diffThisDot)
  377. + lengthOfDiff;
  378. }
  379. }
  380. }
  381. }
  382. } else {
  383. // The segments are parallel. The average b0 term is designed to
  384. // ensure symmetry of the function. That is, dist(seg0,seg1) and
  385. // dist(seg1,seg0) should produce the same number.get
  386. float extentSum = extent + test.getExtent();
  387. float sign = (negativeDirectionDot > 0.0f ? -1.0f : 1.0f);
  388. float averageB0 = (0.5f) * (diffThisDot - sign * diffTestDot);
  389. float lambda = -averageB0;
  390. if (lambda < -extentSum) {
  391. lambda = -extentSum;
  392. } else if (lambda > extentSum) {
  393. lambda = extentSum;
  394. }
  395. squareDistance = lambda * (lambda + (2.0f) * averageB0)
  396. + lengthOfDiff;
  397. }
  398. return FastMath.abs(squareDistance);
  399. }
  400. public float distanceSquared(Ray r) {
  401. Vector3f kDiff = r.getOrigin().subtract(origin);
  402. float fA01 = -r.getDirection().dot(direction);
  403. float fB0 = kDiff.dot(r.getDirection());
  404. float fB1 = -kDiff.dot(direction);
  405. float fC = kDiff.lengthSquared();
  406. float fDet = FastMath.abs(1.0f - fA01 * fA01);
  407. float fS0, fS1, fSqrDist, fExtDet;
  408. if (fDet >= FastMath.FLT_EPSILON) {
  409. // The ray and segment are not parallel.
  410. fS0 = fA01 * fB1 - fB0;
  411. fS1 = fA01 * fB0 - fB1;
  412. fExtDet = extent * fDet;
  413. if (fS0 >= (float) 0.0) {
  414. if (fS1 >= -fExtDet) {
  415. if (fS1 <= fExtDet) // region 0
  416. {
  417. // minimum at interior points of ray and segment
  418. float fInvDet = ((float) 1.0) / fDet;
  419. fS0 *= fInvDet;
  420. fS1 *= fInvDet;
  421. fSqrDist = fS0
  422. * (fS0 + fA01 * fS1 + ((float) 2.0) * fB0)
  423. + fS1
  424. * (fA01 * fS0 + fS1 + ((float) 2.0) * fB1) + fC;
  425. } else // region 1
  426. {
  427. fS1 = extent;
  428. fS0 = -(fA01 * fS1 + fB0);
  429. if (fS0 > (float) 0.0) {
  430. fSqrDist = -fS0 * fS0 + fS1
  431. * (fS1 + ((float) 2.0) * fB1) + fC;
  432. } else {
  433. fS0 = (float) 0.0;
  434. fSqrDist = fS1 * (fS1 + ((float) 2.0) * fB1) + fC;
  435. }
  436. }
  437. } else // region 5
  438. {
  439. fS1 = -extent;
  440. fS0 = -(fA01 * fS1 + fB0);
  441. if (fS0 > (float) 0.0) {
  442. fSqrDist = -fS0 * fS0 + fS1
  443. * (fS1 + ((float) 2.0) * fB1) + fC;
  444. } else {
  445. fS0 = (float) 0.0;
  446. fSqrDist = fS1 * (fS1 + ((float) 2.0) * fB1) + fC;
  447. }
  448. }
  449. } else {
  450. if (fS1 <= -fExtDet) // region 4
  451. {
  452. fS0 = -(-fA01 * extent + fB0);
  453. if (fS0 > (float) 0.0) {
  454. fS1 = -extent;
  455. fSqrDist = -fS0 * fS0 + fS1
  456. * (fS1 + ((float) 2.0) * fB1) + fC;
  457. } else {
  458. fS0 = (float) 0.0;
  459. fS1 = -fB1;
  460. if (fS1 < -extent) {
  461. fS1 = -extent;
  462. } else if (fS1 > extent) {
  463. fS1 = extent;
  464. }
  465. fSqrDist = fS1 * (fS1 + ((float) 2.0) * fB1) + fC;
  466. }
  467. } else if (fS1 <= fExtDet) // region 3
  468. {
  469. fS0 = (float) 0.0;
  470. fS1 = -fB1;
  471. if (fS1 < -extent) {
  472. fS1 = -extent;
  473. } else if (fS1 > extent) {
  474. fS1 = extent;
  475. }
  476. fSqrDist = fS1 * (fS1 + ((float) 2.0) * fB1) + fC;
  477. } else // region 2
  478. {
  479. fS0 = -(fA01 * extent + fB0);
  480. if (fS0 > (float) 0.0) {
  481. fS1 = extent;
  482. fSqrDist = -fS0 * fS0 + fS1
  483. * (fS1 + ((float) 2.0) * fB1) + fC;
  484. } else {
  485. fS0 = (float) 0.0;
  486. fS1 = -fB1;
  487. if (fS1 < -extent) {
  488. fS1 = -extent;
  489. } else if (fS1 > extent) {
  490. fS1 = extent;
  491. }
  492. fSqrDist = fS1 * (fS1 + ((float) 2.0) * fB1) + fC;
  493. }
  494. }
  495. }
  496. } else {
  497. // ray and segment are parallel
  498. if (fA01 > (float) 0.0) {
  499. // opposite direction vectors
  500. fS1 = -extent;
  501. } else {
  502. // same direction vectors
  503. fS1 = extent;
  504. }
  505. fS0 = -(fA01 * fS1 + fB0);
  506. if (fS0 > (float) 0.0) {
  507. fSqrDist = -fS0 * fS0 + fS1 * (fS1 + ((float) 2.0) * fB1) + fC;
  508. } else {
  509. fS0 = (float) 0.0;
  510. fSqrDist = fS1 * (fS1 + ((float) 2.0) * fB1) + fC;
  511. }
  512. }
  513. return FastMath.abs(fSqrDist);
  514. }
  515. public Vector3f getDirection() {
  516. return direction;
  517. }
  518. public void setDirection(Vector3f direction) {
  519. this.direction = direction;
  520. }
  521. public float getExtent() {
  522. return extent;
  523. }
  524. public void setExtent(float extent) {
  525. this.extent = extent;
  526. }
  527. public Vector3f getOrigin() {
  528. return origin;
  529. }
  530. public void setOrigin(Vector3f origin) {
  531. this.origin = origin;
  532. }
  533. // P+e*D
  534. public Vector3f getPositiveEnd(Vector3f store) {
  535. if (store == null) {
  536. store = new Vector3f();
  537. }
  538. return origin.add((direction.mult(extent, store)), store);
  539. }
  540. // P-e*D
  541. public Vector3f getNegativeEnd(Vector3f store) {
  542. if (store == null) {
  543. store = new Vector3f();
  544. }
  545. return origin.subtract((direction.mult(extent, store)), store);
  546. }
  547. public void write(JmeExporter e) throws IOException {
  548. OutputCapsule capsule = e.getCapsule(this);
  549. capsule.write(origin, "origin", Vector3f.ZERO);
  550. capsule.write(direction, "direction", Vector3f.ZERO);
  551. capsule.write(extent, "extent", 0);
  552. }
  553. public void read(JmeImporter e) throws IOException {
  554. InputCapsule capsule = e.getCapsule(this);
  555. origin = (Vector3f) capsule.readSavable("origin", Vector3f.ZERO.clone());
  556. direction = (Vector3f) capsule.readSavable("direction", Vector3f.ZERO.clone());
  557. extent = capsule.readFloat("extent", 0);
  558. }
  559. @Override
  560. public LineSegment clone() {
  561. try {
  562. LineSegment segment = (LineSegment) super.clone();
  563. segment.direction = direction.clone();
  564. segment.origin = origin.clone();
  565. return segment;
  566. } catch (CloneNotSupportedException e) {
  567. throw new AssertionError();
  568. }
  569. }
  570. /**
  571. * <p>Evaluates whether a given point is contained within the axis aligned bounding box
  572. * that contains this LineSegment.</p><p>This function is float error aware.</p>
  573. */
  574. public boolean isPointInsideBounds(Vector3f point) {
  575. return isPointInsideBounds(point, Float.MIN_VALUE);
  576. }
  577. /**
  578. * <p>Evaluates whether a given point is contained within the axis aligned bounding box
  579. * that contains this LineSegment.</p><p>This function accepts an error parameter, which
  580. * is added to the extent of the bounding box.</p>
  581. */
  582. public boolean isPointInsideBounds(Vector3f point, float error) {
  583. if (FastMath.abs(point.x - origin.x) > FastMath.abs(direction.x * extent) + error) {
  584. return false;
  585. }
  586. if (FastMath.abs(point.y - origin.y) > FastMath.abs(direction.y * extent) + error) {
  587. return false;
  588. }
  589. if (FastMath.abs(point.z - origin.z) > FastMath.abs(direction.z * extent) + error) {
  590. return false;
  591. }
  592. return true;
  593. }
  594. }