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