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 */
32package com.jme3.math;
33
34import com.jme3.export.*;
35import com.jme3.util.TempVars;
36import 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 */
52public 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
60    public LineSegment() {
61        origin = new Vector3f();
62        direction = new Vector3f();
63    }
64
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     */
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     */
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
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
98    public float distance(Vector3f point) {
99        return FastMath.sqrt(distanceSquared(point));
100    }
101
102    public float distance(LineSegment ls) {
103        return FastMath.sqrt(distanceSquared(ls));
104    }
105
106    public float distance(Ray r) {
107        return FastMath.sqrt(distanceSquared(r));
108    }
109
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
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
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
538    public Vector3f getDirection() {
539        return direction;
540    }
541
542    public void setDirection(Vector3f direction) {
543        this.direction = direction;
544    }
545
546    public float getExtent() {
547        return extent;
548    }
549
550    public void setExtent(float extent) {
551        this.extent = extent;
552    }
553
554    public Vector3f getOrigin() {
555        return origin;
556    }
557
558    public void setOrigin(Vector3f origin) {
559        this.origin = origin;
560    }
561
562    // P+e*D
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
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
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
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
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     */
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     */
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