1 /**
2 * Contains intersection and distance tests for some 2D and 3D geometric primitives.
3 * 
4 * @author Kai Burjack
5 */
6 module doml.intersection_d;
7 
8 import std.math: isNaN;
9 
10 import Math = doml.math;
11 
12 import doml.vector_2d;
13 import doml.vector_3d;
14 import doml.vector_4d;
15 
16 /*
17 * The MIT License
18 *
19 * Copyright (c) 2015-2021 Kai Burjack
20 *
21 * Permission is hereby granted, free of charge, to any person obtaining a copy
22 * of this software and associated documentation files (the "Software"), to deal
23 * in the Software without restriction, including without limitation the rights
24 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25 * copies of the Software, and to permit persons to whom the Software is
26 * furnished to do so, subject to the following conditions:
27 *
28 * The above copyright notice and this permission notice shall be included in
29 * all copies or substantial portions of the Software.
30 *
31 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
37 * THE SOFTWARE.
38 */
39 
40 /**
41 * Contains intersection and distance tests for some 2D and 3D geometric primitives.
42 * 
43 * @author Kai Burjack
44 */
45 
46 /**
47     * Return value of
48     * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, double, double, double, double, Vector3d)},
49     * {@link #findClosestPointOnTriangle(Vector3d, Vector3d, Vector3d, Vector3d, Vector3d)},
50     * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, Vector2d)} and
51     * {@link #findClosestPointOnTriangle(Vector2d, Vector2d, Vector2d, Vector2d, Vector2d)} or
52     * {@link #intersectSweptSphereTriangle}
53     * to signal that the closest point is the first vertex of the triangle.
54     */
55 public static immutable int POINT_ON_TRIANGLE_VERTEX_0 = 1;
56 /**
57     * Return value of
58     * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, double, double, double, double, Vector3d)},
59     * {@link #findClosestPointOnTriangle(Vector3d, Vector3d, Vector3d, Vector3d, Vector3d)},
60     * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, Vector2d)} and
61     * {@link #findClosestPointOnTriangle(Vector2d, Vector2d, Vector2d, Vector2d, Vector2d)} or
62     * {@link #intersectSweptSphereTriangle}
63     * to signal that the closest point is the second vertex of the triangle.
64     */
65 public static immutable int POINT_ON_TRIANGLE_VERTEX_1 = 2;
66 /**
67     * Return value of
68     * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, double, double, double, double, Vector3d)},
69     * {@link #findClosestPointOnTriangle(Vector3d, Vector3d, Vector3d, Vector3d, Vector3d)},
70     * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, Vector2d)} and
71     * {@link #findClosestPointOnTriangle(Vector2d, Vector2d, Vector2d, Vector2d, Vector2d)} or
72     * {@link #intersectSweptSphereTriangle}
73     * to signal that the closest point is the third vertex of the triangle.
74     */
75 public static immutable int POINT_ON_TRIANGLE_VERTEX_2 = 3;
76 
77 /**
78     * Return value of
79     * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, double, double, double, double, Vector3d)},
80     * {@link #findClosestPointOnTriangle(Vector3d, Vector3d, Vector3d, Vector3d, Vector3d)},
81     * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, Vector2d)} and
82     * {@link #findClosestPointOnTriangle(Vector2d, Vector2d, Vector2d, Vector2d, Vector2d)} or
83     * {@link #intersectSweptSphereTriangle}
84     * to signal that the closest point lies on the edge between the first and second vertex of the triangle.
85     */
86 public static immutable int POINT_ON_TRIANGLE_EDGE_01 = 4;
87 /**
88     * Return value of
89     * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, double, double, double, double, Vector3d)},
90     * {@link #findClosestPointOnTriangle(Vector3d, Vector3d, Vector3d, Vector3d, Vector3d)},
91     * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, Vector2d)} and
92     * {@link #findClosestPointOnTriangle(Vector2d, Vector2d, Vector2d, Vector2d, Vector2d)} or
93     * {@link #intersectSweptSphereTriangle}
94     * to signal that the closest point lies on the edge between the second and third vertex of the triangle.
95     */
96 public static immutable int POINT_ON_TRIANGLE_EDGE_12 = 5;
97 /**
98     * Return value of
99     * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, double, double, double, double, Vector3d)},
100     * {@link #findClosestPointOnTriangle(Vector3d, Vector3d, Vector3d, Vector3d, Vector3d)},
101     * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, Vector2d)} and
102     * {@link #findClosestPointOnTriangle(Vector2d, Vector2d, Vector2d, Vector2d, Vector2d)} or
103     * {@link #intersectSweptSphereTriangle}
104     * to signal that the closest point lies on the edge between the third and first vertex of the triangle.
105     */
106 public static immutable int POINT_ON_TRIANGLE_EDGE_20 = 6;
107 
108 /**
109     * Return value of
110     * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, double, double, double, double, Vector3d)},
111     * {@link #findClosestPointOnTriangle(Vector3d, Vector3d, Vector3d, Vector3d, Vector3d)},
112     * {@link #findClosestPointOnTriangle(double, double, double, double, double, double, double, double, Vector2d)} and
113     * {@link #findClosestPointOnTriangle(Vector2d, Vector2d, Vector2d, Vector2d, Vector2d)} or 
114     * {@link #intersectSweptSphereTriangle}
115     * to signal that the closest point lies on the face of the triangle.
116     */
117 public static immutable int POINT_ON_TRIANGLE_FACE = 7;
118 
119 /**
120     * Return value of {@link #intersectRayAar(double, double, double, double, double, double, double, double, Vector2d)} and
121     * {@link #intersectRayAar(Vector2d, Vector2d, Vector2d, Vector2d, Vector2d)}
122     * to indicate that the ray intersects the side of the axis-aligned rectangle with the minimum x coordinate.
123     */
124 public static immutable int AAR_SIDE_MINX = 0;
125 /**
126     * Return value of {@link #intersectRayAar(double, double, double, double, double, double, double, double, Vector2d)} and
127     * {@link #intersectRayAar(Vector2d, Vector2d, Vector2d, Vector2d, Vector2d)}
128     * to indicate that the ray intersects the side of the axis-aligned rectangle with the minimum y coordinate.
129     */
130 public static immutable int AAR_SIDE_MINY = 1;
131 /**
132     * Return value of {@link #intersectRayAar(double, double, double, double, double, double, double, double, Vector2d)} and
133     * {@link #intersectRayAar(Vector2d, Vector2d, Vector2d, Vector2d, Vector2d)}
134     * to indicate that the ray intersects the side of the axis-aligned rectangle with the maximum x coordinate.
135     */
136 public static immutable int AAR_SIDE_MAXX = 2;
137 /**
138     * Return value of {@link #intersectRayAar(double, double, double, double, double, double, double, double, Vector2d)} and
139     * {@link #intersectRayAar(Vector2d, Vector2d, Vector2d, Vector2d, Vector2d)}
140     * to indicate that the ray intersects the side of the axis-aligned rectangle with the maximum y coordinate.
141     */
142 public static immutable int AAR_SIDE_MAXY = 3;
143 
144 /**
145     * Return value of {@link #intersectLineSegmentAab(double, double, double, double, double, double, double, double, double, double, double, double, Vector2d)} and
146     * {@link #intersectLineSegmentAab(Vector3d, Vector3d, Vector3d, Vector3d, Vector2d)} to indicate that the line segment does not intersect the axis-aligned box;
147     * or return value of {@link #intersectLineSegmentAar(double, double, double, double, double, double, double, double, Vector2d)} and
148     * {@link #intersectLineSegmentAar(Vector2d, Vector2d, Vector2d, Vector2d, Vector2d)} to indicate that the line segment does not intersect the axis-aligned rectangle.
149     */
150 public static immutable int OUTSIDE = -1;
151 /**
152     * Return value of {@link #intersectLineSegmentAab(double, double, double, double, double, double, double, double, double, double, double, double, Vector2d)} and
153     * {@link #intersectLineSegmentAab(Vector3d, Vector3d, Vector3d, Vector3d, Vector2d)} to indicate that one end point of the line segment lies inside of the axis-aligned box;
154     * or return value of {@link #intersectLineSegmentAar(double, double, double, double, double, double, double, double, Vector2d)} and
155     * {@link #intersectLineSegmentAar(Vector2d, Vector2d, Vector2d, Vector2d, Vector2d)} to indicate that one end point of the line segment lies inside of the axis-aligned rectangle.
156     */
157 public static immutable int ONE_INTERSECTION = 1;
158 /**
159     * Return value of {@link #intersectLineSegmentAab(double, double, double, double, double, double, double, double, double, double, double, double, Vector2d)} and
160     * {@link #intersectLineSegmentAab(Vector3d, Vector3d, Vector3d, Vector3d, Vector2d)} to indicate that the line segment intersects two sides of the axis-aligned box
161     * or lies on an edge or a side of the box;
162     * or return value of {@link #intersectLineSegmentAar(double, double, double, double, double, double, double, double, Vector2d)} and
163     * {@link #intersectLineSegmentAar(Vector2d, Vector2d, Vector2d, Vector2d, Vector2d)} to indicate that the line segment intersects two edges of the axis-aligned rectangle
164     * or lies on an edge of the rectangle.
165     */
166 public static immutable int TWO_INTERSECTION = 2;
167 /**
168     * Return value of {@link #intersectLineSegmentAab(double, double, double, double, double, double, double, double, double, double, double, double, Vector2d)} and
169     * {@link #intersectLineSegmentAab(Vector3d, Vector3d, Vector3d, Vector3d, Vector2d)} to indicate that the line segment lies completely inside of the axis-aligned box;
170     * or return value of {@link #intersectLineSegmentAar(double, double, double, double, double, double, double, double, Vector2d)} and
171     * {@link #intersectLineSegmentAar(Vector2d, Vector2d, Vector2d, Vector2d, Vector2d)} to indicate that the line segment lies completely inside of the axis-aligned rectangle.
172     */
173 public static immutable int INSIDE = 3;
174 
175 /**
176     * Test whether the plane with the general plane equation <i>a*x + b*y + c*z + d = 0</i> intersects the sphere with center
177     * <code>(centerX, centerY, centerZ)</code> and <code>radius</code>.
178     * <p>
179     * Reference: <a href="http://math.stackexchange.com/questions/943383/determine-circle-of-intersection-of-plane-and-sphere">http://math.stackexchange.com</a>
180     *
181     * @param a
182     *          the x factor in the plane equation
183     * @param b
184     *          the y factor in the plane equation
185     * @param c
186     *          the z factor in the plane equation
187     * @param d
188     *          the constant in the plane equation
189     * @param centerX
190     *          the x coordinate of the sphere's center
191     * @param centerY
192     *          the y coordinate of the sphere's center
193     * @param centerZ
194     *          the z coordinate of the sphere's center
195     * @param radius
196     *          the radius of the sphere
197     * @return <code>true</code> iff the plane intersects the sphere; <code>false</code> otherwise
198     */
199 public static bool testPlaneSphere(
200         double a, double b, double c, double d,
201         double centerX, double centerY, double centerZ, double radius) {
202     double denom = Math.sqrt(a * a + b * b + c * c);
203     double dist = (a * centerX + b * centerY + c * centerZ + d) / denom;
204     return -radius <= dist && dist <= radius;
205 }
206 
207 /**
208     * Test whether the plane with the general plane equation <i>a*x + b*y + c*z + d = 0</i> intersects the sphere with center
209     * <code>(centerX, centerY, centerZ)</code> and <code>radius</code>, and store the center of the circle of
210     * intersection in the <code>(x, y, z)</code> components of the supplied vector and the radius of that circle in the w component.
211     * <p>
212     * Reference: <a href="http://math.stackexchange.com/questions/943383/determine-circle-of-intersection-of-plane-and-sphere">http://math.stackexchange.com</a>
213     *
214     * @param a
215     *          the x factor in the plane equation
216     * @param b
217     *          the y factor in the plane equation
218     * @param c
219     *          the z factor in the plane equation
220     * @param d
221     *          the constant in the plane equation
222     * @param centerX
223     *          the x coordinate of the sphere's center
224     * @param centerY
225     *          the y coordinate of the sphere's center
226     * @param centerZ
227     *          the z coordinate of the sphere's center
228     * @param radius
229     *          the radius of the sphere
230     * @param intersectionCenterAndRadius
231     *          will hold the center of the circle of intersection in the <code>(x, y, z)</code> components and the radius in the w component
232     * @return <code>true</code> iff the plane intersects the sphere; <code>false</code> otherwise
233     */
234 public static bool intersectPlaneSphere(
235         double a, double b, double c, double d,
236         double centerX, double centerY, double centerZ, double radius,
237         Vector4d intersectionCenterAndRadius) {
238     double invDenom = Math.invsqrt(a * a + b * b + c * c);
239     double dist = (a * centerX + b * centerY + c * centerZ + d) * invDenom;
240     if (-radius <= dist && dist <= radius) {
241         intersectionCenterAndRadius.x = centerX + dist * a * invDenom;
242         intersectionCenterAndRadius.y = centerY + dist * b * invDenom;
243         intersectionCenterAndRadius.z = centerZ + dist * c * invDenom;
244         intersectionCenterAndRadius.w = Math.sqrt(radius * radius - dist * dist);
245         return true;
246     }
247     return false;
248 }
249 
250 /**
251     * Test whether the plane with the general plane equation <i>a*x + b*y + c*z + d = 0</i> intersects the moving sphere with center
252     * <code>(cX, cY, cZ)</code>, <code>radius</code> and velocity <code>(vX, vY, vZ)</code>, and store the point of intersection
253     * in the <code>(x, y, z)</code> components of the supplied vector and the time of intersection in the w component.
254     * <p>
255     * The normal vector <code>(a, b, c)</code> of the plane equation needs to be normalized.
256     * <p>
257     * Reference: Book "Real-Time Collision Detection" chapter 5.5.3 "Intersecting Moving Sphere Against Plane"
258     * 
259     * @param a
260     *          the x factor in the plane equation
261     * @param b
262     *          the y factor in the plane equation
263     * @param c
264     *          the z factor in the plane equation
265     * @param d
266     *          the constant in the plane equation
267     * @param cX
268     *          the x coordinate of the center position of the sphere at t=0
269     * @param cY
270     *          the y coordinate of the center position of the sphere at t=0
271     * @param cZ
272     *          the z coordinate of the center position of the sphere at t=0
273     * @param radius
274     *          the sphere's radius
275     * @param vX
276     *          the x component of the velocity of the sphere
277     * @param vY
278     *          the y component of the velocity of the sphere
279     * @param vZ
280     *          the z component of the velocity of the sphere
281     * @param pointAndTime
282     *          will hold the point and time of intersection (if any)
283     * @return <code>true</code> iff the sphere intersects the plane; <code>false</code> otherwise
284     */
285 public static bool intersectPlaneSweptSphere(
286         double a, double b, double c, double d,
287         double cX, double cY, double cZ, double radius,
288         double vX, double vY, double vZ,
289         Vector4d pointAndTime) {
290     // Compute distance of sphere center to plane
291     double dist = a * cX + b * cY + c * cZ - d;
292     if (Math.abs(dist) <= radius) {
293         // The sphere is already overlapping the plane. Set time of
294         // intersection to zero and q to sphere center
295         pointAndTime.set(cX, cY, cZ, 0.0);
296         return true;
297     }
298     double denom = a * vX + b * vY + c * vZ;
299     if (denom * dist >= 0.0) {
300         // No intersection as sphere moving parallel to or away from plane
301         return false;
302     }
303     // Sphere is moving towards the plane
304     // Use +r in computations if sphere in front of plane, else -r
305     double r = dist > 0.0 ? radius : -radius;
306     double t = (r - dist) / denom;
307     pointAndTime.set(
308             cX + t * vX - r * a,
309             cY + t * vY - r * b,
310             cZ + t * vZ - r * c,
311             t);
312     return true;
313 }
314 
315 /**
316     * Test whether the plane with the general plane equation <i>a*x + b*y + c*z + d = 0</i> intersects the sphere moving from center
317     * position <code>(t0X, t0Y, t0Z)</code> to <code>(t1X, t1Y, t1Z)</code> and having the given <code>radius</code>.
318     * <p>
319     * The normal vector <code>(a, b, c)</code> of the plane equation needs to be normalized.
320     * <p>
321     * Reference: Book "Real-Time Collision Detection" chapter 5.5.3 "Intersecting Moving Sphere Against Plane"
322     * 
323     * @param a
324     *          the x factor in the plane equation
325     * @param b
326     *          the y factor in the plane equation
327     * @param c
328     *          the z factor in the plane equation
329     * @param d
330     *          the constant in the plane equation
331     * @param t0X
332     *          the x coordinate of the start position of the sphere
333     * @param t0Y
334     *          the y coordinate of the start position of the sphere
335     * @param t0Z
336     *          the z coordinate of the start position of the sphere
337     * @param r
338     *          the sphere's radius
339     * @param t1X
340     *          the x coordinate of the end position of the sphere
341     * @param t1Y
342     *          the y coordinate of the end position of the sphere
343     * @param t1Z
344     *          the z coordinate of the end position of the sphere
345     * @return <code>true</code> if the sphere intersects the plane; <code>false</code> otherwise
346     */
347 public static bool testPlaneSweptSphere(
348         double a, double b, double c, double d,
349         double t0X, double t0Y, double t0Z, double r,
350         double t1X, double t1Y, double t1Z) {
351     // Get the distance for both a and b from plane p
352     double adist = t0X * a + t0Y * b + t0Z * c - d;
353     double bdist = t1X * a + t1Y * b + t1Z * c - d;
354     // Intersects if on different sides of plane (distances have different signs)
355     if (adist * bdist < 0.0) return true;
356     // Intersects if start or end position within radius from plane
357     if (Math.abs(adist) <= r || Math.abs(bdist) <= r) return true;
358     // No intersection
359     return false;
360 }
361 
362 /**
363     * Test whether the axis-aligned box with minimum corner <code>(minX, minY, minZ)</code> and maximum corner <code>(maxX, maxY, maxZ)</code>
364     * intersects the plane with the general equation <i>a*x + b*y + c*z + d = 0</i>.
365     * <p>
366     * Reference: <a href="http://www.lighthouse3d.com/tutorials/view-frustum-culling/geometric-approach-testing-boxes-ii/">http://www.lighthouse3d.com</a> ("Geometric Approach - Testing Boxes II")
367     * 
368     * @param minX
369     *          the x coordinate of the minimum corner of the axis-aligned box
370     * @param minY
371     *          the y coordinate of the minimum corner of the axis-aligned box
372     * @param minZ
373     *          the z coordinate of the minimum corner of the axis-aligned box
374     * @param maxX
375     *          the x coordinate of the maximum corner of the axis-aligned box
376     * @param maxY
377     *          the y coordinate of the maximum corner of the axis-aligned box
378     * @param maxZ
379     *          the z coordinate of the maximum corner of the axis-aligned box
380     * @param a
381     *          the x factor in the plane equation
382     * @param b
383     *          the y factor in the plane equation
384     * @param c
385     *          the z factor in the plane equation
386     * @param d
387     *          the constant in the plane equation
388     * @return <code>true</code> iff the axis-aligned box intersects the plane; <code>false</code> otherwise
389     */
390 public static bool testAabPlane(
391         double minX, double minY, double minZ,
392         double maxX, double maxY, double maxZ,
393         double a, double b, double c, double d) {
394     double pX, pY, pZ, nX, nY, nZ;
395     if (a > 0.0) {
396         pX = maxX;
397         nX = minX;
398     } else {
399         pX = minX;
400         nX = maxX;
401     }
402     if (b > 0.0) {
403         pY = maxY;
404         nY = minY;
405     } else {
406         pY = minY;
407         nY = maxY;
408     }
409     if (c > 0.0) {
410         pZ = maxZ;
411         nZ = minZ;
412     } else {
413         pZ = minZ;
414         nZ = maxZ;
415     }
416     double distN = d + a * nX + b * nY + c * nZ;
417     double distP = d + a * pX + b * pY + c * pZ;
418     return distN <= 0.0 && distP >= 0.0;
419 }
420 
421 /**
422     * Test whether the axis-aligned box with minimum corner <code>min</code> and maximum corner <code>max</code>
423     * intersects the plane with the general equation <i>a*x + b*y + c*z + d = 0</i>.
424     * <p>
425     * Reference: <a href="http://www.lighthouse3d.com/tutorials/view-frustum-culling/geometric-approach-testing-boxes-ii/">http://www.lighthouse3d.com</a> ("Geometric Approach - Testing Boxes II")
426     * 
427     * @param min
428     *          the minimum corner of the axis-aligned box
429     * @param max
430     *          the maximum corner of the axis-aligned box
431     * @param a
432     *          the x factor in the plane equation
433     * @param b
434     *          the y factor in the plane equation
435     * @param c
436     *          the z factor in the plane equation
437     * @param d
438     *          the constant in the plane equation
439     * @return <code>true</code> iff the axis-aligned box intersects the plane; <code>false</code> otherwise
440     */
441 public static bool testAabPlane(Vector3d min, Vector3d max, double a, double b, double c, double d) {
442     return testAabPlane(min.x, min.y, min.z, max.x, max.y, max.z, a, b, c, d);
443 }
444 
445 /**
446     * Test whether the axis-aligned box with minimum corner <code>(minXA, minYA, minZA)</code> and maximum corner <code>(maxXA, maxYA, maxZA)</code>
447     * intersects the axis-aligned box with minimum corner <code>(minXB, minYB, minZB)</code> and maximum corner <code>(maxXB, maxYB, maxZB)</code>.
448     * 
449     * @param minXA
450     *              the x coordinate of the minimum corner of the first axis-aligned box
451     * @param minYA
452     *              the y coordinate of the minimum corner of the first axis-aligned box
453     * @param minZA
454     *              the z coordinate of the minimum corner of the first axis-aligned box
455     * @param maxXA
456     *              the x coordinate of the maximum corner of the first axis-aligned box
457     * @param maxYA
458     *              the y coordinate of the maximum corner of the first axis-aligned box
459     * @param maxZA
460     *              the z coordinate of the maximum corner of the first axis-aligned box
461     * @param minXB
462     *              the x coordinate of the minimum corner of the second axis-aligned box
463     * @param minYB
464     *              the y coordinate of the minimum corner of the second axis-aligned box
465     * @param minZB
466     *              the z coordinate of the minimum corner of the second axis-aligned box
467     * @param maxXB
468     *              the x coordinate of the maximum corner of the second axis-aligned box
469     * @param maxYB
470     *              the y coordinate of the maximum corner of the second axis-aligned box
471     * @param maxZB
472     *              the z coordinate of the maximum corner of the second axis-aligned box
473     * @return <code>true</code> iff both axis-aligned boxes intersect; <code>false</code> otherwise
474     */
475 public static bool testAabAab(
476         double minXA, double minYA, double minZA,
477         double maxXA, double maxYA, double maxZA,
478         double minXB, double minYB, double minZB,
479         double maxXB, double maxYB, double maxZB) {
480     return maxXA >= minXB && maxYA >= minYB && maxZA >= minZB && 
481             minXA <= maxXB && minYA <= maxYB && minZA <= maxZB;
482 }
483 
484 /**
485     * Test whether the axis-aligned box with minimum corner <code>minA</code> and maximum corner <code>maxA</code>
486     * intersects the axis-aligned box with minimum corner <code>minB</code> and maximum corner <code>maxB</code>.
487     * 
488     * @param minA
489     *              the minimum corner of the first axis-aligned box
490     * @param maxA
491     *              the maximum corner of the first axis-aligned box
492     * @param minB
493     *              the minimum corner of the second axis-aligned box
494     * @param maxB
495     *              the maximum corner of the second axis-aligned box
496     * @return <code>true</code> iff both axis-aligned boxes intersect; <code>false</code> otherwise
497     */
498 public static bool testAabAab(Vector3d minA, Vector3d maxA, Vector3d minB, Vector3d maxB) {
499     return testAabAab(minA.x, minA.y, minA.z, maxA.x, maxA.y, maxA.z, minB.x, minB.y, minB.z, maxB.x, maxB.y, maxB.z);
500 }
501 
502 /**
503     * Test whether two oriented boxes given via their center position, orientation and half-size, intersect.
504     * <p>
505     * The orientation of a box is given as three unit vectors spanning the local orthonormal basis of the box.
506     * <p>
507     * The size is given as the half-size along each of the unit vectors defining the orthonormal basis.
508     * <p>
509     * Reference: Book "Real-Time Collision Detection" chapter 4.4.1 "OBB-OBB Intersection"
510     * 
511     * @param b0c
512     *          the center of the first box
513     * @param b0uX
514     *          the local X unit vector of the first box
515     * @param b0uY
516     *          the local Y unit vector of the first box
517     * @param b0uZ
518     *          the local Z unit vector of the first box
519     * @param b0hs
520     *          the half-size of the first box
521     * @param b1c
522     *          the center of the second box
523     * @param b1uX
524     *          the local X unit vector of the second box
525     * @param b1uY
526     *          the local Y unit vector of the second box
527     * @param b1uZ
528     *          the local Z unit vector of the second box
529     * @param b1hs
530     *          the half-size of the second box
531     * @return <code>true</code> if both boxes intersect; <code>false</code> otherwise
532     */
533 public static bool testObOb(
534         Vector3d b0c, Vector3d b0uX, Vector3d b0uY, Vector3d b0uZ, Vector3d b0hs,
535         Vector3d b1c, Vector3d b1uX, Vector3d b1uY, Vector3d b1uZ, Vector3d b1hs) {
536     return testObOb(
537             b0c.x, b0c.y, b0c.z, b0uX.x, b0uX.y, b0uX.z, b0uY.x, b0uY.y, b0uY.z, b0uZ.x, b0uZ.y, b0uZ.z, b0hs.x, b0hs.y, b0hs.z,
538             b1c.x, b1c.y, b1c.z, b1uX.x, b1uX.y, b1uX.z, b1uY.x, b1uY.y, b1uY.z, b1uZ.x, b1uZ.y, b1uZ.z, b1hs.x, b1hs.y, b1hs.z);
539 }
540 
541 /**
542     * Test whether two oriented boxes given via their center position, orientation and half-size, intersect.
543     * <p>
544     * The orientation of a box is given as three unit vectors spanning the local orthonormal basis of the box.
545     * <p>
546     * The size is given as the half-size along each of the unit vectors defining the orthonormal basis.
547     * <p>
548     * Reference: Book "Real-Time Collision Detection" chapter 4.4.1 "OBB-OBB Intersection"
549     * 
550     * @param b0cX
551     *          the x coordinate of the center of the first box
552     * @param b0cY
553     *          the y coordinate of the center of the first box
554     * @param b0cZ
555     *          the z coordinate of the center of the first box
556     * @param b0uXx
557     *          the x coordinate of the local X unit vector of the first box
558     * @param b0uXy
559     *          the y coordinate of the local X unit vector of the first box
560     * @param b0uXz
561     *          the z coordinate of the local X unit vector of the first box
562     * @param b0uYx
563     *          the x coordinate of the local Y unit vector of the first box
564     * @param b0uYy
565     *          the y coordinate of the local Y unit vector of the first box
566     * @param b0uYz
567     *          the z coordinate of the local Y unit vector of the first box
568     * @param b0uZx
569     *          the x coordinate of the local Z unit vector of the first box
570     * @param b0uZy
571     *          the y coordinate of the local Z unit vector of the first box
572     * @param b0uZz
573     *          the z coordinate of the local Z unit vector of the first box
574     * @param b0hsX
575     *          the half-size of the first box along its local X axis
576     * @param b0hsY
577     *          the half-size of the first box along its local Y axis
578     * @param b0hsZ
579     *          the half-size of the first box along its local Z axis
580     * @param b1cX
581     *          the x coordinate of the center of the second box
582     * @param b1cY
583     *          the y coordinate of the center of the second box
584     * @param b1cZ
585     *          the z coordinate of the center of the second box
586     * @param b1uXx
587     *          the x coordinate of the local X unit vector of the second box
588     * @param b1uXy
589     *          the y coordinate of the local X unit vector of the second box
590     * @param b1uXz
591     *          the z coordinate of the local X unit vector of the second box
592     * @param b1uYx
593     *          the x coordinate of the local Y unit vector of the second box
594     * @param b1uYy
595     *          the y coordinate of the local Y unit vector of the second box
596     * @param b1uYz
597     *          the z coordinate of the local Y unit vector of the second box
598     * @param b1uZx
599     *          the x coordinate of the local Z unit vector of the second box
600     * @param b1uZy
601     *          the y coordinate of the local Z unit vector of the second box
602     * @param b1uZz
603     *          the z coordinate of the local Z unit vector of the second box
604     * @param b1hsX
605     *          the half-size of the second box along its local X axis
606     * @param b1hsY
607     *          the half-size of the second box along its local Y axis
608     * @param b1hsZ
609     *          the half-size of the second box along its local Z axis
610     * @return <code>true</code> if both boxes intersect; <code>false</code> otherwise
611     */
612 public static bool testObOb(
613         double b0cX, double b0cY, double b0cZ, double b0uXx, double b0uXy, double b0uXz, double b0uYx, double b0uYy, double b0uYz, double b0uZx, double b0uZy, double b0uZz, double b0hsX, double b0hsY, double b0hsZ,
614         double b1cX, double b1cY, double b1cZ, double b1uXx, double b1uXy, double b1uXz, double b1uYx, double b1uYy, double b1uYz, double b1uZx, double b1uZy, double b1uZz, double b1hsX, double b1hsY, double b1hsZ) {
615     double ra, rb;
616     // Compute rotation matrix expressing b in a's coordinate frame
617     double rm00 = b0uXx * b1uXx + b0uYx * b1uYx + b0uZx * b1uZx;
618     double rm10 = b0uXx * b1uXy + b0uYx * b1uYy + b0uZx * b1uZy;
619     double rm20 = b0uXx * b1uXz + b0uYx * b1uYz + b0uZx * b1uZz;
620     double rm01 = b0uXy * b1uXx + b0uYy * b1uYx + b0uZy * b1uZx;
621     double rm11 = b0uXy * b1uXy + b0uYy * b1uYy + b0uZy * b1uZy;
622     double rm21 = b0uXy * b1uXz + b0uYy * b1uYz + b0uZy * b1uZz;
623     double rm02 = b0uXz * b1uXx + b0uYz * b1uYx + b0uZz * b1uZx;
624     double rm12 = b0uXz * b1uXy + b0uYz * b1uYy + b0uZz * b1uZy;
625     double rm22 = b0uXz * b1uXz + b0uYz * b1uYz + b0uZz * b1uZz;
626     // Compute common subexpressions. Add in an epsilon term to
627     // counteract arithmetic errors when two edges are parallel and
628     // their cross product is (near) null (see text for details)
629     double EPSILON = 1E-8;
630     double arm00 = Math.abs(rm00) + EPSILON;
631     double arm01 = Math.abs(rm01) + EPSILON;
632     double arm02 = Math.abs(rm02) + EPSILON;
633     double arm10 = Math.abs(rm10) + EPSILON;
634     double arm11 = Math.abs(rm11) + EPSILON;
635     double arm12 = Math.abs(rm12) + EPSILON;
636     double arm20 = Math.abs(rm20) + EPSILON;
637     double arm21 = Math.abs(rm21) + EPSILON;
638     double arm22 = Math.abs(rm22) + EPSILON;
639     // Compute translation vector t
640     double tx = b1cX - b0cX, ty = b1cY - b0cY, tz = b1cZ - b0cZ;
641     // Bring translation into a's coordinate frame
642     double tax = tx * b0uXx + ty * b0uXy + tz * b0uXz;
643     double tay = tx * b0uYx + ty * b0uYy + tz * b0uYz;
644     double taz = tx * b0uZx + ty * b0uZy + tz * b0uZz;
645     // Test axes L = A0, L = A1, L = A2
646     ra = b0hsX;
647     rb = b1hsX * arm00 + b1hsY * arm01 + b1hsZ * arm02;
648     if (Math.abs(tax) > ra + rb) return false;
649     ra = b0hsY;
650     rb = b1hsX * arm10 + b1hsY * arm11 + b1hsZ * arm12;
651     if (Math.abs(tay) > ra + rb) return false;
652     ra = b0hsZ;
653     rb = b1hsX * arm20 + b1hsY * arm21 + b1hsZ * arm22;
654     if (Math.abs(taz) > ra + rb) return false;
655     // Test axes L = B0, L = B1, L = B2
656     ra = b0hsX * arm00 + b0hsY * arm10 + b0hsZ * arm20;
657     rb = b1hsX;
658     if (Math.abs(tax * rm00 + tay * rm10 + taz * rm20) > ra + rb) return false;
659     ra = b0hsX * arm01 + b0hsY * arm11 + b0hsZ * arm21;
660     rb = b1hsY;
661     if (Math.abs(tax * rm01 + tay * rm11 + taz * rm21) > ra + rb) return false;
662     ra = b0hsX * arm02 + b0hsY * arm12 + b0hsZ * arm22;
663     rb = b1hsZ;
664     if (Math.abs(tax * rm02 + tay * rm12 + taz * rm22) > ra + rb) return false;
665     // Test axis L = A0 x B0
666     ra = b0hsY * arm20 + b0hsZ * arm10;
667     rb = b1hsY * arm02 + b1hsZ * arm01;
668     if (Math.abs(taz * rm10 - tay * rm20) > ra + rb) return false;
669     // Test axis L = A0 x B1
670     ra = b0hsY * arm21 + b0hsZ * arm11;
671     rb = b1hsX * arm02 + b1hsZ * arm00;
672     if (Math.abs(taz * rm11 - tay * rm21) > ra + rb) return false;
673     // Test axis L = A0 x B2
674     ra = b0hsY * arm22 + b0hsZ * arm12;
675     rb = b1hsX * arm01 + b1hsY * arm00;
676     if (Math.abs(taz * rm12 - tay * rm22) > ra + rb) return false;
677     // Test axis L = A1 x B0
678     ra = b0hsX * arm20 + b0hsZ * arm00;
679     rb = b1hsY * arm12 + b1hsZ * arm11;
680     if (Math.abs(tax * rm20 - taz * rm00) > ra + rb) return false;
681     // Test axis L = A1 x B1
682     ra = b0hsX * arm21 + b0hsZ * arm01;
683     rb = b1hsX * arm12 + b1hsZ * arm10;
684     if (Math.abs(tax * rm21 - taz * rm01) > ra + rb) return false;
685     // Test axis L = A1 x B2
686     ra = b0hsX * arm22 + b0hsZ * arm02;
687     rb = b1hsX * arm11 + b1hsY * arm10;
688     if (Math.abs(tax * rm22 - taz * rm02) > ra + rb) return false;
689     // Test axis L = A2 x B0
690     ra = b0hsX * arm10 + b0hsY * arm00;
691     rb = b1hsY * arm22 + b1hsZ * arm21;
692     if (Math.abs(tay * rm00 - tax * rm10) > ra + rb) return false;
693     // Test axis L = A2 x B1
694     ra = b0hsX * arm11 + b0hsY * arm01;
695     rb = b1hsX * arm22 + b1hsZ * arm20;
696     if (Math.abs(tay * rm01 - tax * rm11) > ra + rb) return false;
697     // Test axis L = A2 x B2
698     ra = b0hsX * arm12 + b0hsY * arm02;
699     rb = b1hsX * arm21 + b1hsY * arm20;
700     if (Math.abs(tay * rm02 - tax * rm12) > ra + rb) return false;
701     // Since no separating axis is found, the OBBs must be intersecting
702     return true;
703 }
704 
705 /**
706     * Test whether the one sphere with center <code>(aX, aY, aZ)</code> and square radius <code>radiusSquaredA</code> intersects the other
707     * sphere with center <code>(bX, bY, bZ)</code> and square radius <code>radiusSquaredB</code>, and store the center of the circle of
708     * intersection in the <code>(x, y, z)</code> components of the supplied vector and the radius of that circle in the w component.
709     * <p>
710     * The normal vector of the circle of intersection can simply be obtained by subtracting the center of either sphere from the other.
711     * <p>
712     * Reference: <a href="http://gamedev.stackexchange.com/questions/75756/sphere-sphere-intersection-and-circle-sphere-intersection">http://gamedev.stackexchange.com</a>
713     * 
714     * @param aX
715     *              the x coordinate of the first sphere's center
716     * @param aY
717     *              the y coordinate of the first sphere's center
718     * @param aZ
719     *              the z coordinate of the first sphere's center
720     * @param radiusSquaredA
721     *              the square of the first sphere's radius
722     * @param bX
723     *              the x coordinate of the second sphere's center
724     * @param bY
725     *              the y coordinate of the second sphere's center
726     * @param bZ
727     *              the z coordinate of the second sphere's center
728     * @param radiusSquaredB
729     *              the square of the second sphere's radius
730     * @param centerAndRadiusOfIntersectionCircle
731     *              will hold the center of the circle of intersection in the <code>(x, y, z)</code> components and the radius in the w component
732     * @return <code>true</code> iff both spheres intersect; <code>false</code> otherwise
733     */
734 public static bool intersectSphereSphere(
735         double aX, double aY, double aZ, double radiusSquaredA,
736         double bX, double bY, double bZ, double radiusSquaredB,
737         Vector4d centerAndRadiusOfIntersectionCircle) {
738     double dX = bX - aX, dY = bY - aY, dZ = bZ - aZ;
739     double distSquared = dX * dX + dY * dY + dZ * dZ;
740     double h = 0.5 + (radiusSquaredA - radiusSquaredB) / (2.0 * distSquared);
741     double r_i = radiusSquaredA - h * h * distSquared;
742     if (r_i >= 0.0) {
743         centerAndRadiusOfIntersectionCircle.x = aX + h * dX;
744         centerAndRadiusOfIntersectionCircle.y = aY + h * dY;
745         centerAndRadiusOfIntersectionCircle.z = aZ + h * dZ;
746         centerAndRadiusOfIntersectionCircle.w = Math.sqrt(r_i);
747         return true;
748     }
749     return false;
750 }
751 
752 /**
753     * Test whether the one sphere with center <code>centerA</code> and square radius <code>radiusSquaredA</code> intersects the other
754     * sphere with center <code>centerB</code> and square radius <code>radiusSquaredB</code>, and store the center of the circle of
755     * intersection in the <code>(x, y, z)</code> components of the supplied vector and the radius of that circle in the w component.
756     * <p>
757     * The normal vector of the circle of intersection can simply be obtained by subtracting the center of either sphere from the other.
758     * <p>
759     * Reference: <a href="http://gamedev.stackexchange.com/questions/75756/sphere-sphere-intersection-and-circle-sphere-intersection">http://gamedev.stackexchange.com</a>
760     * 
761     * @param centerA
762     *              the first sphere's center
763     * @param radiusSquaredA
764     *              the square of the first sphere's radius
765     * @param centerB
766     *              the second sphere's center
767     * @param radiusSquaredB
768     *              the square of the second sphere's radius
769     * @param centerAndRadiusOfIntersectionCircle
770     *              will hold the center of the circle of intersection in the <code>(x, y, z)</code> components and the radius in the w component
771     * @return <code>true</code> iff both spheres intersect; <code>false</code> otherwise
772     */
773 public static bool intersectSphereSphere(Vector3d centerA, double radiusSquaredA, Vector3d centerB, double radiusSquaredB, Vector4d centerAndRadiusOfIntersectionCircle) {
774     return intersectSphereSphere(centerA.x, centerA.y, centerA.z, radiusSquaredA, centerB.x, centerB.y, centerB.z, radiusSquaredB, centerAndRadiusOfIntersectionCircle);
775 }
776 
777 /**
778     * Test whether the given sphere with center <code>(sX, sY, sZ)</code> intersects the triangle given by its three vertices, and if they intersect
779     * store the point of intersection into <code>result</code>.
780     * <p>
781     * This method also returns whether the point of intersection is on one of the triangle's vertices, edges or on the face.
782     * <p>
783     * Reference: Book "Real-Time Collision Detection" chapter 5.2.7 "Testing Sphere Against Triangle"
784     * 
785     * @param sX
786     *          the x coordinate of the sphere's center
787     * @param sY
788     *          the y coordinate of the sphere's center
789     * @param sZ
790     *          the z coordinate of the sphere's center
791     * @param sR
792     *          the sphere's radius
793     * @param v0X
794     *          the x coordinate of the first vertex of the triangle
795     * @param v0Y
796     *          the y coordinate of the first vertex of the triangle
797     * @param v0Z
798     *          the z coordinate of the first vertex of the triangle
799     * @param v1X
800     *          the x coordinate of the second vertex of the triangle
801     * @param v1Y
802     *          the y coordinate of the second vertex of the triangle
803     * @param v1Z
804     *          the z coordinate of the second vertex of the triangle
805     * @param v2X
806     *          the x coordinate of the third vertex of the triangle
807     * @param v2Y
808     *          the y coordinate of the third vertex of the triangle
809     * @param v2Z
810     *          the z coordinate of the third vertex of the triangle
811     * @param result
812     *          will hold the point of intersection
813     * @return one of {@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1}, {@link #POINT_ON_TRIANGLE_VERTEX_2},
814     *                {@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12}, {@link #POINT_ON_TRIANGLE_EDGE_20} or
815     *                {@link #POINT_ON_TRIANGLE_FACE} or <code>0</code>
816     */
817 public static int intersectSphereTriangle(
818         double sX, double sY, double sZ, double sR,
819         double v0X, double v0Y, double v0Z,
820         double v1X, double v1Y, double v1Z,
821         double v2X, double v2Y, double v2Z,
822         Vector3d result) {
823     int closest = findClosestPointOnTriangle(v0X, v0Y, v0Z, v1X, v1Y, v1Z, v2X, v2Y, v2Z, sX, sY, sZ, result);
824     double vX = result.x - sX, vY = result.y - sY, vZ = result.z - sZ;
825     double dot = vX * vX + vY * vY + vZ * vZ;
826     if (dot <= sR * sR) {
827         return closest;
828     }
829     return 0;
830 }
831 
832 /**
833     * Test whether the one sphere with center <code>(aX, aY, aZ)</code> and square radius <code>radiusSquaredA</code> intersects the other
834     * sphere with center <code>(bX, bY, bZ)</code> and square radius <code>radiusSquaredB</code>.
835     * <p>
836     * Reference: <a href="http://gamedev.stackexchange.com/questions/75756/sphere-sphere-intersection-and-circle-sphere-intersection">http://gamedev.stackexchange.com</a>
837     * 
838     * @param aX
839     *              the x coordinate of the first sphere's center
840     * @param aY
841     *              the y coordinate of the first sphere's center
842     * @param aZ
843     *              the z coordinate of the first sphere's center
844     * @param radiusSquaredA
845     *              the square of the first sphere's radius
846     * @param bX
847     *              the x coordinate of the second sphere's center
848     * @param bY
849     *              the y coordinate of the second sphere's center
850     * @param bZ
851     *              the z coordinate of the second sphere's center
852     * @param radiusSquaredB
853     *              the square of the second sphere's radius
854     * @return <code>true</code> iff both spheres intersect; <code>false</code> otherwise
855     */
856 public static bool testSphereSphere(
857         double aX, double aY, double aZ, double radiusSquaredA,
858         double bX, double bY, double bZ, double radiusSquaredB) {
859     double dX = bX - aX, dY = bY - aY, dZ = bZ - aZ;
860     double distSquared = dX * dX + dY * dY + dZ * dZ;
861     double h = 0.5 + (radiusSquaredA - radiusSquaredB) / (2.0 * distSquared);
862     double r_i = radiusSquaredA - h * h * distSquared;
863     return r_i >= 0.0;
864 }
865 
866 /**
867     * Test whether the one sphere with center <code>centerA</code> and square radius <code>radiusSquaredA</code> intersects the other
868     * sphere with center <code>centerB</code> and square radius <code>radiusSquaredB</code>.
869     * <p>
870     * Reference: <a href="http://gamedev.stackexchange.com/questions/75756/sphere-sphere-intersection-and-circle-sphere-intersection">http://gamedev.stackexchange.com</a>
871     * 
872     * @param centerA
873     *              the first sphere's center
874     * @param radiusSquaredA
875     *              the square of the first sphere's radius
876     * @param centerB
877     *              the second sphere's center
878     * @param radiusSquaredB
879     *              the square of the second sphere's radius
880     * @return <code>true</code> iff both spheres intersect; <code>false</code> otherwise
881     */
882 public static bool testSphereSphere(Vector3d centerA, double radiusSquaredA, Vector3d centerB, double radiusSquaredB) {
883     return testSphereSphere(centerA.x, centerA.y, centerA.z, radiusSquaredA, centerB.x, centerB.y, centerB.z, radiusSquaredB);
884 }
885 
886 /**
887     * Determine the signed distance of the given point <code>(pointX, pointY, pointZ)</code> to the plane specified via its general plane equation
888     * <i>a*x + b*y + c*z + d = 0</i>.
889     * 
890     * @param pointX
891     *              the x coordinate of the point
892     * @param pointY
893     *              the y coordinate of the point
894     * @param pointZ
895     *              the z coordinate of the point
896     * @param a
897     *              the x factor in the plane equation
898     * @param b
899     *              the y factor in the plane equation
900     * @param c
901     *              the z factor in the plane equation
902     * @param d
903     *              the constant in the plane equation
904     * @return the distance between the point and the plane
905     */
906 public static double distancePointPlane(double pointX, double pointY, double pointZ, double a, double b, double c, double d) {
907     double denom = Math.sqrt(a * a + b * b + c * c);
908     return (a * pointX + b * pointY + c * pointZ + d) / denom;
909 }
910 
911 /**
912     * Determine the signed distance of the given point <code>(pointX, pointY, pointZ)</code> to the plane of the triangle specified by its three points
913     * <code>(v0X, v0Y, v0Z)</code>, <code>(v1X, v1Y, v1Z)</code> and <code>(v2X, v2Y, v2Z)</code>.
914     * <p>
915     * If the point lies on the front-facing side of the triangle's plane, that is, if the triangle has counter-clockwise winding order
916     * as seen from the point, then this method returns a positive number.
917     * 
918     * @param pointX
919     *          the x coordinate of the point
920     * @param pointY
921     *          the y coordinate of the point
922     * @param pointZ
923     *          the z coordinate of the point
924     * @param v0X
925     *          the x coordinate of the first vertex of the triangle
926     * @param v0Y
927     *          the y coordinate of the first vertex of the triangle
928     * @param v0Z
929     *          the z coordinate of the first vertex of the triangle
930     * @param v1X
931     *          the x coordinate of the second vertex of the triangle
932     * @param v1Y
933     *          the y coordinate of the second vertex of the triangle
934     * @param v1Z
935     *          the z coordinate of the second vertex of the triangle
936     * @param v2X
937     *          the x coordinate of the third vertex of the triangle
938     * @param v2Y
939     *          the y coordinate of the third vertex of the triangle
940     * @param v2Z
941     *          the z coordinate of the third vertex of the triangle
942     * @return the signed distance between the point and the plane of the triangle
943     */
944 public static double distancePointPlane(double pointX, double pointY, double pointZ,
945         double v0X, double v0Y, double v0Z, double v1X, double v1Y, double v1Z, double v2X, double v2Y, double v2Z) {
946     double v1Y0Y = v1Y - v0Y;
947     double v2Z0Z = v2Z - v0Z;
948     double v2Y0Y = v2Y - v0Y;
949     double v1Z0Z = v1Z - v0Z;
950     double v2X0X = v2X - v0X;
951     double v1X0X = v1X - v0X;
952     double a = v1Y0Y * v2Z0Z - v2Y0Y * v1Z0Z;
953     double b = v1Z0Z * v2X0X - v2Z0Z * v1X0X;
954     double c = v1X0X * v2Y0Y - v2X0X * v1Y0Y;
955     double d = -(a * v0X + b * v0Y + c * v0Z);
956     return distancePointPlane(pointX, pointY, pointZ, a, b, c, d);
957 }
958 
959 /**
960     * Test whether the ray with given origin <code>(originX, originY, originZ)</code> and direction <code>(dirX, dirY, dirZ)</code> intersects the plane
961     * containing the given point <code>(pointX, pointY, pointZ)</code> and having the normal <code>(normalX, normalY, normalZ)</code>, and return the
962     * value of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> of the intersection point.
963     * <p>
964     * This method returns <code>-1.0</code> if the ray does not intersect the plane, because it is either parallel to the plane or its direction points
965     * away from the plane or the ray's origin is on the <i>negative</i> side of the plane (i.e. the plane's normal points away from the ray's origin).
966     * <p>
967     * Reference: <a href="https://www.siggraph.org/education/materials/HyperGraph/raytrace/rayplane_intersection.htm">https://www.siggraph.org/</a>
968     * 
969     * @param originX
970     *              the x coordinate of the ray's origin
971     * @param originY
972     *              the y coordinate of the ray's origin
973     * @param originZ
974     *              the z coordinate of the ray's origin
975     * @param dirX
976     *              the x coordinate of the ray's direction
977     * @param dirY
978     *              the y coordinate of the ray's direction
979     * @param dirZ
980     *              the z coordinate of the ray's direction
981     * @param pointX
982     *              the x coordinate of a point on the plane
983     * @param pointY
984     *              the y coordinate of a point on the plane
985     * @param pointZ
986     *              the z coordinate of a point on the plane
987     * @param normalX
988     *              the x coordinate of the plane's normal
989     * @param normalY
990     *              the y coordinate of the plane's normal
991     * @param normalZ
992     *              the z coordinate of the plane's normal
993     * @param epsilon
994     *              some small epsilon for when the ray is parallel to the plane
995     * @return the value of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> of the intersection point, if the ray
996     *         intersects the plane; <code>-1.0</code> otherwise
997     */
998 public static double intersectRayPlane(double originX, double originY, double originZ, double dirX, double dirY, double dirZ,
999         double pointX, double pointY, double pointZ, double normalX, double normalY, double normalZ, double epsilon) {
1000     double denom = normalX * dirX + normalY * dirY + normalZ * dirZ;
1001     if (denom < epsilon) {
1002         double t = ((pointX - originX) * normalX + (pointY - originY) * normalY + (pointZ - originZ) * normalZ) / denom;
1003         if (t >= 0.0)
1004             return t;
1005     }
1006     return -1.0;
1007 }
1008 
1009 /**
1010     * Test whether the ray with given <code>origin</code> and direction <code>dir</code> intersects the plane
1011     * containing the given <code>point</code> and having the given <code>normal</code>, and return the
1012     * value of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> of the intersection point.
1013     * <p>
1014     * This method returns <code>-1.0</code> if the ray does not intersect the plane, because it is either parallel to the plane or its direction points
1015     * away from the plane or the ray's origin is on the <i>negative</i> side of the plane (i.e. the plane's normal points away from the ray's origin).
1016     * <p>
1017     * Reference: <a href="https://www.siggraph.org/education/materials/HyperGraph/raytrace/rayplane_intersection.htm">https://www.siggraph.org/</a>
1018     * 
1019     * @param origin
1020     *              the ray's origin
1021     * @param dir
1022     *              the ray's direction
1023     * @param point
1024     *              a point on the plane
1025     * @param normal
1026     *              the plane's normal
1027     * @param epsilon
1028     *              some small epsilon for when the ray is parallel to the plane
1029     * @return the value of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> of the intersection point, if the ray
1030     *         intersects the plane; <code>-1.0</code> otherwise
1031     */
1032 public static double intersectRayPlane(Vector3d origin, Vector3d dir, Vector3d point, Vector3d normal, double epsilon) {
1033     return intersectRayPlane(origin.x, origin.y, origin.z, dir.x, dir.y, dir.z, point.x, point.y, point.z, normal.x, normal.y, normal.z, epsilon);
1034 }
1035 
1036 /**
1037     * Test whether the ray with given origin <code>(originX, originY, originZ)</code> and direction <code>(dirX, dirY, dirZ)</code> intersects the plane
1038     * given as the general plane equation <i>a*x + b*y + c*z + d = 0</i>, and return the
1039     * value of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> of the intersection point.
1040     * <p>
1041     * This method returns <code>-1.0</code> if the ray does not intersect the plane, because it is either parallel to the plane or its direction points
1042     * away from the plane or the ray's origin is on the <i>negative</i> side of the plane (i.e. the plane's normal points away from the ray's origin).
1043     * <p>
1044     * Reference: <a href="https://www.siggraph.org/education/materials/HyperGraph/raytrace/rayplane_intersection.htm">https://www.siggraph.org/</a>
1045     * 
1046     * @param originX
1047     *              the x coordinate of the ray's origin
1048     * @param originY
1049     *              the y coordinate of the ray's origin
1050     * @param originZ
1051     *              the z coordinate of the ray's origin
1052     * @param dirX
1053     *              the x coordinate of the ray's direction
1054     * @param dirY
1055     *              the y coordinate of the ray's direction
1056     * @param dirZ
1057     *              the z coordinate of the ray's direction
1058     * @param a
1059     *              the x factor in the plane equation
1060     * @param b
1061     *              the y factor in the plane equation
1062     * @param c
1063     *              the z factor in the plane equation
1064     * @param d
1065     *              the constant in the plane equation
1066     * @param epsilon
1067     *              some small epsilon for when the ray is parallel to the plane
1068     * @return the value of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> of the intersection point, if the ray
1069     *         intersects the plane; <code>-1.0</code> otherwise
1070     */
1071 public static double intersectRayPlane(double originX, double originY, double originZ, double dirX, double dirY, double dirZ,
1072         double a, double b, double c, double d, double epsilon) {
1073     double denom = a * dirX + b * dirY + c * dirZ;
1074     if (denom < 0.0) {
1075         double t = -(a * originX + b * originY + c * originZ + d) / denom;
1076         if (t >= 0.0)
1077             return t;
1078     }
1079     return -1.0;
1080 }
1081 
1082 /**
1083     * Test whether the axis-aligned box with minimum corner <code>(minX, minY, minZ)</code> and maximum corner <code>(maxX, maxY, maxZ)</code>
1084     * intersects the sphere with the given center <code>(centerX, centerY, centerZ)</code> and square radius <code>radiusSquared</code>.
1085     * <p>
1086     * Reference: <a href="http://stackoverflow.com/questions/4578967/cube-sphere-intersection-test#answer-4579069">http://stackoverflow.com</a>
1087     * 
1088     * @param minX
1089     *          the x coordinate of the minimum corner of the axis-aligned box
1090     * @param minY
1091     *          the y coordinate of the minimum corner of the axis-aligned box
1092     * @param minZ
1093     *          the z coordinate of the minimum corner of the axis-aligned box
1094     * @param maxX
1095     *          the x coordinate of the maximum corner of the axis-aligned box
1096     * @param maxY
1097     *          the y coordinate of the maximum corner of the axis-aligned box
1098     * @param maxZ
1099     *          the z coordinate of the maximum corner of the axis-aligned box
1100     * @param centerX
1101     *          the x coordinate of the sphere's center
1102     * @param centerY
1103     *          the y coordinate of the sphere's center
1104     * @param centerZ
1105     *          the z coordinate of the sphere's center
1106     * @param radiusSquared
1107     *          the square of the sphere's radius
1108     * @return <code>true</code> iff the axis-aligned box intersects the sphere; <code>false</code> otherwise
1109     */
1110 public static bool testAabSphere(
1111         double minX, double minY, double minZ,
1112         double maxX, double maxY, double maxZ,
1113         double centerX, double centerY, double centerZ, double radiusSquared) {
1114     double radius2 = radiusSquared;
1115     if (centerX < minX) {
1116         double d = (centerX - minX);
1117         radius2 -= d * d;
1118     } else if (centerX > maxX) {
1119         double d = (centerX - maxX);
1120         radius2 -= d * d;
1121     }
1122     if (centerY < minY) {
1123         double d = (centerY - minY);
1124         radius2 -= d * d;
1125     } else if (centerY > maxY) {
1126         double d = (centerY - maxY);
1127         radius2 -= d * d;
1128     }
1129     if (centerZ < minZ) {
1130         double d = (centerZ - minZ);
1131         radius2 -= d * d;
1132     } else if (centerZ > maxZ) {
1133         double d = (centerZ - maxZ);
1134         radius2 -= d * d;
1135     }
1136     return radius2 >= 0.0;
1137 }
1138 
1139 /**
1140     * Test whether the axis-aligned box with minimum corner <code>min</code> and maximum corner <code>max</code>
1141     * intersects the sphere with the given <code>center</code> and square radius <code>radiusSquared</code>.
1142     * <p>
1143     * Reference: <a href="http://stackoverflow.com/questions/4578967/cube-sphere-intersection-test#answer-4579069">http://stackoverflow.com</a>
1144     * 
1145     * @param min
1146     *          the minimum corner of the axis-aligned box
1147     * @param max
1148     *          the maximum corner of the axis-aligned box
1149     * @param center
1150     *          the sphere's center
1151     * @param radiusSquared
1152     *          the squared of the sphere's radius
1153     * @return <code>true</code> iff the axis-aligned box intersects the sphere; <code>false</code> otherwise
1154     */
1155 public static bool testAabSphere(Vector3d min, Vector3d max, Vector3d center, double radiusSquared) {
1156     return testAabSphere(min.x, min.y, min.z, max.x, max.y, max.z, center.x, center.y, center.z, radiusSquared);
1157 }
1158 
1159 /**
1160     * Find the point on the given plane which is closest to the specified point <code>(pX, pY, pZ)</code> and store the result in <code>result</code>.
1161     * 
1162     * @param aX
1163     *          the x coordinate of one point on the plane
1164     * @param aY
1165     *          the y coordinate of one point on the plane
1166     * @param aZ
1167     *          the z coordinate of one point on the plane
1168     * @param nX
1169     *          the x coordinate of the unit normal of the plane
1170     * @param nY
1171     *          the y coordinate of the unit normal of the plane
1172     * @param nZ
1173     *          the z coordinate of the unit normal of the plane
1174     * @param pX
1175     *          the x coordinate of the point
1176     * @param pY
1177     *          the y coordinate of the point
1178     * @param pZ
1179     *          the z coordinate of the point
1180     * @param result
1181     *          will hold the result
1182     * @return result
1183     */
1184 public static Vector3d findClosestPointOnPlane(double aX, double aY, double aZ, double nX, double nY, double nZ, double pX, double pY, double pZ, ref Vector3d result) {
1185     double d = -(nX * aX + nY * aY + nZ * aZ);
1186     double t = nX * pX + nY * pY + nZ * pZ - d;
1187     result.x = pX - t * nX;
1188     result.y = pY - t * nY;
1189     result.z = pZ - t * nZ;
1190     return result;
1191 }
1192 
1193 /**
1194     * Find the point on the given line segment which is closest to the specified point <code>(pX, pY, pZ)</code>, and store the result in <code>result</code>.
1195     * 
1196     * @param aX
1197     *          the x coordinate of the first end point of the line segment
1198     * @param aY
1199     *          the y coordinate of the first end point of the line segment
1200     * @param aZ
1201     *          the z coordinate of the first end point of the line segment
1202     * @param bX
1203     *          the x coordinate of the second end point of the line segment
1204     * @param bY
1205     *          the y coordinate of the second end point of the line segment
1206     * @param bZ
1207     *          the z coordinate of the second end point of the line segment
1208     * @param pX
1209     *          the x coordinate of the point
1210     * @param pY
1211     *          the y coordinate of the point
1212     * @param pZ
1213     *          the z coordinate of the point
1214     * @param result
1215     *          will hold the result
1216     * @return result
1217     */
1218 public static Vector3d findClosestPointOnLineSegment(double aX, double aY, double aZ, double bX, double bY, double bZ, double pX, double pY, double pZ, ref Vector3d result) {
1219     double abX = bX - aX, abY = bY - aY, abZ = bZ - aZ;
1220     double t = ((pX - aX) * abX + (pY - aY) * abY + (pZ - aZ) * abZ) / (abX * abX + abY * abY + abZ * abZ);
1221     if (t < 0.0) t = 0.0;
1222     if (t > 1.0) t = 1.0;
1223     result.x = aX + t * abX;
1224     result.y = aY + t * abY;
1225     result.z = aZ + t * abZ;
1226     return result;
1227 }
1228 
1229 /**
1230     * Find the closest points on the two line segments, store the point on the first line segment in <code>resultA</code> and 
1231     * the point on the second line segment in <code>resultB</code>, and return the square distance between both points.
1232     * <p>
1233     * Reference: Book "Real-Time Collision Detection" chapter 5.1.9 "Closest Points of Two Line Segments"
1234     * 
1235     * @param a0X
1236     *          the x coordinate of the first line segment's first end point
1237     * @param a0Y
1238     *          the y coordinate of the first line segment's first end point
1239     * @param a0Z
1240     *          the z coordinate of the first line segment's first end point
1241     * @param a1X
1242     *          the x coordinate of the first line segment's second end point
1243     * @param a1Y
1244     *          the y coordinate of the first line segment's second end point
1245     * @param a1Z
1246     *          the z coordinate of the first line segment's second end point
1247     * @param b0X
1248     *          the x coordinate of the second line segment's first end point
1249     * @param b0Y
1250     *          the y coordinate of the second line segment's first end point
1251     * @param b0Z
1252     *          the z coordinate of the second line segment's first end point
1253     * @param b1X
1254     *          the x coordinate of the second line segment's second end point
1255     * @param b1Y
1256     *          the y coordinate of the second line segment's second end point
1257     * @param b1Z
1258     *          the z coordinate of the second line segment's second end point
1259     * @param resultA
1260     *          will hold the point on the first line segment
1261     * @param resultB
1262     *          will hold the point on the second line segment
1263     * @return the square distance between the two closest points
1264     */
1265 public static double findClosestPointsLineSegments(
1266         double a0X, double a0Y, double a0Z, double a1X, double a1Y, double a1Z,
1267         double b0X, double b0Y, double b0Z, double b1X, double b1Y, double b1Z,
1268         Vector3d resultA, Vector3d resultB) {
1269     double d1x = a1X - a0X, d1y = a1Y - a0Y, d1z = a1Z - a0Z;
1270     double d2x = b1X - b0X, d2y = b1Y - b0Y, d2z = b1Z - b0Z;
1271     double rX = a0X - b0X, rY = a0Y - b0Y, rZ = a0Z - b0Z;
1272     double a = d1x * d1x + d1y * d1y + d1z * d1z;
1273     double e = d2x * d2x + d2y * d2y + d2z * d2z;
1274     double f = d2x * rX + d2y * rY + d2z * rZ;
1275     double EPSILON = 1E-8;
1276     double s, t;
1277     if (a <= EPSILON && e <= EPSILON) {
1278         // Both segments degenerate into points
1279         resultA.set(a0X, a0Y, a0Z);
1280         resultB.set(b0X, b0Y, b0Z);
1281         return resultA.dot(resultB);
1282     }
1283     if (a <= EPSILON) {
1284         // First segment degenerates into a point
1285         s = 0.0;
1286         t = f / e;
1287         t = Math.min(Math.max(t, 0.0), 1.0);
1288     } else {
1289         double c = d1x * rX + d1y * rY + d1z * rZ;
1290         if (e <= EPSILON) {
1291             // Second segment degenerates into a point
1292             t = 0.0;
1293             s = Math.min(Math.max(-c / a, 0.0), 1.0);
1294         } else {
1295             // The general nondegenerate case starts here
1296             double b = d1x * d2x + d1y * d2y + d1z * d2z;
1297             double denom = a * e - b * b;
1298             // If segments not parallel, compute closest point on L1 to L2 and
1299             // clamp to segment S1. Else pick arbitrary s (here 0)
1300             if (denom != 0.0)
1301                 s = Math.min(Math.max((b*f - c*e) / denom, 0.0), 1.0);
1302             else
1303                 s = 0.0;
1304             // Compute point on L2 closest to S1(s) using
1305             // t = Dot((P1 + D1*s) - P2,D2) / Dot(D2,D2) = (b*s + f) / e
1306             t = (b * s + f) / e;
1307             // If t in [0,1] done. Else clamp t, recompute s for the new value
1308             // of t using s = Dot((P2 + D2*t) - P1,D1) / Dot(D1,D1)= (t*b - c) / a
1309             // and clamp s to [0, 1]
1310             if (t < 0.0) {
1311                 t = 0.0;
1312                 s = Math.min(Math.max(-c / a, 0.0), 1.0);
1313             } else if (t > 1.0) {
1314                 t = 1.0;
1315                 s = Math.min(Math.max((b - c) / a, 0.0), 1.0);
1316             }
1317         }
1318     }
1319     resultA.set(a0X + d1x * s, a0Y + d1y * s, a0Z + d1z * s);
1320     resultB.set(b0X + d2x * t, b0Y + d2y * t, b0Z + d2z * t);
1321     double dX = resultA.x - resultB.x, dY = resultA.y - resultB.y, dZ = resultA.z - resultB.z;
1322     return dX*dX + dY*dY + dZ*dZ;
1323 }
1324 
1325 /**
1326     * Find the closest points on a line segment and a triangle.
1327     * <p>
1328     * Reference: Book "Real-Time Collision Detection" chapter 5.1.10 "Closest Points of a Line Segment and a Triangle"
1329     * 
1330     * @param aX
1331     *          the x coordinate of the line segment's first end point
1332     * @param aY
1333     *          the y coordinate of the line segment's first end point
1334     * @param aZ
1335     *          the z coordinate of the line segment's first end point
1336     * @param bX
1337     *          the x coordinate of the line segment's second end point
1338     * @param bY
1339     *          the y coordinate of the line segment's second end point
1340     * @param bZ
1341     *          the z coordinate of the line segment's second end point
1342     * @param v0X
1343     *          the x coordinate of the triangle's first vertex
1344     * @param v0Y
1345     *          the y coordinate of the triangle's first vertex
1346     * @param v0Z
1347     *          the z coordinate of the triangle's first vertex
1348     * @param v1X
1349     *          the x coordinate of the triangle's second vertex
1350     * @param v1Y
1351     *          the y coordinate of the triangle's second vertex
1352     * @param v1Z
1353     *          the z coordinate of the triangle's second vertex
1354     * @param v2X
1355     *          the x coordinate of the triangle's third vertex
1356     * @param v2Y
1357     *          the y coordinate of the triangle's third vertex
1358     * @param v2Z
1359     *          the z coordinate of the triangle's third vertex
1360     * @param lineSegmentResult
1361     *          will hold the closest point on the line segment
1362     * @param triangleResult
1363     *          will hold the closest point on the triangle
1364     * @return the square distance of the closest points
1365     */
1366 public static double findClosestPointsLineSegmentTriangle(
1367         double aX, double aY, double aZ, double bX, double bY, double bZ,
1368         double v0X, double v0Y, double v0Z, double v1X, double v1Y, double v1Z, double v2X, double v2Y, double v2Z,
1369         Vector3d lineSegmentResult, Vector3d triangleResult) {
1370     double min, d;
1371     double minlsX, minlsY, minlsZ, mintX, mintY, mintZ;
1372     // AB -> V0V1
1373     d = findClosestPointsLineSegments(aX, aY, aZ, bX, bY, bZ, v0X, v0Y, v0Z, v1X, v1Y, v1Z, lineSegmentResult, triangleResult);
1374     min = d;
1375     minlsX = lineSegmentResult.x; minlsY = lineSegmentResult.y; minlsZ = lineSegmentResult.z;
1376     mintX = triangleResult.x; mintY = triangleResult.y; mintZ = triangleResult.z;
1377     // AB -> V1V2
1378     d = findClosestPointsLineSegments(aX, aY, aZ, bX, bY, bZ, v1X, v1Y, v1Z, v2X, v2Y, v2Z, lineSegmentResult, triangleResult);
1379     if (d < min) {
1380         min = d;
1381         minlsX = lineSegmentResult.x; minlsY = lineSegmentResult.y; minlsZ = lineSegmentResult.z;
1382         mintX = triangleResult.x; mintY = triangleResult.y; mintZ = triangleResult.z;
1383     }
1384     // AB -> V2V0
1385     d = findClosestPointsLineSegments(aX, aY, aZ, bX, bY, bZ, v2X, v2Y, v2Z, v0X, v0Y, v0Z, lineSegmentResult, triangleResult);
1386     if (d < min) {
1387         min = d;
1388         minlsX = lineSegmentResult.x; minlsY = lineSegmentResult.y; minlsZ = lineSegmentResult.z;
1389         mintX = triangleResult.x; mintY = triangleResult.y; mintZ = triangleResult.z;
1390     }
1391     // segment endpoint A and plane of triangle (when A projects inside V0V1V2)
1392     bool computed = false;
1393     double a = double.nan, b = double.nan, c = double.nan, nd = double.nan;
1394     if (testPointInTriangle(aX, aY, aZ, v0X, v0Y, v0Z, v1X, v1Y, v1Z, v2X, v2Y, v2Z)) {
1395         double v1Y0Y = v1Y - v0Y;
1396         double v2Z0Z = v2Z - v0Z;
1397         double v2Y0Y = v2Y - v0Y;
1398         double v1Z0Z = v1Z - v0Z;
1399         double v2X0X = v2X - v0X;
1400         double v1X0X = v1X - v0X;
1401         a = v1Y0Y * v2Z0Z - v2Y0Y * v1Z0Z;
1402         b = v1Z0Z * v2X0X - v2Z0Z * v1X0X;
1403         c = v1X0X * v2Y0Y - v2X0X * v1Y0Y;
1404         computed = true;
1405         double invLen = Math.invsqrt(a*a + b*b + c*c);
1406         a *= invLen; b *= invLen; c *= invLen;
1407         nd = -(a * v0X + b * v0Y + c * v0Z);
1408         d = (a * aX + b * aY + c * aZ + nd);
1409         double l = d;
1410         d *= d;
1411         if (d < min) {
1412             min = d;
1413             minlsX = aX; minlsY = aY; minlsZ = aZ;
1414             mintX = aX - a*l; mintY = aY - b*l; mintZ = aZ - c*l;
1415         }
1416     }
1417     // segment endpoint B and plane of triangle (when B projects inside V0V1V2)
1418     if (testPointInTriangle(bX, bY, bZ, v0X, v0Y, v0Z, v1X, v1Y, v1Z, v2X, v2Y, v2Z)) {
1419         if (!computed) {
1420             double v1Y0Y = v1Y - v0Y;
1421             double v2Z0Z = v2Z - v0Z;
1422             double v2Y0Y = v2Y - v0Y;
1423             double v1Z0Z = v1Z - v0Z;
1424             double v2X0X = v2X - v0X;
1425             double v1X0X = v1X - v0X;
1426             a = v1Y0Y * v2Z0Z - v2Y0Y * v1Z0Z;
1427             b = v1Z0Z * v2X0X - v2Z0Z * v1X0X;
1428             c = v1X0X * v2Y0Y - v2X0X * v1Y0Y;
1429             double invLen = Math.invsqrt(a*a + b*b + c*c);
1430             a *= invLen; b *= invLen; c *= invLen;
1431             nd = -(a * v0X + b * v0Y + c * v0Z);
1432         }
1433         d = (a * bX + b * bY + c * bZ + nd);
1434         double l = d;
1435         d *= d;
1436         if (d < min) {
1437             min = d;
1438             minlsX = bX; minlsY = bY; minlsZ = bZ;
1439             mintX = bX - a*l; mintY = bY - b*l; mintZ = bZ - c*l;
1440         }
1441     }
1442     lineSegmentResult.set(minlsX, minlsY, minlsZ);
1443     triangleResult.set(mintX, mintY, mintZ);
1444     return min;
1445 }
1446 
1447 /**
1448     * Determine the closest point on the triangle with the given vertices <code>(v0X, v0Y, v0Z)</code>, <code>(v1X, v1Y, v1Z)</code>, <code>(v2X, v2Y, v2Z)</code>
1449     * between that triangle and the given point <code>(pX, pY, pZ)</code> and store that point into the given <code>result</code>.
1450     * <p>
1451     * Additionally, this method returns whether the closest point is a vertex ({@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1}, {@link #POINT_ON_TRIANGLE_VERTEX_2})
1452     * of the triangle, lies on an edge ({@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12}, {@link #POINT_ON_TRIANGLE_EDGE_20})
1453     * or on the {@link #POINT_ON_TRIANGLE_FACE face} of the triangle.
1454     * <p>
1455     * Reference: Book "Real-Time Collision Detection" chapter 5.1.5 "Closest Point on Triangle to Point"
1456     * 
1457     * @param v0X
1458     *          the x coordinate of the first vertex of the triangle
1459     * @param v0Y
1460     *          the y coordinate of the first vertex of the triangle
1461     * @param v0Z
1462     *          the z coordinate of the first vertex of the triangle
1463     * @param v1X
1464     *          the x coordinate of the second vertex of the triangle
1465     * @param v1Y
1466     *          the y coordinate of the second vertex of the triangle
1467     * @param v1Z
1468     *          the z coordinate of the second vertex of the triangle
1469     * @param v2X
1470     *          the x coordinate of the third vertex of the triangle
1471     * @param v2Y
1472     *          the y coordinate of the third vertex of the triangle
1473     * @param v2Z
1474     *          the z coordinate of the third vertex of the triangle
1475     * @param pX
1476     *          the x coordinate of the point
1477     * @param pY
1478     *          the y coordinate of the point
1479     * @param pZ
1480     *          the y coordinate of the point
1481     * @param result
1482     *          will hold the closest point
1483     * @return one of {@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1}, {@link #POINT_ON_TRIANGLE_VERTEX_2},
1484     *                {@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12}, {@link #POINT_ON_TRIANGLE_EDGE_20} or
1485     *                {@link #POINT_ON_TRIANGLE_FACE}
1486     */
1487 public static int findClosestPointOnTriangle(
1488         double v0X, double v0Y, double v0Z,
1489         double v1X, double v1Y, double v1Z,
1490         double v2X, double v2Y, double v2Z,
1491         double pX, double pY, double pZ,
1492         Vector3d result) {
1493     double abX = v1X - v0X, abY = v1Y - v0Y, abZ = v1Z - v0Z;
1494     double acX = v2X - v0X, acY = v2Y - v0Y, acZ = v2Z - v0Z;
1495     double apX = pX - v0X, apY = pY - v0Y, apZ = pZ - v0Z;
1496     double d1 = abX * apX + abY * apY + abZ * apZ;
1497     double d2 = acX * apX + acY * apY + acZ * apZ;
1498     if (d1 <= 0.0 && d2 <= 0.0) {
1499         result.x = v0X;
1500         result.y = v0Y;
1501         result.z = v0Z;
1502         return POINT_ON_TRIANGLE_VERTEX_0;
1503     }
1504     double bpX = pX - v1X, bpY = pY - v1Y, bpZ = pZ - v1Z;
1505     double d3 = abX * bpX + abY * bpY + abZ * bpZ;
1506     double d4 = acX * bpX + acY * bpY + acZ * bpZ;
1507     if (d3 >= 0.0 && d4 <= d3) {
1508         result.x = v1X;
1509         result.y = v1Y;
1510         result.z = v1Z;
1511         return POINT_ON_TRIANGLE_VERTEX_1;
1512     }
1513     double vc = d1 * d4 - d3 * d2;
1514     if (vc <= 0.0 && d1 >= 0.0 && d3 <= 0.0) {
1515         double v = d1 / (d1 - d3);
1516         result.x = v0X + v * abX;
1517         result.y = v0Y + v * abY;
1518         result.z = v0Z + v * abZ;
1519         return POINT_ON_TRIANGLE_EDGE_01;
1520     }
1521     double cpX = pX - v2X, cpY = pY - v2Y, cpZ = pZ - v2Z;
1522     double d5 = abX * cpX + abY * cpY + abZ * cpZ;
1523     double d6 = acX * cpX + acY * cpY + acZ * cpZ;
1524     if (d6 >= 0.0 && d5 <= d6) {
1525         result.x = v2X;
1526         result.y = v2Y;
1527         result.z = v2Z;
1528         return POINT_ON_TRIANGLE_VERTEX_2;
1529     }
1530     double vb = d5 * d2 - d1 * d6;
1531     if (vb <= 0.0 && d2 >= 0.0 && d6 <= 0.0) {
1532         double w = d2 / (d2 - d6);
1533         result.x = v0X + w * acX;
1534         result.y = v0Y + w * acY;
1535         result.z = v0Z + w * acZ;
1536         return POINT_ON_TRIANGLE_EDGE_20;
1537     }
1538     double va = d3 * d6 - d5 * d4;
1539     if (va <= 0.0 && d4 - d3 >= 0.0 && d5 - d6 >= 0.0) {
1540         double w = (d4 - d3) / (d4 - d3 + d5 - d6);
1541         result.x = v1X + w * (v2X - v1X);
1542         result.y = v1Y + w * (v2Y - v1Y);
1543         result.z = v1Z + w * (v2Z - v1Z);
1544         return POINT_ON_TRIANGLE_EDGE_12;
1545     }
1546     double denom = 1.0 / (va + vb + vc);
1547     double v = vb * denom;
1548     double w = vc * denom;
1549     result.x = v0X + abX * v + acX * w;
1550     result.y = v0Y + abY * v + acY * w;
1551     result.z = v0Z + abZ * v + acZ * w;
1552     return POINT_ON_TRIANGLE_FACE;
1553 }
1554 
1555 /**
1556     * Determine the closest point on the triangle with the vertices <code>v0</code>, <code>v1</code>, <code>v2</code>
1557     * between that triangle and the given point <code>p</code> and store that point into the given <code>result</code>.
1558     * <p>
1559     * Additionally, this method returns whether the closest point is a vertex ({@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1}, {@link #POINT_ON_TRIANGLE_VERTEX_2})
1560     * of the triangle, lies on an edge ({@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12}, {@link #POINT_ON_TRIANGLE_EDGE_20})
1561     * or on the {@link #POINT_ON_TRIANGLE_FACE face} of the triangle.
1562     * <p>
1563     * Reference: Book "Real-Time Collision Detection" chapter 5.1.5 "Closest Point on Triangle to Point"
1564     * 
1565     * @param v0
1566     *          the first vertex of the triangle
1567     * @param v1
1568     *          the second vertex of the triangle
1569     * @param v2
1570     *          the third vertex of the triangle
1571     * @param p
1572     *          the point
1573     * @param result
1574     *          will hold the closest point
1575     * @return one of {@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1}, {@link #POINT_ON_TRIANGLE_VERTEX_2},
1576     *                {@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12}, {@link #POINT_ON_TRIANGLE_EDGE_20} or
1577     *                {@link #POINT_ON_TRIANGLE_FACE}
1578     */
1579 public static int findClosestPointOnTriangle(Vector3d v0, Vector3d v1, Vector3d v2, Vector3d p, Vector3d result) {
1580     return findClosestPointOnTriangle(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p.x, p.y, p.z, result);
1581 }
1582 
1583 /**
1584     * Find the point on a given rectangle, specified via three of its corners, which is closest to the specified point
1585     * <code>(pX, pY, pZ)</code> and store the result into <code>res</code>.
1586     * <p>
1587     * Reference: Book "Real-Time Collision Detection" chapter 5.1.4.2 "Closest Point on 3D Rectangle to Point"
1588     * 
1589     * @param aX
1590     *          the x coordinate of the first corner point of the rectangle
1591     * @param aY
1592     *          the y coordinate of the first corner point of the rectangle
1593     * @param aZ
1594     *          the z coordinate of the first corner point of the rectangle
1595     * @param bX
1596     *          the x coordinate of the second corner point of the rectangle 
1597     * @param bY
1598     *          the y coordinate of the second corner point of the rectangle
1599     * @param bZ
1600     *          the z coordinate of the second corner point of the rectangle
1601     * @param cX
1602     *          the x coordinate of the third corner point of the rectangle
1603     * @param cY
1604     *          the y coordinate of the third corner point of the rectangle
1605     * @param cZ
1606     *          the z coordinate of the third corner point of the rectangle
1607     * @param pX
1608     *          the x coordinate of the point
1609     * @param pY
1610     *          the y coordinate of the point
1611     * @param pZ
1612     *          the z coordinate of the point
1613     * @param res
1614     *          will hold the result
1615     * @return res
1616     */
1617 public static Vector3d findClosestPointOnRectangle(
1618         double aX, double aY, double aZ,
1619         double bX, double bY, double bZ,
1620         double cX, double cY, double cZ,
1621         double pX, double pY, double pZ, ref Vector3d res) {
1622     double abX = bX - aX, abY = bY - aY, abZ = bZ - aZ;
1623     double acX = cX - aX, acY = cY - aY, acZ = cZ - aZ;
1624     double dX = pX - aX, dY = pY - aY, dZ = pZ - aZ;
1625     double qX = aX, qY = aY, qZ = aZ;
1626     double dist = dX * abX + dY * abY + dZ * abZ;
1627     double maxdist = abX * abX + abY * abY + abZ * abZ;
1628     if (dist >= maxdist) {
1629         qX += abX;
1630         qY += abY;
1631         qZ += abZ;
1632     } else if (dist > 0.0) {
1633         qX += (dist / maxdist) * abX;
1634         qY += (dist / maxdist) * abY;
1635         qZ += (dist / maxdist) * abZ;
1636     }
1637     dist = dX * acX + dY * acY + dZ * acZ;
1638     maxdist = acX * acX + acY * acY + acZ * acZ;
1639     if (dist >= maxdist) {
1640         qX += acX;
1641         qY += acY;
1642         qZ += acZ;
1643     } else if (dist > 0.0) {
1644         qX += (dist / maxdist) * acX;
1645         qY += (dist / maxdist) * acY;
1646         qZ += (dist / maxdist) * acZ;
1647     }
1648     res.x = qX;
1649     res.y = qY;
1650     res.z = qZ;
1651     return res;
1652 }
1653 
1654 /**
1655     * Determine the point of intersection between a sphere with the given center <code>(centerX, centerY, centerZ)</code> and <code>radius</code> moving
1656     * with the given velocity <code>(velX, velY, velZ)</code> and the triangle specified via its three vertices <code>(v0X, v0Y, v0Z)</code>, <code>(v1X, v1Y, v1Z)</code>, <code>(v2X, v2Y, v2Z)</code>.
1657     * <p>
1658     * The vertices of the triangle must be specified in counter-clockwise winding order.
1659     * <p>
1660     * An intersection is only considered if the time of intersection is smaller than the given <code>maxT</code> value.
1661     * <p>
1662     * Reference: <a href="http://www.peroxide.dk/papers/collision/collision.pdf">Improved Collision detection and Response</a>
1663     * 
1664     * @param centerX
1665     *              the x coordinate of the sphere's center
1666     * @param centerY
1667     *              the y coordinate of the sphere's center
1668     * @param centerZ
1669     *              the z coordinate of the sphere's center
1670     * @param radius
1671     *              the radius of the sphere
1672     * @param velX
1673     *              the x component of the velocity of the sphere
1674     * @param velY
1675     *              the y component of the velocity of the sphere
1676     * @param velZ
1677     *              the z component of the velocity of the sphere
1678     * @param v0X
1679     *              the x coordinate of the first triangle vertex
1680     * @param v0Y
1681     *              the y coordinate of the first triangle vertex
1682     * @param v0Z
1683     *              the z coordinate of the first triangle vertex
1684     * @param v1X
1685     *              the x coordinate of the second triangle vertex
1686     * @param v1Y
1687     *              the y coordinate of the second triangle vertex
1688     * @param v1Z
1689     *              the z coordinate of the second triangle vertex
1690     * @param v2X
1691     *              the x coordinate of the third triangle vertex
1692     * @param v2Y
1693     *              the y coordinate of the third triangle vertex
1694     * @param v2Z
1695     *              the z coordinate of the third triangle vertex
1696     * @param epsilon
1697     *              a small epsilon when testing spheres that move almost parallel to the triangle
1698     * @param maxT
1699     *              the maximum intersection time
1700     * @param pointAndTime
1701     *              iff the moving sphere and the triangle intersect, this will hold the point of intersection in the <code>(x, y, z)</code> components
1702     *              and the time of intersection in the <code>w</code> component
1703     * @return {@link #POINT_ON_TRIANGLE_FACE} if the intersection point lies on the triangle's face,
1704     *         or {@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1} or {@link #POINT_ON_TRIANGLE_VERTEX_2} if the intersection point is a vertex,
1705     *         or {@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12} or {@link #POINT_ON_TRIANGLE_EDGE_20} if the intersection point lies on an edge;
1706     *         or <code>0</code> if no intersection
1707     */
1708 public static int intersectSweptSphereTriangle(
1709         double centerX, double centerY, double centerZ, double radius, double velX, double velY, double velZ,
1710         double v0X, double v0Y, double v0Z, double v1X, double v1Y, double v1Z, double v2X, double v2Y, double v2Z,
1711         double epsilon, double maxT, Vector4d pointAndTime) {
1712     double v10X = v1X - v0X;
1713     double v10Y = v1Y - v0Y;
1714     double v10Z = v1Z - v0Z;
1715     double v20X = v2X - v0X;
1716     double v20Y = v2Y - v0Y;
1717     double v20Z = v2Z - v0Z;
1718     // build triangle plane
1719     double a = v10Y * v20Z - v20Y * v10Z;
1720     double b = v10Z * v20X - v20Z * v10X;
1721     double c = v10X * v20Y - v20X * v10Y;
1722     double d = -(a * v0X + b * v0Y + c * v0Z);
1723     double invLen = Math.invsqrt(a * a + b * b + c * c);
1724     double signedDist = (a * centerX + b * centerY + c * centerZ + d) * invLen;
1725     double dot = (a * velX + b * velY + c * velZ) * invLen;
1726     if (dot < epsilon && dot > -epsilon)
1727         return 0;
1728     double pt0 = (radius - signedDist) / dot;
1729     if (pt0 > maxT)
1730         return 0;
1731     double pt1 = (-radius - signedDist) / dot;
1732     double p0X = centerX - radius * a * invLen + velX * pt0;
1733     double p0Y = centerY - radius * b * invLen + velY * pt0;
1734     double p0Z = centerZ - radius * c * invLen + velZ * pt0;
1735     bool insideTriangle = testPointInTriangle(p0X, p0Y, p0Z, v0X, v0Y, v0Z, v1X, v1Y, v1Z, v2X, v2Y, v2Z);
1736     if (insideTriangle) {
1737         pointAndTime.x = p0X;
1738         pointAndTime.y = p0Y;
1739         pointAndTime.z = p0Z;
1740         pointAndTime.w = pt0;
1741         return POINT_ON_TRIANGLE_FACE;
1742     }
1743     int isect = 0;
1744     double t0 = maxT;
1745     double A = velX * velX + velY * velY + velZ * velZ;
1746     double radius2 = radius * radius;
1747     // test against v0
1748     double centerV0X = centerX - v0X;
1749     double centerV0Y = centerY - v0Y;
1750     double centerV0Z = centerZ - v0Z;
1751     double B0 = 2.0 * (velX * centerV0X + velY * centerV0Y + velZ * centerV0Z);
1752     double C0 = centerV0X * centerV0X + centerV0Y * centerV0Y + centerV0Z * centerV0Z - radius2;
1753     double root0 = computeLowestRoot(A, B0, C0, t0);
1754     if (root0 < t0) {
1755         pointAndTime.x = v0X;
1756         pointAndTime.y = v0Y;
1757         pointAndTime.z = v0Z;
1758         pointAndTime.w = root0;
1759         t0 = root0;
1760         isect = POINT_ON_TRIANGLE_VERTEX_0;
1761     }
1762     // test against v1
1763     double centerV1X = centerX - v1X;
1764     double centerV1Y = centerY - v1Y;
1765     double centerV1Z = centerZ - v1Z;
1766     double centerV1Len = centerV1X * centerV1X + centerV1Y * centerV1Y + centerV1Z * centerV1Z;
1767     double B1 = 2.0 * (velX * centerV1X + velY * centerV1Y + velZ * centerV1Z);
1768     double C1 = centerV1Len - radius2;
1769     double root1 = computeLowestRoot(A, B1, C1, t0);
1770     if (root1 < t0) {
1771         pointAndTime.x = v1X;
1772         pointAndTime.y = v1Y;
1773         pointAndTime.z = v1Z;
1774         pointAndTime.w = root1;
1775         t0 = root1;
1776         isect = POINT_ON_TRIANGLE_VERTEX_1;
1777     }
1778     // test against v2
1779     double centerV2X = centerX - v2X;
1780     double centerV2Y = centerY - v2Y;
1781     double centerV2Z = centerZ - v2Z;
1782     double B2 = 2.0 * (velX * centerV2X + velY * centerV2Y + velZ * centerV2Z);
1783     double C2 = centerV2X * centerV2X + centerV2Y * centerV2Y + centerV2Z * centerV2Z - radius2;
1784     double root2 = computeLowestRoot(A, B2, C2, t0);
1785     if (root2 < t0) {
1786         pointAndTime.x = v2X;
1787         pointAndTime.y = v2Y;
1788         pointAndTime.z = v2Z;
1789         pointAndTime.w = root2;
1790         t0 = root2;
1791         isect = POINT_ON_TRIANGLE_VERTEX_2;
1792     }
1793     double velLen = velX * velX + velY * velY + velZ * velZ;
1794     // test against edge10
1795     double len10 = v10X * v10X + v10Y * v10Y + v10Z * v10Z;
1796     double baseTo0Len = centerV0X * centerV0X + centerV0Y * centerV0Y + centerV0Z * centerV0Z;
1797     double v10Vel = (v10X * velX + v10Y * velY + v10Z * velZ);
1798     double A10 = len10 * -velLen + v10Vel * v10Vel;
1799     double v10BaseTo0 = v10X * -centerV0X + v10Y * -centerV0Y + v10Z * -centerV0Z;
1800     double velBaseTo0 = velX * -centerV0X + velY * -centerV0Y + velZ * -centerV0Z;
1801     double B10 = len10 * 2 * velBaseTo0 - 2 * v10Vel * v10BaseTo0;
1802     double C10 = len10 * (radius2 - baseTo0Len) + v10BaseTo0 * v10BaseTo0;
1803     double root10 = computeLowestRoot(A10, B10, C10, t0);
1804     double f10 = (v10Vel * root10 - v10BaseTo0) / len10;
1805     if (f10 >= 0.0 && f10 <= 1.0 && root10 < t0) {
1806         pointAndTime.x = v0X + f10 * v10X;
1807         pointAndTime.y = v0Y + f10 * v10Y;
1808         pointAndTime.z = v0Z + f10 * v10Z;
1809         pointAndTime.w = root10;
1810         t0 = root10;
1811         isect = POINT_ON_TRIANGLE_EDGE_01;
1812     }
1813     // test against edge20
1814     double len20 = v20X * v20X + v20Y * v20Y + v20Z * v20Z;
1815     double v20Vel = (v20X * velX + v20Y * velY + v20Z * velZ);
1816     double A20 = len20 * -velLen + v20Vel * v20Vel;
1817     double v20BaseTo0 = v20X * -centerV0X + v20Y * -centerV0Y + v20Z * -centerV0Z;
1818     double B20 = len20 * 2 * velBaseTo0 - 2 * v20Vel * v20BaseTo0;
1819     double C20 = len20 * (radius2 - baseTo0Len) + v20BaseTo0 * v20BaseTo0;
1820     double root20 = computeLowestRoot(A20, B20, C20, t0);
1821     double f20 = (v20Vel * root20 - v20BaseTo0) / len20;
1822     if (f20 >= 0.0 && f20 <= 1.0 && root20 < pt1) {
1823         pointAndTime.x = v0X + f20 * v20X;
1824         pointAndTime.y = v0Y + f20 * v20Y;
1825         pointAndTime.z = v0Z + f20 * v20Z;
1826         pointAndTime.w = root20;
1827         t0 = root20;
1828         isect = POINT_ON_TRIANGLE_EDGE_20;
1829     }
1830     // test against edge21
1831     double v21X = v2X - v1X;
1832     double v21Y = v2Y - v1Y;
1833     double v21Z = v2Z - v1Z;
1834     double len21 = v21X * v21X + v21Y * v21Y + v21Z * v21Z;
1835     double baseTo1Len = centerV1Len;
1836     double v21Vel = (v21X * velX + v21Y * velY + v21Z * velZ);
1837     double A21 = len21 * -velLen + v21Vel * v21Vel;
1838     double v21BaseTo1 = v21X * -centerV1X + v21Y * -centerV1Y + v21Z * -centerV1Z;
1839     double velBaseTo1 = velX * -centerV1X + velY * -centerV1Y + velZ * -centerV1Z;
1840     double B21 = len21 * 2 * velBaseTo1 - 2 * v21Vel * v21BaseTo1;
1841     double C21 = len21 * (radius2 - baseTo1Len) + v21BaseTo1 * v21BaseTo1;
1842     double root21 = computeLowestRoot(A21, B21, C21, t0);
1843     double f21 = (v21Vel * root21 - v21BaseTo1) / len21;
1844     if (f21 >= 0.0 && f21 <= 1.0 && root21 < t0) {
1845         pointAndTime.x = v1X + f21 * v21X;
1846         pointAndTime.y = v1Y + f21 * v21Y;
1847         pointAndTime.z = v1Z + f21 * v21Z;
1848         pointAndTime.w = root21;
1849         t0 = root21;
1850         isect = POINT_ON_TRIANGLE_EDGE_12;
1851     }
1852     return isect;
1853 }
1854 
1855 /**
1856     * Compute the lowest root for <code>t</code> in the quadratic equation <code>a*t*t + b*t + c = 0</code>.
1857     * <p>
1858     * This is a helper method for {@link #intersectSweptSphereTriangle}
1859     * 
1860     * @param a
1861     *              the quadratic factor
1862     * @param b
1863     *              the linear factor
1864     * @param c
1865     *              the constant
1866     * @param maxR
1867     *              the maximum expected root
1868     * @return the lowest of the two roots of the quadratic equation; or {@link Double#POSITIVE_INFINITY}
1869     */
1870 private static double computeLowestRoot(double a, double b, double c, double maxR) {
1871     double determinant = b * b - 4.0 * a * c;
1872     if (determinant < 0.0)
1873         return double.infinity;
1874     double sqrtD = Math.sqrt(determinant);
1875     double r1 = (-b - sqrtD) / (2.0 * a);
1876     double r2 = (-b + sqrtD) / (2.0 * a);
1877     if (r1 > r2) {
1878         double temp = r2;
1879         r2 = r1;
1880         r1 = temp;
1881     }
1882     if (r1 > 0.0 && r1 < maxR) {
1883         return r1;
1884     }
1885     if (r2 > 0.0 && r2 < maxR) {
1886         return r2;
1887     }
1888     return double.infinity;
1889 }
1890 
1891 /**
1892     * Test whether the projection of the given point <code>(pX, pY, pZ)</code> lies inside of the triangle defined by the three vertices
1893     * <code>(v0X, v0Y, v0Z)</code>, <code>(v1X, v1Y, v1Z)</code> and <code>(v2X, v2Y, v2Z)</code>.
1894     * <p>
1895     * Reference: <a href="http://www.peroxide.dk/papers/collision/collision.pdf">Improved Collision detection and Response</a>
1896     * 
1897     * @param pX
1898     *              the x coordinate of the point to test
1899     * @param pY
1900     *              the y coordinate of the point to test
1901     * @param pZ
1902     *              the z coordinate of the point to test
1903     * @param v0X
1904     *              the x coordinate of the first vertex
1905     * @param v0Y
1906     *              the y coordinate of the first vertex
1907     * @param v0Z
1908     *              the z coordinate of the first vertex
1909     * @param v1X
1910     *              the x coordinate of the second vertex
1911     * @param v1Y
1912     *              the y coordinate of the second vertex
1913     * @param v1Z
1914     *              the z coordinate of the second vertex
1915     * @param v2X
1916     *              the x coordinate of the third vertex
1917     * @param v2Y
1918     *              the y coordinate of the third vertex
1919     * @param v2Z
1920     *              the z coordinate of the third vertex
1921     * @return <code>true</code> if the projection of the given point lies inside of the given triangle; <code>false</code> otherwise
1922     */
1923 public static bool testPointInTriangle(double pX, double pY, double pZ, double v0X, double v0Y, double v0Z, double v1X, double v1Y, double v1Z, double v2X, double v2Y, double v2Z) {
1924     double e10X = v1X - v0X;
1925     double e10Y = v1Y - v0Y;
1926     double e10Z = v1Z - v0Z;
1927     double e20X = v2X - v0X;
1928     double e20Y = v2Y - v0Y;
1929     double e20Z = v2Z - v0Z;
1930     double a = e10X * e10X + e10Y * e10Y + e10Z * e10Z;
1931     double b = e10X * e20X + e10Y * e20Y + e10Z * e20Z;
1932     double c = e20X * e20X + e20Y * e20Y + e20Z * e20Z;
1933     double ac_bb = a * c - b * b;
1934     double vpX = pX - v0X;
1935     double vpY = pY - v0Y;
1936     double vpZ = pZ - v0Z;
1937     double d = vpX * e10X + vpY * e10Y + vpZ * e10Z;
1938     double e = vpX * e20X + vpY * e20Y + vpZ * e20Z;
1939     double x = d * c - e * b;
1940     double y = e * a - d * b;
1941     double z = x + y - ac_bb;
1942     return ((Math.doubleToLongBits(z) & ~(Math.doubleToLongBits(x) | Math.doubleToLongBits(y))) & 0x8000000000000000L) != 0L;
1943 }
1944 
1945 /**
1946     * Test whether the given ray with the origin <code>(originX, originY, originZ)</code> and normalized direction <code>(dirX, dirY, dirZ)</code>
1947     * intersects the given sphere with center <code>(centerX, centerY, centerZ)</code> and square radius <code>radiusSquared</code>,
1948     * and store the values of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> for both points (near
1949     * and far) of intersections into the given <code>result</code> vector.
1950     * <p>
1951     * This method returns <code>true</code> for a ray whose origin lies inside the sphere.
1952     * <p>
1953     * Reference: <a href="http://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection">http://www.scratchapixel.com/</a>
1954     * 
1955     * @param originX
1956     *              the x coordinate of the ray's origin
1957     * @param originY
1958     *              the y coordinate of the ray's origin
1959     * @param originZ
1960     *              the z coordinate of the ray's origin
1961     * @param dirX
1962     *              the x coordinate of the ray's normalized direction
1963     * @param dirY
1964     *              the y coordinate of the ray's normalized direction
1965     * @param dirZ
1966     *              the z coordinate of the ray's normalized direction
1967     * @param centerX
1968     *              the x coordinate of the sphere's center
1969     * @param centerY
1970     *              the y coordinate of the sphere's center
1971     * @param centerZ
1972     *              the z coordinate of the sphere's center
1973     * @param radiusSquared
1974     *              the sphere radius squared
1975     * @param result
1976     *              a vector that will contain the values of the parameter <i>t</i> in the ray equation
1977     *              <i>p(t) = origin + t * dir</i> for both points (near, far) of intersections with the sphere
1978     * @return <code>true</code> if the ray intersects the sphere; <code>false</code> otherwise
1979     */
1980 public static bool intersectRaySphere(double originX, double originY, double originZ, double dirX, double dirY, double dirZ,
1981         double centerX, double centerY, double centerZ, double radiusSquared, Vector2d result) {
1982     double Lx = centerX - originX;
1983     double Ly = centerY - originY;
1984     double Lz = centerZ - originZ;
1985     double tca = Lx * dirX + Ly * dirY + Lz * dirZ;
1986     double d2 = Lx * Lx + Ly * Ly + Lz * Lz - tca * tca;
1987     if (d2 > radiusSquared)
1988         return false;
1989     double thc = Math.sqrt(radiusSquared - d2);
1990     double t0 = tca - thc;
1991     double t1 = tca + thc;
1992     if (t0 < t1 && t1 >= 0.0) {
1993         result.x = t0;
1994         result.y = t1;
1995         return true;
1996     }
1997     return false;
1998 }
1999 
2000 /**
2001     * Test whether the ray with the given <code>origin</code> and normalized direction <code>dir</code>
2002     * intersects the sphere with the given <code>center</code> and square radius <code>radiusSquared</code>,
2003     * and store the values of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> for both points (near
2004     * and far) of intersections into the given <code>result</code> vector.
2005     * <p>
2006     * This method returns <code>true</code> for a ray whose origin lies inside the sphere.
2007     * <p>
2008     * Reference: <a href="http://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection">http://www.scratchapixel.com/</a>
2009     * 
2010     * @param origin
2011     *              the ray's origin
2012     * @param dir
2013     *              the ray's normalized direction
2014     * @param center
2015     *              the sphere's center
2016     * @param radiusSquared
2017     *              the sphere radius squared
2018     * @param result
2019     *              a vector that will contain the values of the parameter <i>t</i> in the ray equation
2020     *              <i>p(t) = origin + t * dir</i> for both points (near, far) of intersections with the sphere
2021     * @return <code>true</code> if the ray intersects the sphere; <code>false</code> otherwise
2022     */
2023 public static bool intersectRaySphere(Vector3d origin, Vector3d dir, Vector3d center, double radiusSquared, Vector2d result) {
2024     return intersectRaySphere(origin.x, origin.y, origin.z, dir.x, dir.y, dir.z, center.x, center.y, center.z, radiusSquared, result);
2025 }
2026 
2027 /**
2028     * Test whether the given ray with the origin <code>(originX, originY, originZ)</code> and normalized direction <code>(dirX, dirY, dirZ)</code>
2029     * intersects the given sphere with center <code>(centerX, centerY, centerZ)</code> and square radius <code>radiusSquared</code>.
2030     * <p>
2031     * This method returns <code>true</code> for a ray whose origin lies inside the sphere.
2032     * <p>
2033     * Reference: <a href="http://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection">http://www.scratchapixel.com/</a>
2034     * 
2035     * @param originX
2036     *              the x coordinate of the ray's origin
2037     * @param originY
2038     *              the y coordinate of the ray's origin
2039     * @param originZ
2040     *              the z coordinate of the ray's origin
2041     * @param dirX
2042     *              the x coordinate of the ray's normalized direction
2043     * @param dirY
2044     *              the y coordinate of the ray's normalized direction
2045     * @param dirZ
2046     *              the z coordinate of the ray's normalized direction
2047     * @param centerX
2048     *              the x coordinate of the sphere's center
2049     * @param centerY
2050     *              the y coordinate of the sphere's center
2051     * @param centerZ
2052     *              the z coordinate of the sphere's center
2053     * @param radiusSquared
2054     *              the sphere radius squared
2055     * @return <code>true</code> if the ray intersects the sphere; <code>false</code> otherwise
2056     */
2057 public static bool testRaySphere(double originX, double originY, double originZ, double dirX, double dirY, double dirZ,
2058         double centerX, double centerY, double centerZ, double radiusSquared) {
2059     double Lx = centerX - originX;
2060     double Ly = centerY - originY;
2061     double Lz = centerZ - originZ;
2062     double tca = Lx * dirX + Ly * dirY + Lz * dirZ;
2063     double d2 = Lx * Lx + Ly * Ly + Lz * Lz - tca * tca;
2064     if (d2 > radiusSquared)
2065         return false;
2066     double thc = Math.sqrt(radiusSquared - d2);
2067     double t0 = tca - thc;
2068     double t1 = tca + thc;
2069     return t0 < t1 && t1 >= 0.0;
2070 }
2071 
2072 /**
2073     * Test whether the ray with the given <code>origin</code> and normalized direction <code>dir</code>
2074     * intersects the sphere with the given <code>center</code> and square radius.
2075     * <p>
2076     * This method returns <code>true</code> for a ray whose origin lies inside the sphere.
2077     * <p>
2078     * Reference: <a href="http://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection">http://www.scratchapixel.com/</a>
2079     * 
2080     * @param origin
2081     *              the ray's origin
2082     * @param dir
2083     *              the ray's normalized direction
2084     * @param center
2085     *              the sphere's center
2086     * @param radiusSquared
2087     *              the sphere radius squared
2088     * @return <code>true</code> if the ray intersects the sphere; <code>false</code> otherwise
2089     */
2090 public static bool testRaySphere(Vector3d origin, Vector3d dir, Vector3d center, double radiusSquared) {
2091     return testRaySphere(origin.x, origin.y, origin.z, dir.x, dir.y, dir.z, center.x, center.y, center.z, radiusSquared);
2092 }
2093 
2094 /**
2095     * Test whether the line segment with the end points <code>(p0X, p0Y, p0Z)</code> and <code>(p1X, p1Y, p1Z)</code>
2096     * intersects the given sphere with center <code>(centerX, centerY, centerZ)</code> and square radius <code>radiusSquared</code>.
2097     * <p>
2098     * Reference: <a href="http://paulbourke.net/geometry/circlesphere/index.html#linesphere">http://paulbourke.net/</a>
2099     * 
2100     * @param p0X
2101     *              the x coordinate of the line segment's first end point
2102     * @param p0Y
2103     *              the y coordinate of the line segment's first end point
2104     * @param p0Z
2105     *              the z coordinate of the line segment's first end point
2106     * @param p1X
2107     *              the x coordinate of the line segment's second end point
2108     * @param p1Y
2109     *              the y coordinate of the line segment's second end point
2110     * @param p1Z
2111     *              the z coordinate of the line segment's second end point
2112     * @param centerX
2113     *              the x coordinate of the sphere's center
2114     * @param centerY
2115     *              the y coordinate of the sphere's center
2116     * @param centerZ
2117     *              the z coordinate of the sphere's center
2118     * @param radiusSquared
2119     *              the sphere radius squared
2120     * @return <code>true</code> if the line segment intersects the sphere; <code>false</code> otherwise
2121     */
2122 public static bool testLineSegmentSphere(double p0X, double p0Y, double p0Z, double p1X, double p1Y, double p1Z,
2123         double centerX, double centerY, double centerZ, double radiusSquared) {
2124     double dX = p1X - p0X;
2125     double dY = p1Y - p0Y;
2126     double dZ = p1Z - p0Z;
2127     double nom = (centerX - p0X) * dX + (centerY - p0Y) * dY + (centerZ - p0Z) * dZ;
2128     double den = dX * dX + dY * dY + dZ * dZ;
2129     double u = nom / den;
2130     if (u < 0.0) {
2131         dX = p0X - centerX;
2132         dY = p0Y - centerY;
2133         dZ = p0Z - centerZ;
2134     } else if (u > 1.0) {
2135         dX = p1X - centerX;
2136         dY = p1Y - centerY;
2137         dZ = p1Z - centerZ;
2138     } else { // has to be >= 0 and <= 1
2139         double pX = p0X + u * dX;
2140         double pY = p0Y + u * dY;
2141         double pZ = p0Z + u * dZ;
2142         dX = pX - centerX;
2143         dY = pY - centerY;
2144         dZ = pZ - centerZ;
2145     }
2146     double dist = dX * dX + dY * dY + dZ * dZ;
2147     return dist <= radiusSquared;
2148 }
2149 
2150 /**
2151     * Test whether the line segment with the end points <code>p0</code> and <code>p1</code>
2152     * intersects the given sphere with center <code>center</code> and square radius <code>radiusSquared</code>.
2153     * <p>
2154     * Reference: <a href="http://paulbourke.net/geometry/circlesphere/index.html#linesphere">http://paulbourke.net/</a>
2155     * 
2156     * @param p0
2157     *              the line segment's first end point
2158     * @param p1
2159     *              the line segment's second end point
2160     * @param center
2161     *              the sphere's center
2162     * @param radiusSquared
2163     *              the sphere radius squared
2164     * @return <code>true</code> if the line segment intersects the sphere; <code>false</code> otherwise
2165     */
2166 public static bool testLineSegmentSphere(Vector3d p0, Vector3d p1, Vector3d center, double radiusSquared) {
2167     return testLineSegmentSphere(p0.x, p0.y, p0.z, p1.x, p1.y, p1.z, center.x, center.y, center.z, radiusSquared);
2168 }
2169 
2170 /**
2171     * Test whether the given ray with the origin <code>(originX, originY, originZ)</code> and direction <code>(dirX, dirY, dirZ)</code>
2172     * intersects the axis-aligned box given as its minimum corner <code>(minX, minY, minZ)</code> and maximum corner <code>(maxX, maxY, maxZ)</code>,
2173     * and return the values of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> of the near and far point of intersection.
2174     * <p>
2175     * This method returns <code>true</code> for a ray whose origin lies inside the axis-aligned box.
2176     * <p>
2177     * If many boxes need to be tested against the same ray, then the {@link RayAabIntersection} class is likely more efficient.
2178     * <p>
2179     * Reference: <a href="https://dl.acm.org/citation.cfm?id=1198748">An Efficient and Robust Ray–Box Intersection</a>
2180     * 
2181     * @see #intersectRayAab(Vector3d, Vector3d, Vector3d, Vector3d, Vector2d)
2182     * @see RayAabIntersection
2183     * 
2184     * @param originX
2185     *              the x coordinate of the ray's origin
2186     * @param originY
2187     *              the y coordinate of the ray's origin
2188     * @param originZ
2189     *              the z coordinate of the ray's origin
2190     * @param dirX
2191     *              the x coordinate of the ray's direction
2192     * @param dirY
2193     *              the y coordinate of the ray's direction
2194     * @param dirZ
2195     *              the z coordinate of the ray's direction
2196     * @param minX
2197     *              the x coordinate of the minimum corner of the axis-aligned box
2198     * @param minY
2199     *              the y coordinate of the minimum corner of the axis-aligned box
2200     * @param minZ
2201     *              the z coordinate of the minimum corner of the axis-aligned box
2202     * @param maxX
2203     *              the x coordinate of the maximum corner of the axis-aligned box
2204     * @param maxY
2205     *              the y coordinate of the maximum corner of the axis-aligned box
2206     * @param maxZ
2207     *              the y coordinate of the maximum corner of the axis-aligned box
2208     * @param result
2209     *              a vector which will hold the resulting values of the parameter
2210     *              <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> of the near and far point of intersection
2211     *              iff the ray intersects the axis-aligned box
2212     * @return <code>true</code> if the given ray intersects the axis-aligned box; <code>false</code> otherwise
2213     */
2214 public static bool intersectRayAab(double originX, double originY, double originZ, double dirX, double dirY, double dirZ,
2215         double minX, double minY, double minZ, double maxX, double maxY, double maxZ, ref Vector2d result) {
2216     double invDirX = 1.0 / dirX, invDirY = 1.0 / dirY, invDirZ = 1.0 / dirZ;
2217     double tNear, tFar, tymin, tymax, tzmin, tzmax;
2218     if (invDirX >= 0.0) {
2219         tNear = (minX - originX) * invDirX;
2220         tFar = (maxX - originX) * invDirX;
2221     } else {
2222         tNear = (maxX - originX) * invDirX;
2223         tFar = (minX - originX) * invDirX;
2224     }
2225     if (invDirY >= 0.0) {
2226         tymin = (minY - originY) * invDirY;
2227         tymax = (maxY - originY) * invDirY;
2228     } else {
2229         tymin = (maxY - originY) * invDirY;
2230         tymax = (minY - originY) * invDirY;
2231     }
2232     if (tNear > tymax || tymin > tFar)
2233         return false;
2234     if (invDirZ >= 0.0) {
2235         tzmin = (minZ - originZ) * invDirZ;
2236         tzmax = (maxZ - originZ) * invDirZ;
2237     } else {
2238         tzmin = (maxZ - originZ) * invDirZ;
2239         tzmax = (minZ - originZ) * invDirZ;
2240     }
2241     if (tNear > tzmax || tzmin > tFar)
2242         return false;
2243     tNear = tymin > tNear || isNaN(tNear) ? tymin : tNear;
2244     tFar = tymax < tFar || isNaN(tFar) ? tymax : tFar;
2245     tNear = tzmin > tNear ? tzmin : tNear;
2246     tFar = tzmax < tFar ? tzmax : tFar;
2247     if (tNear < tFar && tFar >= 0.0) {
2248         result.x = tNear;
2249         result.y = tFar;
2250         return true;
2251     }
2252     return false;
2253 }
2254 
2255 /**
2256     * Test whether the ray with the given <code>origin</code> and direction <code>dir</code>
2257     * intersects the axis-aligned box specified as its minimum corner <code>min</code> and maximum corner <code>max</code>,
2258     * and return the values of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> of the near and far point of intersection..
2259     * <p>
2260     * This method returns <code>true</code> for a ray whose origin lies inside the axis-aligned box.
2261     * <p>
2262     * If many boxes need to be tested against the same ray, then the {@link RayAabIntersection} class is likely more efficient.
2263     * <p>
2264     * Reference: <a href="https://dl.acm.org/citation.cfm?id=1198748">An Efficient and Robust Ray–Box Intersection</a>
2265     * 
2266     * @see #intersectRayAab(double, double, double, double, double, double, double, double, double, double, double, double, Vector2d)
2267     * @see RayAabIntersection
2268     * 
2269     * @param origin
2270     *              the ray's origin
2271     * @param dir
2272     *              the ray's direction
2273     * @param min
2274     *              the minimum corner of the axis-aligned box
2275     * @param max
2276     *              the maximum corner of the axis-aligned box
2277     * @param result
2278     *              a vector which will hold the resulting values of the parameter
2279     *              <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> of the near and far point of intersection
2280     *              iff the ray intersects the axis-aligned box
2281     * @return <code>true</code> if the given ray intersects the axis-aligned box; <code>false</code> otherwise
2282     */
2283 public static bool intersectRayAab(Vector3d origin, Vector3d dir, Vector3d min, Vector3d max, ref Vector2d result) {
2284     return intersectRayAab(origin.x, origin.y, origin.z, dir.x, dir.y, dir.z, min.x, min.y, min.z, max.x, max.y, max.z, result);
2285 }
2286 
2287 /**
2288     * Determine whether the undirected line segment with the end points <code>(p0X, p0Y, p0Z)</code> and <code>(p1X, p1Y, p1Z)</code>
2289     * intersects the axis-aligned box given as its minimum corner <code>(minX, minY, minZ)</code> and maximum corner <code>(maxX, maxY, maxZ)</code>,
2290     * and return the values of the parameter <i>t</i> in the ray equation <i>p(t) = origin + p0 * (p1 - p0)</i> of the near and far point of intersection.
2291     * <p>
2292     * This method returns <code>true</code> for a line segment whose either end point lies inside the axis-aligned box.
2293     * <p>
2294     * Reference: <a href="https://dl.acm.org/citation.cfm?id=1198748">An Efficient and Robust Ray–Box Intersection</a>
2295     * 
2296     * @see #intersectLineSegmentAab(Vector3d, Vector3d, Vector3d, Vector3d, Vector2d)
2297     * 
2298     * @param p0X
2299     *              the x coordinate of the line segment's first end point
2300     * @param p0Y
2301     *              the y coordinate of the line segment's first end point
2302     * @param p0Z
2303     *              the z coordinate of the line segment's first end point
2304     * @param p1X
2305     *              the x coordinate of the line segment's second end point
2306     * @param p1Y
2307     *              the y coordinate of the line segment's second end point
2308     * @param p1Z
2309     *              the z coordinate of the line segment's second end point
2310     * @param minX
2311     *              the x coordinate of one corner of the axis-aligned box
2312     * @param minY
2313     *              the y coordinate of one corner of the axis-aligned box
2314     * @param minZ
2315     *              the z coordinate of one corner of the axis-aligned box
2316     * @param maxX
2317     *              the x coordinate of the opposite corner of the axis-aligned box
2318     * @param maxY
2319     *              the y coordinate of the opposite corner of the axis-aligned box
2320     * @param maxZ
2321     *              the y coordinate of the opposite corner of the axis-aligned box
2322     * @param result
2323     *              a vector which will ing values of the parameter
2324     *              <i>t</i> in the ray equation <i>p(t) = p0 + t * (p1 - p0)</i> of the near and far point of intersection
2325     *              iff the line segment intersects the axis-aligned box
2326     * @return {@link #INSIDE} if the line segment lies completely inside of the axis-aligned box; or
2327     *         {@link #OUTSIDE} if the line segment lies completely outside of the axis-aligned box; or
2328     *         {@link #ONE_INTERSECTION} if one of the end points of the line segment lies inside of the axis-aligned box; or
2329     *         {@link #TWO_INTERSECTION} if the line segment intersects two sides of the axis-aligned box
2330     *         or lies on an edge or a side of the box
2331     */
2332 public static int intersectLineSegmentAab(double p0X, double p0Y, double p0Z, double p1X, double p1Y, double p1Z,
2333         double minX, double minY, double minZ, double maxX, double maxY, double maxZ, Vector2d result) {
2334     double dirX = p1X - p0X, dirY = p1Y - p0Y, dirZ = p1Z - p0Z;
2335     double invDirX = 1.0 / dirX, invDirY = 1.0 / dirY, invDirZ = 1.0 / dirZ;
2336     double tNear, tFar, tymin, tymax, tzmin, tzmax;
2337     if (invDirX >= 0.0) {
2338         tNear = (minX - p0X) * invDirX;
2339         tFar = (maxX - p0X) * invDirX;
2340     } else {
2341         tNear = (maxX - p0X) * invDirX;
2342         tFar = (minX - p0X) * invDirX;
2343     }
2344     if (invDirY >= 0.0) {
2345         tymin = (minY - p0Y) * invDirY;
2346         tymax = (maxY - p0Y) * invDirY;
2347     } else {
2348         tymin = (maxY - p0Y) * invDirY;
2349         tymax = (minY - p0Y) * invDirY;
2350     }
2351     if (tNear > tymax || tymin > tFar)
2352         return OUTSIDE;
2353     if (invDirZ >= 0.0) {
2354         tzmin = (minZ - p0Z) * invDirZ;
2355         tzmax = (maxZ - p0Z) * invDirZ;
2356     } else {
2357         tzmin = (maxZ - p0Z) * invDirZ;
2358         tzmax = (minZ - p0Z) * invDirZ;
2359     }
2360     if (tNear > tzmax || tzmin > tFar)
2361         return OUTSIDE;
2362     tNear = tymin > tNear || isNaN(tNear) ? tymin : tNear;
2363     tFar = tymax < tFar || isNaN(tFar) ? tymax : tFar;
2364     tNear = tzmin > tNear ? tzmin : tNear;
2365     tFar = tzmax < tFar ? tzmax : tFar;
2366     int type = OUTSIDE;
2367     if (tNear <= tFar && tNear <= 1.0f && tFar >= 0.0f) {
2368         if (tNear >= 0.0f && tFar > 1.0f) {
2369             tFar = tNear;
2370             type = ONE_INTERSECTION;
2371         } else if (tNear < 0.0f && tFar <= 1.0f) {
2372             tNear = tFar;
2373             type = ONE_INTERSECTION;
2374         } else if (tNear < 0.0f && tFar > 1.0f) {
2375             type = INSIDE;
2376         } else {
2377             type = TWO_INTERSECTION;
2378         }
2379         result.x = tNear;
2380         result.y = tFar;
2381     }
2382     return type;
2383 }
2384 
2385 /**
2386     * Determine whether the undirected line segment with the end points <code>p0</code> and <code>p1</code>
2387     * intersects the axis-aligned box given as its minimum corner <code>min</code> and maximum corner <code>max</code>,
2388     * and return the values of the parameter <i>t</i> in the ray equation <i>p(t) = origin + p0 * (p1 - p0)</i> of the near and far point of intersection.
2389     * <p>
2390     * This method returns <code>true</code> for a line segment whose either end point lies inside the axis-aligned box.
2391     * <p>
2392     * Reference: <a href="https://dl.acm.org/citation.cfm?id=1198748">An Efficient and Robust Ray–Box Intersection</a>
2393     * 
2394     * @see #intersectLineSegmentAab(Vector3d, Vector3d, Vector3d, Vector3d, Vector2d)
2395     * 
2396     * @param p0
2397     *              the line segment's first end point
2398     * @param p1
2399     *              the line segment's second end point
2400     * @param min
2401     *              the minimum corner of the axis-aligned box
2402     * @param max
2403     *              the maximum corner of the axis-aligned box
2404     * @param result
2405     *              a vector which will hold the resulting values of the parameter
2406     *              <i>t</i> in the ray equation <i>p(t) = p0 + t * (p1 - p0)</i> of the near and far point of intersection
2407     *              iff the line segment intersects the axis-aligned box
2408     * @return {@link #INSIDE} if the line segment lies completely inside of the axis-aligned box; or
2409     *         {@link #OUTSIDE} if the line segment lies completely outside of the axis-aligned box; or
2410     *         {@link #ONE_INTERSECTION} if one of the end points of the line segment lies inside of the axis-aligned box; or
2411     *         {@link #TWO_INTERSECTION} if the line segment intersects two sides of the axis-aligned box
2412     *         or lies on an edge or a side of the box
2413     */
2414 public static int intersectLineSegmentAab(Vector3d p0, Vector3d p1, Vector3d min, Vector3d max, ref Vector2d result) {
2415     return intersectLineSegmentAab(p0.x, p0.y, p0.z, p1.x, p1.y, p1.z, min.x, min.y, min.z, max.x, max.y, max.z, result);
2416 }
2417 
2418 /**
2419     * Test whether the given ray with the origin <code>(originX, originY, originZ)</code> and direction <code>(dirX, dirY, dirZ)</code>
2420     * intersects the axis-aligned box given as its minimum corner <code>(minX, minY, minZ)</code> and maximum corner <code>(maxX, maxY, maxZ)</code>.
2421     * <p>
2422     * This method returns <code>true</code> for a ray whose origin lies inside the axis-aligned box.
2423     * <p>
2424     * If many boxes need to be tested against the same ray, then the {@link RayAabIntersection} class is likely more efficient.
2425     * <p>
2426     * Reference: <a href="https://dl.acm.org/citation.cfm?id=1198748">An Efficient and Robust Ray–Box Intersection</a>
2427     * 
2428     * @see #testRayAab(Vector3d, Vector3d, Vector3d, Vector3d)
2429     * @see RayAabIntersection
2430     * 
2431     * @param originX
2432     *              the x coordinate of the ray's origin
2433     * @param originY
2434     *              the y coordinate of the ray's origin
2435     * @param originZ
2436     *              the z coordinate of the ray's origin
2437     * @param dirX
2438     *              the x coordinate of the ray's direction
2439     * @param dirY
2440     *              the y coordinate of the ray's direction
2441     * @param dirZ
2442     *              the z coordinate of the ray's direction
2443     * @param minX
2444     *              the x coordinate of the minimum corner of the axis-aligned box
2445     * @param minY
2446     *              the y coordinate of the minimum corner of the axis-aligned box
2447     * @param minZ
2448     *              the z coordinate of the minimum corner of the axis-aligned box
2449     * @param maxX
2450     *              the x coordinate of the maximum corner of the axis-aligned box
2451     * @param maxY
2452     *              the y coordinate of the maximum corner of the axis-aligned box
2453     * @param maxZ
2454     *              the y coordinate of the maximum corner of the axis-aligned box
2455     * @return <code>true</code> if the given ray intersects the axis-aligned box; <code>false</code> otherwise
2456     */
2457 public static bool testRayAab(double originX, double originY, double originZ, double dirX, double dirY, double dirZ,
2458         double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {
2459     double invDirX = 1.0 / dirX, invDirY = 1.0 / dirY, invDirZ = 1.0 / dirZ;
2460     double tNear, tFar, tymin, tymax, tzmin, tzmax;
2461     if (invDirX >= 0.0) {
2462         tNear = (minX - originX) * invDirX;
2463         tFar = (maxX - originX) * invDirX;
2464     } else {
2465         tNear = (maxX - originX) * invDirX;
2466         tFar = (minX - originX) * invDirX;
2467     }
2468     if (invDirY >= 0.0) {
2469         tymin = (minY - originY) * invDirY;
2470         tymax = (maxY - originY) * invDirY;
2471     } else {
2472         tymin = (maxY - originY) * invDirY;
2473         tymax = (minY - originY) * invDirY;
2474     }
2475     if (tNear > tymax || tymin > tFar)
2476         return false;
2477     if (invDirZ >= 0.0) {
2478         tzmin = (minZ - originZ) * invDirZ;
2479         tzmax = (maxZ - originZ) * invDirZ;
2480     } else {
2481         tzmin = (maxZ - originZ) * invDirZ;
2482         tzmax = (minZ - originZ) * invDirZ;
2483     }
2484     if (tNear > tzmax || tzmin > tFar)
2485         return false;
2486     tNear = tymin > tNear || isNaN(tNear) ? tymin : tNear;
2487     tFar = tymax < tFar || isNaN(tFar) ? tymax : tFar;
2488     tNear = tzmin > tNear ? tzmin : tNear;
2489     tFar = tzmax < tFar ? tzmax : tFar;
2490     return tNear < tFar && tFar >= 0.0;
2491 }
2492 
2493 /**
2494     * Test whether the ray with the given <code>origin</code> and direction <code>dir</code>
2495     * intersects the axis-aligned box specified as its minimum corner <code>min</code> and maximum corner <code>max</code>.
2496     * <p>
2497     * This method returns <code>true</code> for a ray whose origin lies inside the axis-aligned box.
2498     * <p>
2499     * If many boxes need to be tested against the same ray, then the {@link RayAabIntersection} class is likely more efficient.
2500     * <p>
2501     * Reference: <a href="https://dl.acm.org/citation.cfm?id=1198748">An Efficient and Robust Ray–Box Intersection</a>
2502     *  
2503     * @see #testRayAab(double, double, double, double, double, double, double, double, double, double, double, double)
2504     * @see RayAabIntersection
2505     * 
2506     * @param origin
2507     *              the ray's origin
2508     * @param dir
2509     *              the ray's direction
2510     * @param min
2511     *              the minimum corner of the axis-aligned box
2512     * @param max
2513     *              the maximum corner of the axis-aligned box
2514     * @return <code>true</code> if the given ray intersects the axis-aligned box; <code>false</code> otherwise
2515     */
2516 public static bool testRayAab(Vector3d origin, Vector3d dir, Vector3d min, Vector3d max) {
2517     return testRayAab(origin.x, origin.y, origin.z, dir.x, dir.y, dir.z, min.x, min.y, min.z, max.x, max.y, max.z);
2518 }
2519 
2520 /**
2521     * Test whether the given ray with the origin <code>(originX, originY, originZ)</code> and direction <code>(dirX, dirY, dirZ)</code>
2522     * intersects the frontface of the triangle consisting of the three vertices <code>(v0X, v0Y, v0Z)</code>, <code>(v1X, v1Y, v1Z)</code> and <code>(v2X, v2Y, v2Z)</code>.
2523     * <p>
2524     * This is an implementation of the <a href="http://www.graphics.cornell.edu/pubs/1997/MT97.pdf">
2525     * Fast, Minimum Storage Ray/Triangle Intersection</a> method.
2526     * <p>
2527     * This test implements backface culling, that is, it will return <code>false</code> when the triangle is in clockwise
2528     * winding order assuming a <i>right-handed</i> coordinate system when seen along the ray's direction, even if the ray intersects the triangle.
2529     * This is in compliance with how OpenGL handles backface culling with default frontface/backface settings.
2530     * 
2531     * @see #testRayTriangleFront(Vector3d, Vector3d, Vector3d, Vector3d, Vector3d, double)
2532     * 
2533     * @param originX
2534     *              the x coordinate of the ray's origin
2535     * @param originY
2536     *              the y coordinate of the ray's origin
2537     * @param originZ
2538     *              the z coordinate of the ray's origin
2539     * @param dirX
2540     *              the x coordinate of the ray's direction
2541     * @param dirY
2542     *              the y coordinate of the ray's direction
2543     * @param dirZ
2544     *              the z coordinate of the ray's direction
2545     * @param v0X
2546     *              the x coordinate of the first vertex
2547     * @param v0Y
2548     *              the y coordinate of the first vertex
2549     * @param v0Z
2550     *              the z coordinate of the first vertex
2551     * @param v1X
2552     *              the x coordinate of the second vertex
2553     * @param v1Y
2554     *              the y coordinate of the second vertex
2555     * @param v1Z
2556     *              the z coordinate of the second vertex
2557     * @param v2X
2558     *              the x coordinate of the third vertex
2559     * @param v2Y
2560     *              the y coordinate of the third vertex
2561     * @param v2Z
2562     *              the z coordinate of the third vertex
2563     * @param epsilon
2564     *              a small epsilon when testing rays that are almost parallel to the triangle
2565     * @return <code>true</code> if the given ray intersects the frontface of the triangle; <code>false</code> otherwise
2566     */
2567 public static bool testRayTriangleFront(double originX, double originY, double originZ, double dirX, double dirY, double dirZ,
2568         double v0X, double v0Y, double v0Z, double v1X, double v1Y, double v1Z, double v2X, double v2Y, double v2Z,
2569         double epsilon) {
2570     double edge1X = v1X - v0X;
2571     double edge1Y = v1Y - v0Y;
2572     double edge1Z = v1Z - v0Z;
2573     double edge2X = v2X - v0X;
2574     double edge2Y = v2Y - v0Y;
2575     double edge2Z = v2Z - v0Z;
2576     double pvecX = dirY * edge2Z - dirZ * edge2Y;
2577     double pvecY = dirZ * edge2X - dirX * edge2Z;
2578     double pvecZ = dirX * edge2Y - dirY * edge2X;
2579     double det = edge1X * pvecX + edge1Y * pvecY + edge1Z * pvecZ;
2580     if (det < epsilon)
2581         return false;
2582     double tvecX = originX - v0X;
2583     double tvecY = originY - v0Y;
2584     double tvecZ = originZ - v0Z;
2585     double u = (tvecX * pvecX + tvecY * pvecY + tvecZ * pvecZ);
2586     if (u < 0.0 || u > det)
2587         return false;
2588     double qvecX = tvecY * edge1Z - tvecZ * edge1Y;
2589     double qvecY = tvecZ * edge1X - tvecX * edge1Z;
2590     double qvecZ = tvecX * edge1Y - tvecY * edge1X;
2591     double v = (dirX * qvecX + dirY * qvecY + dirZ * qvecZ);
2592     if (v < 0.0 || u + v > det)
2593         return false;
2594     double invDet = 1.0 / det;
2595     double t = (edge2X * qvecX + edge2Y * qvecY + edge2Z * qvecZ) * invDet;
2596     return t >= epsilon;
2597 }
2598 
2599 /**
2600     * Test whether the ray with the given <code>origin</code> and the given <code>dir</code> intersects the frontface of the triangle consisting of the three vertices
2601     * <code>v0</code>, <code>v1</code> and <code>v2</code>.
2602     * <p>
2603     * This is an implementation of the <a href="http://www.graphics.cornell.edu/pubs/1997/MT97.pdf">
2604     * Fast, Minimum Storage Ray/Triangle Intersection</a> method.
2605     * <p>
2606     * This test implements backface culling, that is, it will return <code>false</code> when the triangle is in clockwise
2607     * winding order assuming a <i>right-handed</i> coordinate system when seen along the ray's direction, even if the ray intersects the triangle.
2608     * This is in compliance with how OpenGL handles backface culling with default frontface/backface settings.
2609     * 
2610     * @see #testRayTriangleFront(double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double)
2611     * 
2612     * @param origin
2613     *              the ray's origin
2614     * @param dir
2615     *              the ray's direction
2616     * @param v0
2617     *              the position of the first vertex
2618     * @param v1
2619     *              the position of the second vertex
2620     * @param v2
2621     *              the position of the third vertex
2622     * @param epsilon
2623     *              a small epsilon when testing rays that are almost parallel to the triangle
2624     * @return <code>true</code> if the given ray intersects the frontface of the triangle; <code>false</code> otherwise
2625     */
2626 public static bool testRayTriangleFront(Vector3d origin, Vector3d dir, Vector3d v0, Vector3d v1, Vector3d v2, double epsilon) {
2627     return testRayTriangleFront(origin.x, origin.y, origin.z, dir.x, dir.y, dir.z, v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, epsilon);
2628 }
2629 
2630 /**
2631     * Test whether the given ray with the origin <code>(originX, originY, originZ)</code> and direction <code>(dirX, dirY, dirZ)</code>
2632     * intersects the triangle consisting of the three vertices <code>(v0X, v0Y, v0Z)</code>, <code>(v1X, v1Y, v1Z)</code> and <code>(v2X, v2Y, v2Z)</code>.
2633     * <p>
2634     * This is an implementation of the <a href="http://www.graphics.cornell.edu/pubs/1997/MT97.pdf">
2635     * Fast, Minimum Storage Ray/Triangle Intersection</a> method.
2636     * <p>
2637     * This test does not take into account the winding order of the triangle, so a ray will intersect a front-facing triangle as well as a back-facing triangle.
2638     * 
2639     * @see #testRayTriangle(Vector3d, Vector3d, Vector3d, Vector3d, Vector3d, double)
2640     * 
2641     * @param originX
2642     *              the x coordinate of the ray's origin
2643     * @param originY
2644     *              the y coordinate of the ray's origin
2645     * @param originZ
2646     *              the z coordinate of the ray's origin
2647     * @param dirX
2648     *              the x coordinate of the ray's direction
2649     * @param dirY
2650     *              the y coordinate of the ray's direction
2651     * @param dirZ
2652     *              the z coordinate of the ray's direction
2653     * @param v0X
2654     *              the x coordinate of the first vertex
2655     * @param v0Y
2656     *              the y coordinate of the first vertex
2657     * @param v0Z
2658     *              the z coordinate of the first vertex
2659     * @param v1X
2660     *              the x coordinate of the second vertex
2661     * @param v1Y
2662     *              the y coordinate of the second vertex
2663     * @param v1Z
2664     *              the z coordinate of the second vertex
2665     * @param v2X
2666     *              the x coordinate of the third vertex
2667     * @param v2Y
2668     *              the y coordinate of the third vertex
2669     * @param v2Z
2670     *              the z coordinate of the third vertex
2671     * @param epsilon
2672     *              a small epsilon when testing rays that are almost parallel to the triangle
2673     * @return <code>true</code> if the given ray intersects the frontface of the triangle; <code>false</code> otherwise
2674     */
2675 public static bool testRayTriangle(double originX, double originY, double originZ, double dirX, double dirY, double dirZ,
2676         double v0X, double v0Y, double v0Z, double v1X, double v1Y, double v1Z, double v2X, double v2Y, double v2Z,
2677         double epsilon) {
2678     double edge1X = v1X - v0X;
2679     double edge1Y = v1Y - v0Y;
2680     double edge1Z = v1Z - v0Z;
2681     double edge2X = v2X - v0X;
2682     double edge2Y = v2Y - v0Y;
2683     double edge2Z = v2Z - v0Z;
2684     double pvecX = dirY * edge2Z - dirZ * edge2Y;
2685     double pvecY = dirZ * edge2X - dirX * edge2Z;
2686     double pvecZ = dirX * edge2Y - dirY * edge2X;
2687     double det = edge1X * pvecX + edge1Y * pvecY + edge1Z * pvecZ;
2688     if (det > -epsilon && det < epsilon)
2689         return false;
2690     double tvecX = originX - v0X;
2691     double tvecY = originY - v0Y;
2692     double tvecZ = originZ - v0Z;
2693     double invDet = 1.0 / det;
2694     double u = (tvecX * pvecX + tvecY * pvecY + tvecZ * pvecZ) * invDet;
2695     if (u < 0.0 || u > 1.0)
2696         return false;
2697     double qvecX = tvecY * edge1Z - tvecZ * edge1Y;
2698     double qvecY = tvecZ * edge1X - tvecX * edge1Z;
2699     double qvecZ = tvecX * edge1Y - tvecY * edge1X;
2700     double v = (dirX * qvecX + dirY * qvecY + dirZ * qvecZ) * invDet;
2701     if (v < 0.0 || u + v > 1.0)
2702         return false;
2703     double t = (edge2X * qvecX + edge2Y * qvecY + edge2Z * qvecZ) * invDet;
2704     return t >= epsilon;
2705 }
2706 
2707 /**
2708     * Test whether the ray with the given <code>origin</code> and the given <code>dir</code> intersects the frontface of the triangle consisting of the three vertices
2709     * <code>v0</code>, <code>v1</code> and <code>v2</code>.
2710     * <p>
2711     * This is an implementation of the <a href="http://www.graphics.cornell.edu/pubs/1997/MT97.pdf">
2712     * Fast, Minimum Storage Ray/Triangle Intersection</a> method.
2713     * <p>
2714     * This test does not take into account the winding order of the triangle, so a ray will intersect a front-facing triangle as well as a back-facing triangle.
2715     * 
2716     * @see #testRayTriangle(double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double)
2717     * 
2718     * @param origin
2719     *              the ray's origin
2720     * @param dir
2721     *              the ray's direction
2722     * @param v0
2723     *              the position of the first vertex
2724     * @param v1
2725     *              the position of the second vertex
2726     * @param v2
2727     *              the position of the third vertex
2728     * @param epsilon
2729     *              a small epsilon when testing rays that are almost parallel to the triangle
2730     * @return <code>true</code> if the given ray intersects the frontface of the triangle; <code>false</code> otherwise
2731     */
2732 public static bool testRayTriangle(Vector3d origin, Vector3d dir, Vector3d v0, Vector3d v1, Vector3d v2, double epsilon) {
2733     return testRayTriangle(origin.x, origin.y, origin.z, dir.x, dir.y, dir.z, v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, epsilon);
2734 }
2735 
2736 /**
2737     * Determine whether the given ray with the origin <code>(originX, originY, originZ)</code> and direction <code>(dirX, dirY, dirZ)</code>
2738     * intersects the frontface of the triangle consisting of the three vertices <code>(v0X, v0Y, v0Z)</code>, <code>(v1X, v1Y, v1Z)</code> and <code>(v2X, v2Y, v2Z)</code>
2739     * and return the value of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> of the point of intersection.
2740     * <p>
2741     * This is an implementation of the <a href="http://www.graphics.cornell.edu/pubs/1997/MT97.pdf">
2742     * Fast, Minimum Storage Ray/Triangle Intersection</a> method.
2743     * <p>
2744     * This test implements backface culling, that is, it will return <code>false</code> when the triangle is in clockwise
2745     * winding order assuming a <i>right-handed</i> coordinate system when seen along the ray's direction, even if the ray intersects the triangle.
2746     * This is in compliance with how OpenGL handles backface culling with default frontface/backface settings.
2747     * 
2748     * @see #testRayTriangleFront(Vector3d, Vector3d, Vector3d, Vector3d, Vector3d, double)
2749     * 
2750     * @param originX
2751     *              the x coordinate of the ray's origin
2752     * @param originY
2753     *              the y coordinate of the ray's origin
2754     * @param originZ
2755     *              the z coordinate of the ray's origin
2756     * @param dirX
2757     *              the x coordinate of the ray's direction
2758     * @param dirY
2759     *              the y coordinate of the ray's direction
2760     * @param dirZ
2761     *              the z coordinate of the ray's direction
2762     * @param v0X
2763     *              the x coordinate of the first vertex
2764     * @param v0Y
2765     *              the y coordinate of the first vertex
2766     * @param v0Z
2767     *              the z coordinate of the first vertex
2768     * @param v1X
2769     *              the x coordinate of the second vertex
2770     * @param v1Y
2771     *              the y coordinate of the second vertex
2772     * @param v1Z
2773     *              the z coordinate of the second vertex
2774     * @param v2X
2775     *              the x coordinate of the third vertex
2776     * @param v2Y
2777     *              the y coordinate of the third vertex
2778     * @param v2Z
2779     *              the z coordinate of the third vertex
2780     * @param epsilon
2781     *              a small epsilon when testing rays that are almost parallel to the triangle
2782     * @return the value of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> of the point of intersection
2783     *         if the ray intersects the frontface of the triangle; <code>-1.0</code> otherwise
2784     */
2785 public static double intersectRayTriangleFront(double originX, double originY, double originZ, double dirX, double dirY, double dirZ,
2786         double v0X, double v0Y, double v0Z, double v1X, double v1Y, double v1Z, double v2X, double v2Y, double v2Z,
2787         double epsilon) {
2788     double edge1X = v1X - v0X;
2789     double edge1Y = v1Y - v0Y;
2790     double edge1Z = v1Z - v0Z;
2791     double edge2X = v2X - v0X;
2792     double edge2Y = v2Y - v0Y;
2793     double edge2Z = v2Z - v0Z;
2794     double pvecX = dirY * edge2Z - dirZ * edge2Y;
2795     double pvecY = dirZ * edge2X - dirX * edge2Z;
2796     double pvecZ = dirX * edge2Y - dirY * edge2X;
2797     double det = edge1X * pvecX + edge1Y * pvecY + edge1Z * pvecZ;
2798     if (det <= epsilon)
2799         return -1.0;
2800     double tvecX = originX - v0X;
2801     double tvecY = originY - v0Y;
2802     double tvecZ = originZ - v0Z;
2803     double u = tvecX * pvecX + tvecY * pvecY + tvecZ * pvecZ;
2804     if (u < 0.0 || u > det)
2805         return -1.0;
2806     double qvecX = tvecY * edge1Z - tvecZ * edge1Y;
2807     double qvecY = tvecZ * edge1X - tvecX * edge1Z;
2808     double qvecZ = tvecX * edge1Y - tvecY * edge1X;
2809     double v = dirX * qvecX + dirY * qvecY + dirZ * qvecZ;
2810     if (v < 0.0 || u + v > det)
2811         return -1.0;
2812     double invDet = 1.0 / det;
2813     double t = (edge2X * qvecX + edge2Y * qvecY + edge2Z * qvecZ) * invDet;
2814     return t;
2815 }
2816 
2817 /**
2818     * Determine whether the ray with the given <code>origin</code> and the given <code>dir</code> intersects the frontface of the triangle consisting of the three vertices
2819     * <code>v0</code>, <code>v1</code> and <code>v2</code> and return the value of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> of the point of intersection.
2820     * <p>
2821     * This is an implementation of the <a href="http://www.graphics.cornell.edu/pubs/1997/MT97.pdf">
2822     * Fast, Minimum Storage Ray/Triangle Intersection</a> method.
2823     * <p>
2824     * This test implements backface culling, that is, it will return <code>false</code> when the triangle is in clockwise
2825     * winding order assuming a <i>right-handed</i> coordinate system when seen along the ray's direction, even if the ray intersects the triangle.
2826     * This is in compliance with how OpenGL handles backface culling with default frontface/backface settings.
2827     * 
2828     * @see #intersectRayTriangleFront(double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double)
2829     * 
2830     * @param origin
2831     *              the ray's origin
2832     * @param dir
2833     *              the ray's direction
2834     * @param v0
2835     *              the position of the first vertex
2836     * @param v1
2837     *              the position of the second vertex
2838     * @param v2
2839     *              the position of the third vertex
2840     * @param epsilon
2841     *              a small epsilon when testing rays that are almost parallel to the triangle
2842     * @return the value of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> of the point of intersection
2843     *         if the ray intersects the frontface of the triangle; <code>-1.0</code> otherwise
2844     */
2845 public static double intersectRayTriangleFront(Vector3d origin, Vector3d dir, Vector3d v0, Vector3d v1, Vector3d v2, double epsilon) {
2846     return intersectRayTriangleFront(origin.x, origin.y, origin.z, dir.x, dir.y, dir.z, v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, epsilon);
2847 }
2848 
2849 /**
2850     * Determine whether the given ray with the origin <code>(originX, originY, originZ)</code> and direction <code>(dirX, dirY, dirZ)</code>
2851     * intersects the triangle consisting of the three vertices <code>(v0X, v0Y, v0Z)</code>, <code>(v1X, v1Y, v1Z)</code> and <code>(v2X, v2Y, v2Z)</code>
2852     * and return the value of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> of the point of intersection.
2853     * <p>
2854     * This is an implementation of the <a href="http://www.graphics.cornell.edu/pubs/1997/MT97.pdf">
2855     * Fast, Minimum Storage Ray/Triangle Intersection</a> method.
2856     * <p>
2857     * This test does not take into account the winding order of the triangle, so a ray will intersect a front-facing triangle as well as a back-facing triangle.
2858     * 
2859     * @see #testRayTriangle(Vector3d, Vector3d, Vector3d, Vector3d, Vector3d, double)
2860     * 
2861     * @param originX
2862     *              the x coordinate of the ray's origin
2863     * @param originY
2864     *              the y coordinate of the ray's origin
2865     * @param originZ
2866     *              the z coordinate of the ray's origin
2867     * @param dirX
2868     *              the x coordinate of the ray's direction
2869     * @param dirY
2870     *              the y coordinate of the ray's direction
2871     * @param dirZ
2872     *              the z coordinate of the ray's direction
2873     * @param v0X
2874     *              the x coordinate of the first vertex
2875     * @param v0Y
2876     *              the y coordinate of the first vertex
2877     * @param v0Z
2878     *              the z coordinate of the first vertex
2879     * @param v1X
2880     *              the x coordinate of the second vertex
2881     * @param v1Y
2882     *              the y coordinate of the second vertex
2883     * @param v1Z
2884     *              the z coordinate of the second vertex
2885     * @param v2X
2886     *              the x coordinate of the third vertex
2887     * @param v2Y
2888     *              the y coordinate of the third vertex
2889     * @param v2Z
2890     *              the z coordinate of the third vertex
2891     * @param epsilon
2892     *              a small epsilon when testing rays that are almost parallel to the triangle
2893     * @return the value of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> of the point of intersection
2894     *         if the ray intersects the triangle; <code>-1.0</code> otherwise
2895     */
2896 public static double intersectRayTriangle(double originX, double originY, double originZ, double dirX, double dirY, double dirZ,
2897         double v0X, double v0Y, double v0Z, double v1X, double v1Y, double v1Z, double v2X, double v2Y, double v2Z,
2898         double epsilon) {
2899     double edge1X = v1X - v0X;
2900     double edge1Y = v1Y - v0Y;
2901     double edge1Z = v1Z - v0Z;
2902     double edge2X = v2X - v0X;
2903     double edge2Y = v2Y - v0Y;
2904     double edge2Z = v2Z - v0Z;
2905     double pvecX = dirY * edge2Z - dirZ * edge2Y;
2906     double pvecY = dirZ * edge2X - dirX * edge2Z;
2907     double pvecZ = dirX * edge2Y - dirY * edge2X;
2908     double det = edge1X * pvecX + edge1Y * pvecY + edge1Z * pvecZ;
2909     if (det > -epsilon && det < epsilon)
2910         return -1.0;
2911     double tvecX = originX - v0X;
2912     double tvecY = originY - v0Y;
2913     double tvecZ = originZ - v0Z;
2914     double invDet = 1.0 / det;
2915     double u = (tvecX * pvecX + tvecY * pvecY + tvecZ * pvecZ) * invDet;
2916     if (u < 0.0 || u > 1.0)
2917         return -1.0;
2918     double qvecX = tvecY * edge1Z - tvecZ * edge1Y;
2919     double qvecY = tvecZ * edge1X - tvecX * edge1Z;
2920     double qvecZ = tvecX * edge1Y - tvecY * edge1X;
2921     double v = (dirX * qvecX + dirY * qvecY + dirZ * qvecZ) * invDet;
2922     if (v < 0.0 || u + v > 1.0)
2923         return -1.0;
2924     double t = (edge2X * qvecX + edge2Y * qvecY + edge2Z * qvecZ) * invDet;
2925     return t;
2926 }
2927 
2928 /**
2929     * Determine whether the ray with the given <code>origin</code> and the given <code>dir</code> intersects the triangle consisting of the three vertices
2930     * <code>v0</code>, <code>v1</code> and <code>v2</code> and return the value of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> of the point of intersection.
2931     * <p>
2932     * This is an implementation of the <a href="http://www.graphics.cornell.edu/pubs/1997/MT97.pdf">
2933     * Fast, Minimum Storage Ray/Triangle Intersection</a> method.
2934     * <p>
2935     * This test does not take into account the winding order of the triangle, so a ray will intersect a front-facing triangle as well as a back-facing triangle.
2936     * 
2937     * @see #intersectRayTriangle(double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double)
2938     * 
2939     * @param origin
2940     *              the ray's origin
2941     * @param dir
2942     *              the ray's direction
2943     * @param v0
2944     *              the position of the first vertex
2945     * @param v1
2946     *              the position of the second vertex
2947     * @param v2
2948     *              the position of the third vertex
2949     * @param epsilon
2950     *              a small epsilon when testing rays that are almost parallel to the triangle
2951     * @return the value of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> of the point of intersection
2952     *         if the ray intersects the triangle; <code>-1.0</code> otherwise
2953     */
2954 public static double intersectRayTriangle(Vector3d origin, Vector3d dir, Vector3d v0, Vector3d v1, Vector3d v2, double epsilon) {
2955     return intersectRayTriangle(origin.x, origin.y, origin.z, dir.x, dir.y, dir.z, v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, epsilon);
2956 }
2957 
2958 /**
2959     * Test whether the line segment with the end points <code>(p0X, p0Y, p0Z)</code> and <code>(p1X, p1Y, p1Z)</code>
2960     * intersects the triangle consisting of the three vertices <code>(v0X, v0Y, v0Z)</code>, <code>(v1X, v1Y, v1Z)</code> and <code>(v2X, v2Y, v2Z)</code>,
2961     * regardless of the winding order of the triangle or the direction of the line segment between its two end points.
2962     * <p>
2963     * Reference: <a href="http://www.graphics.cornell.edu/pubs/1997/MT97.pdf">
2964     * Fast, Minimum Storage Ray/Triangle Intersection</a>
2965     * 
2966     * @see #testLineSegmentTriangle(Vector3d, Vector3d, Vector3d, Vector3d, Vector3d, double)
2967     * 
2968     * @param p0X
2969     *              the x coordinate of the line segment's first end point
2970     * @param p0Y
2971     *              the y coordinate of the line segment's first end point
2972     * @param p0Z
2973     *              the z coordinate of the line segment's first end point
2974     * @param p1X
2975     *              the x coordinate of the line segment's second end point
2976     * @param p1Y
2977     *              the y coordinate of the line segment's second end point
2978     * @param p1Z
2979     *              the z coordinate of the line segment's second end point
2980     * @param v0X
2981     *              the x coordinate of the first vertex
2982     * @param v0Y
2983     *              the y coordinate of the first vertex
2984     * @param v0Z
2985     *              the z coordinate of the first vertex
2986     * @param v1X
2987     *              the x coordinate of the second vertex
2988     * @param v1Y
2989     *              the y coordinate of the second vertex
2990     * @param v1Z
2991     *              the z coordinate of the second vertex
2992     * @param v2X
2993     *              the x coordinate of the third vertex
2994     * @param v2Y
2995     *              the y coordinate of the third vertex
2996     * @param v2Z
2997     *              the z coordinate of the third vertex
2998     * @param epsilon
2999     *              a small epsilon when testing line segments that are almost parallel to the triangle
3000     * @return <code>true</code> if the given line segment intersects the triangle; <code>false</code> otherwise
3001     */
3002 public static bool testLineSegmentTriangle(double p0X, double p0Y, double p0Z, double p1X, double p1Y, double p1Z,
3003         double v0X, double v0Y, double v0Z, double v1X, double v1Y, double v1Z, double v2X, double v2Y, double v2Z,
3004         double epsilon) {
3005     double dirX = p1X - p0X;
3006     double dirY = p1Y - p0Y;
3007     double dirZ = p1Z - p0Z;
3008     double t = intersectRayTriangle(p0X, p0Y, p0Z, dirX, dirY, dirZ, v0X, v0Y, v0Z, v1X, v1Y, v1Z, v2X, v2Y, v2Z, epsilon);
3009     return t >= 0.0 && t <= 1.0;
3010 }
3011 
3012 /**
3013     * Test whether the line segment with the end points <code>p0</code> and <code>p1</code>
3014     * intersects the triangle consisting of the three vertices <code>(v0X, v0Y, v0Z)</code>, <code>(v1X, v1Y, v1Z)</code> and <code>(v2X, v2Y, v2Z)</code>,
3015     * regardless of the winding order of the triangle or the direction of the line segment between its two end points.
3016     * <p>
3017     * Reference: <a href="http://www.graphics.cornell.edu/pubs/1997/MT97.pdf">
3018     * Fast, Minimum Storage Ray/Triangle Intersection</a>
3019     * 
3020     * @see #testLineSegmentTriangle(double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double)
3021     * 
3022     * @param p0
3023     *              the line segment's first end point
3024     * @param p1
3025     *              the line segment's second end point
3026     * @param v0
3027     *              the position of the first vertex
3028     * @param v1
3029     *              the position of the second vertex
3030     * @param v2
3031     *              the position of the third vertex
3032     * @param epsilon
3033     *              a small epsilon when testing line segments that are almost parallel to the triangle
3034     * @return <code>true</code> if the given line segment intersects the triangle; <code>false</code> otherwise
3035     */
3036 public static bool testLineSegmentTriangle(Vector3d p0, Vector3d p1, Vector3d v0, Vector3d v1, Vector3d v2, double epsilon) {
3037     return testLineSegmentTriangle(p0.x, p0.y, p0.z, p1.x, p1.y, p1.z, v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, epsilon);
3038 }
3039 
3040 /**
3041     * Determine whether the line segment with the end points <code>(p0X, p0Y, p0Z)</code> and <code>(p1X, p1Y, p1Z)</code>
3042     * intersects the triangle consisting of the three vertices <code>(v0X, v0Y, v0Z)</code>, <code>(v1X, v1Y, v1Z)</code> and <code>(v2X, v2Y, v2Z)</code>,
3043     * regardless of the winding order of the triangle or the direction of the line segment between its two end points,
3044     * and return the point of intersection.
3045     * <p>
3046     * Reference: <a href="http://www.graphics.cornell.edu/pubs/1997/MT97.pdf">
3047     * Fast, Minimum Storage Ray/Triangle Intersection</a>
3048     * 
3049     * @see #intersectLineSegmentTriangle(Vector3d, Vector3d, Vector3d, Vector3d, Vector3d, double, Vector3d)
3050     * 
3051     * @param p0X
3052     *              the x coordinate of the line segment's first end point
3053     * @param p0Y
3054     *              the y coordinate of the line segment's first end point
3055     * @param p0Z
3056     *              the z coordinate of the line segment's first end point
3057     * @param p1X
3058     *              the x coordinate of the line segment's second end point
3059     * @param p1Y
3060     *              the y coordinate of the line segment's second end point
3061     * @param p1Z
3062     *              the z coordinate of the line segment's second end point
3063     * @param v0X
3064     *              the x coordinate of the first vertex
3065     * @param v0Y
3066     *              the y coordinate of the first vertex
3067     * @param v0Z
3068     *              the z coordinate of the first vertex
3069     * @param v1X
3070     *              the x coordinate of the second vertex
3071     * @param v1Y
3072     *              the y coordinate of the second vertex
3073     * @param v1Z
3074     *              the z coordinate of the second vertex
3075     * @param v2X
3076     *              the x coordinate of the third vertex
3077     * @param v2Y
3078     *              the y coordinate of the third vertex
3079     * @param v2Z
3080     *              the z coordinate of the third vertex
3081     * @param epsilon
3082     *              a small epsilon when testing line segments that are almost parallel to the triangle
3083     * @param intersectionPoint
3084     *              the point of intersection
3085     * @return <code>true</code> if the given line segment intersects the triangle; <code>false</code> otherwise
3086     */
3087 public static bool intersectLineSegmentTriangle(double p0X, double p0Y, double p0Z, double p1X, double p1Y, double p1Z,
3088         double v0X, double v0Y, double v0Z, double v1X, double v1Y, double v1Z, double v2X, double v2Y, double v2Z,
3089         double epsilon, Vector3d intersectionPoint) {
3090     double dirX = p1X - p0X;
3091     double dirY = p1Y - p0Y;
3092     double dirZ = p1Z - p0Z;
3093     double t = intersectRayTriangle(p0X, p0Y, p0Z, dirX, dirY, dirZ, v0X, v0Y, v0Z, v1X, v1Y, v1Z, v2X, v2Y, v2Z, epsilon);
3094     if (t >= 0.0 && t <= 1.0) {
3095         intersectionPoint.x = p0X + dirX * t;
3096         intersectionPoint.y = p0Y + dirY * t;
3097         intersectionPoint.z = p0Z + dirZ * t;
3098         return true;
3099     }
3100     return false;
3101 }
3102 
3103 /**
3104     * Determine whether the line segment with the end points <code>p0</code> and <code>p1</code>
3105     * intersects the triangle consisting of the three vertices <code>(v0X, v0Y, v0Z)</code>, <code>(v1X, v1Y, v1Z)</code> and <code>(v2X, v2Y, v2Z)</code>,
3106     * regardless of the winding order of the triangle or the direction of the line segment between its two end points,
3107     * and return the point of intersection.
3108     * <p>
3109     * Reference: <a href="http://www.graphics.cornell.edu/pubs/1997/MT97.pdf">
3110     * Fast, Minimum Storage Ray/Triangle Intersection</a>
3111     * 
3112     * @see #intersectLineSegmentTriangle(double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, Vector3d)
3113     * 
3114     * @param p0
3115     *              the line segment's first end point
3116     * @param p1
3117     *              the line segment's second end point
3118     * @param v0
3119     *              the position of the first vertex
3120     * @param v1
3121     *              the position of the second vertex
3122     * @param v2
3123     *              the position of the third vertex
3124     * @param epsilon
3125     *              a small epsilon when testing line segments that are almost parallel to the triangle
3126     * @param intersectionPoint
3127     *              the point of intersection
3128     * @return <code>true</code> if the given line segment intersects the triangle; <code>false</code> otherwise
3129     */
3130 public static bool intersectLineSegmentTriangle(Vector3d p0, Vector3d p1, Vector3d v0, Vector3d v1, Vector3d v2, double epsilon, Vector3d intersectionPoint) {
3131     return intersectLineSegmentTriangle(p0.x, p0.y, p0.z, p1.x, p1.y, p1.z, v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, epsilon, intersectionPoint);
3132 }
3133 
3134 /**
3135     * Determine whether the line segment with the end points <code>(p0X, p0Y, p0Z)</code> and <code>(p1X, p1Y, p1Z)</code>
3136     * intersects the plane given as the general plane equation <i>a*x + b*y + c*z + d = 0</i>,
3137     * and return the point of intersection.
3138     * 
3139     * @param p0X
3140     *              the x coordinate of the line segment's first end point
3141     * @param p0Y
3142     *              the y coordinate of the line segment's first end point
3143     * @param p0Z
3144     *              the z coordinate of the line segment's first end point
3145     * @param p1X
3146     *              the x coordinate of the line segment's second end point
3147     * @param p1Y
3148     *              the y coordinate of the line segment's second end point
3149     * @param p1Z
3150     *              the z coordinate of the line segment's second end point
3151     * @param a
3152     *              the x factor in the plane equation
3153     * @param b
3154     *              the y factor in the plane equation
3155     * @param c
3156     *              the z factor in the plane equation
3157     * @param d
3158     *              the constant in the plane equation
3159     * @param intersectionPoint
3160     *              the point of intersection
3161     * @return <code>true</code> if the given line segment intersects the plane; <code>false</code> otherwise
3162     */
3163 public static bool intersectLineSegmentPlane(double p0X, double p0Y, double p0Z, double p1X, double p1Y, double p1Z,
3164         double a, double b, double c, double d, Vector3d intersectionPoint) {
3165     double dirX = p1X - p0X;
3166     double dirY = p1Y - p0Y;
3167     double dirZ = p1Z - p0Z;
3168     double denom = a * dirX + b * dirY + c * dirZ;
3169     double t = -(a * p0X + b * p0Y + c * p0Z + d) / denom;
3170     if (t >= 0.0 && t <= 1.0) {
3171         intersectionPoint.x = p0X + t * dirX;
3172         intersectionPoint.y = p0Y + t * dirY;
3173         intersectionPoint.z = p0Z + t * dirZ;
3174         return true;
3175     }
3176     return false;
3177 }
3178 
3179 /**
3180     * Test whether the line with the general line equation <i>a*x + b*y + c = 0</i> intersects the circle with center
3181     * <code>(centerX, centerY)</code> and <code>radius</code>.
3182     * <p>
3183     * Reference: <a href="http://math.stackexchange.com/questions/943383/determine-circle-of-intersection-of-plane-and-sphere">http://math.stackexchange.com</a>
3184     *
3185     * @param a
3186     *          the x factor in the line equation
3187     * @param b
3188     *          the y factor in the line equation
3189     * @param c
3190     *          the constant in the line equation
3191     * @param centerX
3192     *          the x coordinate of the circle's center
3193     * @param centerY
3194     *          the y coordinate of the circle's center
3195     * @param radius
3196     *          the radius of the circle
3197     * @return <code>true</code> iff the line intersects the circle; <code>false</code> otherwise
3198     */
3199 public static bool testLineCircle(double a, double b, double c, double centerX, double centerY, double radius) {
3200     double denom = Math.sqrt(a * a + b * b);
3201     double dist = (a * centerX + b * centerY + c) / denom;
3202     return -radius <= dist && dist <= radius;
3203 }
3204 
3205 /**
3206     * Test whether the line with the general line equation <i>a*x + b*y + c = 0</i> intersects the circle with center
3207     * <code>(centerX, centerY)</code> and <code>radius</code>, and store the center of the line segment of
3208     * intersection in the <code>(x, y)</code> components of the supplied vector and the half-length of that line segment in the z component.
3209     * <p>
3210     * Reference: <a href="http://math.stackexchange.com/questions/943383/determine-circle-of-intersection-of-plane-and-sphere">http://math.stackexchange.com</a>
3211     *
3212     * @param a
3213     *          the x factor in the line equation
3214     * @param b
3215     *          the y factor in the line equation
3216     * @param c
3217     *          the constant in the line equation
3218     * @param centerX
3219     *          the x coordinate of the circle's center
3220     * @param centerY
3221     *          the y coordinate of the circle's center
3222     * @param radius
3223     *          the radius of the circle
3224     * @param intersectionCenterAndHL
3225     *          will hold the center of the line segment of intersection in the <code>(x, y)</code> components and the half-length in the z component
3226     * @return <code>true</code> iff the line intersects the circle; <code>false</code> otherwise
3227     */
3228 public static bool intersectLineCircle(double a, double b, double c, double centerX, double centerY, double radius, Vector3d intersectionCenterAndHL) {
3229     double invDenom = Math.invsqrt(a * a + b * b);
3230     double dist = (a * centerX + b * centerY + c) * invDenom;
3231     if (-radius <= dist && dist <= radius) {
3232         intersectionCenterAndHL.x = centerX + dist * a * invDenom;
3233         intersectionCenterAndHL.y = centerY + dist * b * invDenom;
3234         intersectionCenterAndHL.z = Math.sqrt(radius * radius - dist * dist);
3235         return true;
3236     }
3237     return false;
3238 }
3239 
3240 /**
3241     * Test whether the line defined by the two points <code>(x0, y0)</code> and <code>(x1, y1)</code> intersects the circle with center
3242     * <code>(centerX, centerY)</code> and <code>radius</code>, and store the center of the line segment of
3243     * intersection in the <code>(x, y)</code> components of the supplied vector and the half-length of that line segment in the z component.
3244     * <p>
3245     * Reference: <a href="http://math.stackexchange.com/questions/943383/determine-circle-of-intersection-of-plane-and-sphere">http://math.stackexchange.com</a>
3246     *
3247     * @param x0
3248     *          the x coordinate of the first point on the line
3249     * @param y0
3250     *          the y coordinate of the first point on the line
3251     * @param x1
3252     *          the x coordinate of the second point on the line
3253     * @param y1
3254     *          the y coordinate of the second point on the line
3255     * @param centerX
3256     *          the x coordinate of the circle's center
3257     * @param centerY
3258     *          the y coordinate of the circle's center
3259     * @param radius
3260     *          the radius of the circle
3261     * @param intersectionCenterAndHL
3262     *          will hold the center of the line segment of intersection in the <code>(x, y)</code> components and the half-length in the z component
3263     * @return <code>true</code> iff the line intersects the circle; <code>false</code> otherwise
3264     */
3265 public static bool intersectLineCircle(double x0, double y0, double x1, double y1, double centerX, double centerY, double radius, Vector3d intersectionCenterAndHL) {
3266     // Build general line equation from two points and use the other method
3267     return intersectLineCircle(y0 - y1, x1 - x0, (x0 - x1) * y0 + (y1 - y0) * x0, centerX, centerY, radius, intersectionCenterAndHL);
3268 }
3269 
3270 /**
3271     * Test whether the axis-aligned rectangle with minimum corner <code>(minX, minY)</code> and maximum corner <code>(maxX, maxY)</code>
3272     * intersects the line with the general equation <i>a*x + b*y + c = 0</i>.
3273     * <p>
3274     * Reference: <a href="http://www.lighthouse3d.com/tutorials/view-frustum-culling/geometric-approach-testing-boxes-ii/">http://www.lighthouse3d.com</a> ("Geometric Approach - Testing Boxes II")
3275     * 
3276     * @param minX
3277     *          the x coordinate of the minimum corner of the axis-aligned rectangle
3278     * @param minY
3279     *          the y coordinate of the minimum corner of the axis-aligned rectangle
3280     * @param maxX
3281     *          the x coordinate of the maximum corner of the axis-aligned rectangle
3282     * @param maxY
3283     *          the y coordinate of the maximum corner of the axis-aligned rectangle
3284     * @param a
3285     *          the x factor in the line equation
3286     * @param b
3287     *          the y factor in the line equation
3288     * @param c
3289     *          the constant in the plane equation
3290     * @return <code>true</code> iff the axis-aligned rectangle intersects the line; <code>false</code> otherwise
3291     */
3292 public static bool testAarLine(double minX, double minY, double maxX, double maxY, double a, double b, double c) {
3293     double pX, pY, nX, nY;
3294     if (a > 0.0) {
3295         pX = maxX;
3296         nX = minX;
3297     } else {
3298         pX = minX;
3299         nX = maxX;
3300     }
3301     if (b > 0.0) {
3302         pY = maxY;
3303         nY = minY;
3304     } else {
3305         pY = minY;
3306         nY = maxY;
3307     }
3308     double distN = c + a * nX + b * nY;
3309     double distP = c + a * pX + b * pY;
3310     return distN <= 0.0 && distP >= 0.0;
3311 }
3312 
3313 /**
3314     * Test whether the axis-aligned rectangle with minimum corner <code>min</code> and maximum corner <code>max</code>
3315     * intersects the line with the general equation <i>a*x + b*y + c = 0</i>.
3316     * <p>
3317     * Reference: <a href="http://www.lighthouse3d.com/tutorials/view-frustum-culling/geometric-approach-testing-boxes-ii/">http://www.lighthouse3d.com</a> ("Geometric Approach - Testing Boxes II")
3318     * 
3319     * @param min
3320     *          the minimum corner of the axis-aligned rectangle
3321     * @param max
3322     *          the maximum corner of the axis-aligned rectangle
3323     * @param a
3324     *          the x factor in the line equation
3325     * @param b
3326     *          the y factor in the line equation
3327     * @param c
3328     *          the constant in the line equation
3329     * @return <code>true</code> iff the axis-aligned rectangle intersects the line; <code>false</code> otherwise
3330     */
3331 public static bool testAarLine(Vector2d min, Vector2d max, double a, double b, double c) {
3332     return testAarLine(min.x, min.y, max.x, max.y, a, b, c);
3333 }
3334 
3335 /**
3336     * Test whether the axis-aligned rectangle with minimum corner <code>(minX, minY)</code> and maximum corner <code>(maxX, maxY)</code>
3337     * intersects the line defined by the two points <code>(x0, y0)</code> and <code>(x1, y1)</code>.
3338     * <p>
3339     * Reference: <a href="http://www.lighthouse3d.com/tutorials/view-frustum-culling/geometric-approach-testing-boxes-ii/">http://www.lighthouse3d.com</a> ("Geometric Approach - Testing Boxes II")
3340     * 
3341     * @param minX
3342     *          the x coordinate of the minimum corner of the axis-aligned rectangle
3343     * @param minY
3344     *          the y coordinate of the minimum corner of the axis-aligned rectangle
3345     * @param maxX
3346     *          the x coordinate of the maximum corner of the axis-aligned rectangle
3347     * @param maxY
3348     *          the y coordinate of the maximum corner of the axis-aligned rectangle
3349     * @param x0
3350     *          the x coordinate of the first point on the line
3351     * @param y0
3352     *          the y coordinate of the first point on the line
3353     * @param x1
3354     *          the x coordinate of the second point on the line
3355     * @param y1
3356     *          the y coordinate of the second point on the line
3357     * @return <code>true</code> iff the axis-aligned rectangle intersects the line; <code>false</code> otherwise
3358     */
3359 public static bool testAarLine(double minX, double minY, double maxX, double maxY, double x0, double y0, double x1, double y1) {
3360     double a = y0 - y1;
3361     double b = x1 - x0;
3362     double c = -b * y0 - a * x0;
3363     return testAarLine(minX, minY, maxX, maxY, a, b, c);
3364 }
3365 
3366 /**
3367     * Test whether the axis-aligned rectangle with minimum corner <code>(minXA, minYA)</code> and maximum corner <code>(maxXA, maxYA)</code>
3368     * intersects the axis-aligned rectangle with minimum corner <code>(minXB, minYB)</code> and maximum corner <code>(maxXB, maxYB)</code>.
3369     * 
3370     * @param minXA
3371     *              the x coordinate of the minimum corner of the first axis-aligned rectangle
3372     * @param minYA
3373     *              the y coordinate of the minimum corner of the first axis-aligned rectangle
3374     * @param maxXA
3375     *              the x coordinate of the maximum corner of the first axis-aligned rectangle
3376     * @param maxYA
3377     *              the y coordinate of the maximum corner of the first axis-aligned rectangle
3378     * @param minXB
3379     *              the x coordinate of the minimum corner of the second axis-aligned rectangle
3380     * @param minYB
3381     *              the y coordinate of the minimum corner of the second axis-aligned rectangle
3382     * @param maxXB
3383     *              the x coordinate of the maximum corner of the second axis-aligned rectangle
3384     * @param maxYB
3385     *              the y coordinate of the maximum corner of the second axis-aligned rectangle
3386     * @return <code>true</code> iff both axis-aligned rectangles intersect; <code>false</code> otherwise
3387     */
3388 public static bool testAarAar(double minXA, double minYA, double maxXA, double maxYA, double minXB, double minYB, double maxXB, double maxYB) {
3389     return maxXA >= minXB && maxYA >= minYB &&  minXA <= maxXB && minYA <= maxYB;
3390 }
3391 
3392 /**
3393     * Test whether the axis-aligned rectangle with minimum corner <code>minA</code> and maximum corner <code>maxA</code>
3394     * intersects the axis-aligned rectangle with minimum corner <code>minB</code> and maximum corner <code>maxB</code>.
3395     * 
3396     * @param minA
3397     *              the minimum corner of the first axis-aligned rectangle
3398     * @param maxA
3399     *              the maximum corner of the first axis-aligned rectangle
3400     * @param minB
3401     *              the minimum corner of the second axis-aligned rectangle
3402     * @param maxB
3403     *              the maximum corner of the second axis-aligned rectangle
3404     * @return <code>true</code> iff both axis-aligned rectangles intersect; <code>false</code> otherwise
3405     */
3406 public static bool testAarAar(Vector2d minA, Vector2d maxA, Vector2d minB, Vector2d maxB) {
3407     return testAarAar(minA.x, minA.y, maxA.x, maxA.y, minB.x, minB.y, maxB.x, maxB.y);
3408 }
3409 
3410 /**
3411     * Test whether a given circle with center <code>(aX, aY)</code> and radius <code>aR</code> and travelled distance vector <code>(maX, maY)</code>
3412     * intersects a given static circle with center <code>(bX, bY)</code> and radius <code>bR</code>.
3413     * <p>
3414     * Note that the case of two moving circles can always be reduced to this case by expressing the moved distance of one of the circles relative
3415     * to the other.
3416     * <p>
3417     * Reference: <a href="https://www.gamasutra.com/view/feature/131424/pool_hall_lessons_fast_accurate_.php?page=2">https://www.gamasutra.com</a>
3418     * 
3419     * @param aX
3420     *              the x coordinate of the first circle's center
3421     * @param aY
3422     *              the y coordinate of the first circle's center
3423     * @param maX
3424     *              the x coordinate of the first circle's travelled distance vector
3425     * @param maY
3426     *              the y coordinate of the first circle's travelled distance vector
3427     * @param aR
3428     *              the radius of the first circle
3429     * @param bX
3430     *              the x coordinate of the second circle's center
3431     * @param bY
3432     *              the y coordinate of the second circle's center
3433     * @param bR
3434     *              the radius of the second circle
3435     * @return <code>true</code> if both circle intersect; <code>false</code> otherwise
3436     */
3437 public static bool testMovingCircleCircle(double aX, double aY, double maX, double maY, double aR, double bX, double bY, double bR) {
3438     double aRbR = aR + bR;
3439     double dist = Math.sqrt((aX - bX) * (aX - bX) + (aY - bY) * (aY - bY)) - aRbR;
3440     double mLen = Math.sqrt(maX * maX + maY * maY);
3441     if (mLen < dist)
3442         return false;
3443     double invMLen = 1.0 / mLen;
3444     double nX = maX * invMLen;
3445     double nY = maY * invMLen;
3446     double cX = bX - aX;
3447     double cY = bY - aY;
3448     double nDotC = nX * cX + nY * cY;
3449     if (nDotC <= 0.0)
3450         return false;
3451     double cLen = Math.sqrt(cX * cX + cY * cY);
3452     double cLenNdotC = cLen * cLen - nDotC * nDotC;
3453     double aRbR2 = aRbR * aRbR;
3454     if (cLenNdotC >= aRbR2)
3455         return false;
3456     double t = aRbR2 - cLenNdotC;
3457     if (t < 0.0)
3458         return false;
3459     double distance = nDotC - Math.sqrt(t);
3460     double mag = mLen;
3461     if (mag < distance)
3462         return false;
3463     return true;
3464 }
3465 
3466 /**
3467     * Test whether a given circle with center <code>centerA</code> and radius <code>aR</code> and travelled distance vector <code>moveA</code>
3468     * intersects a given static circle with center <code>centerB</code> and radius <code>bR</code>.
3469     * <p>
3470     * Note that the case of two moving circles can always be reduced to this case by expressing the moved distance of one of the circles relative
3471     * to the other.
3472     * <p>
3473     * Reference: <a href="https://www.gamasutra.com/view/feature/131424/pool_hall_lessons_fast_accurate_.php?page=2">https://www.gamasutra.com</a>
3474     * 
3475     * @param centerA
3476     *              the coordinates of the first circle's center
3477     * @param moveA
3478     *              the coordinates of the first circle's travelled distance vector
3479     * @param aR
3480     *              the radius of the first circle
3481     * @param centerB
3482     *              the coordinates of the second circle's center
3483     * @param bR
3484     *              the radius of the second circle
3485     * @return <code>true</code> if both circle intersect; <code>false</code> otherwise
3486     */
3487 public static bool testMovingCircleCircle(Vector2d centerA, Vector2d moveA, double aR, Vector2d centerB, double bR) {
3488     return testMovingCircleCircle(centerA.x, centerA.y, moveA.x, moveA.y, aR, centerB.x, centerB.y, bR);
3489 }
3490 
3491 /**
3492     * Test whether the one circle with center <code>(aX, aY)</code> and square radius <code>radiusSquaredA</code> intersects the other
3493     * circle with center <code>(bX, bY)</code> and square radius <code>radiusSquaredB</code>, and store the center of the line segment of
3494     * intersection in the <code>(x, y)</code> components of the supplied vector and the half-length of that line segment in the z component.
3495     * <p>
3496     * This method returns <code>false</code> when one circle contains the other circle.
3497     * <p>
3498     * Reference: <a href="http://gamedev.stackexchange.com/questions/75756/sphere-sphere-intersection-and-circle-sphere-intersection">http://gamedev.stackexchange.com</a>
3499     * 
3500     * @param aX
3501     *              the x coordinate of the first circle's center
3502     * @param aY
3503     *              the y coordinate of the first circle's center
3504     * @param radiusSquaredA
3505     *              the square of the first circle's radius
3506     * @param bX
3507     *              the x coordinate of the second circle's center
3508     * @param bY
3509     *              the y coordinate of the second circle's center
3510     * @param radiusSquaredB
3511     *              the square of the second circle's radius
3512     * @param intersectionCenterAndHL
3513     *              will hold the center of the circle of intersection in the <code>(x, y, z)</code> components and the radius in the w component
3514     * @return <code>true</code> iff both circles intersect; <code>false</code> otherwise
3515     */
3516 public static bool intersectCircleCircle(double aX, double aY, double radiusSquaredA, double bX, double bY, double radiusSquaredB, Vector3d intersectionCenterAndHL) {
3517     double dX = bX - aX, dY = bY - aY;
3518     double distSquared = dX * dX + dY * dY;
3519     double h = 0.5 + (radiusSquaredA - radiusSquaredB) / distSquared;
3520     double r_i = Math.sqrt(radiusSquaredA - h * h * distSquared);
3521     if (r_i >= 0.0) {
3522         intersectionCenterAndHL.x = aX + h * dX;
3523         intersectionCenterAndHL.y = aY + h * dY;
3524         intersectionCenterAndHL.z = r_i;
3525         return true;
3526     }
3527     return false;
3528 }
3529 
3530 /**
3531     * Test whether the one circle with center <code>centerA</code> and square radius <code>radiusSquaredA</code> intersects the other
3532     * circle with center <code>centerB</code> and square radius <code>radiusSquaredB</code>, and store the center of the line segment of
3533     * intersection in the <code>(x, y)</code> components of the supplied vector and the half-length of that line segment in the z component.
3534     * <p>
3535     * This method returns <code>false</code> when one circle contains the other circle.
3536     * <p>
3537     * Reference: <a href="http://gamedev.stackexchange.com/questions/75756/sphere-sphere-intersection-and-circle-sphere-intersection">http://gamedev.stackexchange.com</a>
3538     * 
3539     * @param centerA
3540     *              the first circle's center
3541     * @param radiusSquaredA
3542     *              the square of the first circle's radius
3543     * @param centerB
3544     *              the second circle's center
3545     * @param radiusSquaredB
3546     *              the square of the second circle's radius
3547     * @param intersectionCenterAndHL
3548     *              will hold the center of the line segment of intersection in the <code>(x, y)</code> components and the half-length in the z component
3549     * @return <code>true</code> iff both circles intersect; <code>false</code> otherwise
3550     */
3551 public static bool intersectCircleCircle(Vector2d centerA, double radiusSquaredA, Vector2d centerB, double radiusSquaredB, Vector3d intersectionCenterAndHL) {
3552     return intersectCircleCircle(centerA.x, centerA.y, radiusSquaredA, centerB.x, centerB.y, radiusSquaredB, intersectionCenterAndHL);
3553 }
3554 
3555 /**
3556     * Test whether the one circle with center <code>(aX, aY)</code> and radius <code>rA</code> intersects the other circle with center <code>(bX, bY)</code> and radius <code>rB</code>.
3557     * <p>
3558     * This method returns <code>true</code> when one circle contains the other circle.
3559     * <p>
3560     * Reference: <a href="http://math.stackexchange.com/questions/275514/two-circles-overlap">http://math.stackexchange.com/</a>
3561     * 
3562     * @param aX
3563     *              the x coordinate of the first circle's center
3564     * @param aY
3565     *              the y coordinate of the first circle's center
3566     * @param rA
3567     *              the square of the first circle's radius
3568     * @param bX
3569     *              the x coordinate of the second circle's center
3570     * @param bY
3571     *              the y coordinate of the second circle's center
3572     * @param rB
3573     *              the square of the second circle's radius
3574     * @return <code>true</code> iff both circles intersect; <code>false</code> otherwise
3575     */
3576 public static bool testCircleCircle(double aX, double aY, double rA, double bX, double bY, double rB) {
3577     double d = (aX - bX) * (aX - bX) + (aY - bY) * (aY - bY);
3578     return d <= (rA + rB) * (rA + rB);
3579 }
3580 
3581 /**
3582     * Test whether the one circle with center <code>centerA</code> and square radius <code>radiusSquaredA</code> intersects the other
3583     * circle with center <code>centerB</code> and square radius <code>radiusSquaredB</code>.
3584     * <p>
3585     * This method returns <code>true</code> when one circle contains the other circle.
3586     * <p>
3587     * Reference: <a href="http://gamedev.stackexchange.com/questions/75756/sphere-sphere-intersection-and-circle-sphere-intersection">http://gamedev.stackexchange.com</a>
3588     * 
3589     * @param centerA
3590     *              the first circle's center
3591     * @param radiusSquaredA
3592     *              the square of the first circle's radius
3593     * @param centerB
3594     *              the second circle's center
3595     * @param radiusSquaredB
3596     *              the square of the second circle's radius
3597     * @return <code>true</code> iff both circles intersect; <code>false</code> otherwise
3598     */
3599 public static bool testCircleCircle(Vector2d centerA, double radiusSquaredA, Vector2d centerB, double radiusSquaredB) {
3600     return testCircleCircle(centerA.x, centerA.y, radiusSquaredA, centerB.x, centerB.y, radiusSquaredB);
3601 }
3602 
3603 /**
3604     * Determine the signed distance of the given point <code>(pointX, pointY)</code> to the line specified via its general plane equation
3605     * <i>a*x + b*y + c = 0</i>.
3606     * <p>
3607     * Reference: <a href="http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html">http://mathworld.wolfram.com</a>
3608     * 
3609     * @param pointX
3610     *              the x coordinate of the point
3611     * @param pointY
3612     *              the y coordinate of the point
3613     * @param a
3614     *              the x factor in the plane equation
3615     * @param b
3616     *              the y factor in the plane equation
3617     * @param c
3618     *              the constant in the plane equation
3619     * @return the distance between the point and the line
3620     */
3621 public static double distancePointLine(double pointX, double pointY, double a, double b, double c) {
3622     double denom = Math.sqrt(a * a + b * b);
3623     return (a * pointX + b * pointY + c) / denom;
3624 }
3625 
3626 /**
3627     * Determine the signed distance of the given point <code>(pointX, pointY)</code> to the line defined by the two points <code>(x0, y0)</code> and <code>(x1, y1)</code>.
3628     * <p>
3629     * Reference: <a href="http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html">http://mathworld.wolfram.com</a>
3630     * 
3631     * @param pointX
3632     *              the x coordinate of the point
3633     * @param pointY
3634     *              the y coordinate of the point
3635     * @param x0
3636     *              the x coordinate of the first point on the line
3637     * @param y0
3638     *              the y coordinate of the first point on the line
3639     * @param x1
3640     *              the x coordinate of the second point on the line
3641     * @param y1
3642     *              the y coordinate of the second point on the line
3643     * @return the distance between the point and the line
3644     */
3645 public static double distancePointLine(double pointX, double pointY, double x0, double y0, double x1, double y1) {
3646     double dx = x1 - x0;
3647     double dy = y1 - y0;
3648     double denom = Math.sqrt(dx * dx + dy * dy);
3649     return (dx * (y0 - pointY) - (x0 - pointX) * dy) / denom;
3650 }
3651 
3652 /**
3653     * Compute the distance of the given point <code>(pX, pY, pZ)</code> to the line defined by the two points <code>(x0, y0, z0)</code> and <code>(x1, y1, z1)</code>.
3654     * <p>
3655     * Reference: <a href="http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html">http://mathworld.wolfram.com</a>
3656     * 
3657     * @param pX
3658     *          the x coordinate of the point
3659     * @param pY
3660     *          the y coordinate of the point
3661     * @param pZ
3662     *          the z coordinate of the point
3663     * @param x0
3664     *          the x coordinate of the first point on the line
3665     * @param y0
3666     *          the y coordinate of the first point on the line
3667     * @param z0
3668     *          the z coordinate of the first point on the line
3669     * @param x1
3670     *          the x coordinate of the second point on the line
3671     * @param y1
3672     *          the y coordinate of the second point on the line
3673     * @param z1
3674     *          the z coordinate of the second point on the line
3675     * @return the distance between the point and the line
3676     */
3677 public static double distancePointLine(double pX, double pY, double pZ, 
3678         double x0, double y0, double z0, double x1, double y1, double z1) {
3679     double d21x = x1 - x0, d21y = y1 - y0, d21z = z1 - z0;
3680     double d10x = x0 - pX, d10y = y0 - pY, d10z = z0 - pZ;
3681     double cx = d21y * d10z - d21z * d10y, cy = d21z * d10x - d21x * d10z, cz = d21x * d10y - d21y * d10x;
3682     return Math.sqrt((cx*cx + cy*cy + cz*cz) / (d21x*d21x + d21y*d21y + d21z*d21z));
3683 }
3684 
3685 /**
3686     * Test whether the ray with given origin <code>(originX, originY)</code> and direction <code>(dirX, dirY)</code> intersects the line
3687     * containing the given point <code>(pointX, pointY)</code> and having the normal <code>(normalX, normalY)</code>, and return the
3688     * value of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> of the intersection point.
3689     * <p>
3690     * This method returns <code>-1.0</code> if the ray does not intersect the line, because it is either parallel to the line or its direction points
3691     * away from the line or the ray's origin is on the <i>negative</i> side of the line (i.e. the line's normal points away from the ray's origin).
3692     * 
3693     * @param originX
3694     *              the x coordinate of the ray's origin
3695     * @param originY
3696     *              the y coordinate of the ray's origin
3697     * @param dirX
3698     *              the x coordinate of the ray's direction
3699     * @param dirY
3700     *              the y coordinate of the ray's direction
3701     * @param pointX
3702     *              the x coordinate of a point on the line
3703     * @param pointY
3704     *              the y coordinate of a point on the line
3705     * @param normalX
3706     *              the x coordinate of the line's normal
3707     * @param normalY
3708     *              the y coordinate of the line's normal
3709     * @param epsilon
3710     *              some small epsilon for when the ray is parallel to the line
3711     * @return the value of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> of the intersection point, if the ray
3712     *         intersects the line; <code>-1.0</code> otherwise
3713     */
3714 public static double intersectRayLine(double originX, double originY, double dirX, double dirY, double pointX, double pointY, double normalX, double normalY, double epsilon) {
3715     double denom = normalX * dirX + normalY * dirY;
3716     if (denom < epsilon) {
3717         double t = ((pointX - originX) * normalX + (pointY - originY) * normalY) / denom;
3718         if (t >= 0.0)
3719             return t;
3720     }
3721     return -1.0;
3722 }
3723 
3724 /**
3725     * Test whether the ray with given <code>origin</code> and direction <code>dir</code> intersects the line
3726     * containing the given <code>point</code> and having the given <code>normal</code>, and return the
3727     * value of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> of the intersection point.
3728     * <p>
3729     * This method returns <code>-1.0</code> if the ray does not intersect the line, because it is either parallel to the line or its direction points
3730     * away from the line or the ray's origin is on the <i>negative</i> side of the line (i.e. the line's normal points away from the ray's origin).
3731     * 
3732     * @param origin
3733     *              the ray's origin
3734     * @param dir
3735     *              the ray's direction
3736     * @param point
3737     *              a point on the line
3738     * @param normal
3739     *              the line's normal
3740     * @param epsilon
3741     *              some small epsilon for when the ray is parallel to the line
3742     * @return the value of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> of the intersection point, if the ray
3743     *         intersects the line; <code>-1.0</code> otherwise
3744     */
3745 public static double intersectRayLine(Vector2d origin, Vector2d dir, Vector2d point, Vector2d normal, double epsilon) {
3746     return intersectRayLine(origin.x, origin.y, dir.x, dir.y, point.x, point.y, normal.x, normal.y, epsilon);
3747 }
3748 
3749 /**
3750     * Determine whether the ray with given origin <code>(originX, originY)</code> and direction <code>(dirX, dirY)</code> intersects the undirected line segment
3751     * given by the two end points <code>(aX, bY)</code> and <code>(bX, bY)</code>, and return the value of the parameter <i>t</i> in the ray equation
3752     * <i>p(t) = origin + t * dir</i> of the intersection point, if any.
3753     * <p>
3754     * This method returns <code>-1.0</code> if the ray does not intersect the line segment.
3755     * 
3756     * @see #intersectRayLineSegment(Vector2d, Vector2d, Vector2d, Vector2d)
3757     * 
3758     * @param originX
3759     *              the x coordinate of the ray's origin
3760     * @param originY
3761     *              the y coordinate of the ray's origin
3762     * @param dirX
3763     *              the x coordinate of the ray's direction
3764     * @param dirY
3765     *              the y coordinate of the ray's direction
3766     * @param aX
3767     *              the x coordinate of the line segment's first end point
3768     * @param aY
3769     *              the y coordinate of the line segment's first end point
3770     * @param bX
3771     *              the x coordinate of the line segment's second end point
3772     * @param bY
3773     *              the y coordinate of the line segment's second end point
3774     * @return the value of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> of the intersection point, if the ray
3775     *         intersects the line segment; <code>-1.0</code> otherwise
3776     */
3777 public static double intersectRayLineSegment(double originX, double originY, double dirX, double dirY, double aX, double aY, double bX, double bY) {
3778     double v1X = originX - aX;
3779     double v1Y = originY - aY;
3780     double v2X = bX - aX;
3781     double v2Y = bY - aY;
3782     double invV23 = 1.0 / (v2Y * dirX - v2X * dirY);
3783     double t1 = (v2X * v1Y - v2Y * v1X) * invV23;
3784     double t2 = (v1Y * dirX - v1X * dirY) * invV23;
3785     if (t1 >= 0.0 && t2 >= 0.0 && t2 <= 1.0)
3786         return t1;
3787     return -1.0;
3788 }
3789 
3790 /**
3791     * Determine whether the ray with given <code>origin</code> and direction <code>dir</code> intersects the undirected line segment
3792     * given by the two end points <code>a</code> and <code>b</code>, and return the value of the parameter <i>t</i> in the ray equation
3793     * <i>p(t) = origin + t * dir</i> of the intersection point, if any.
3794     * <p>
3795     * This method returns <code>-1.0</code> if the ray does not intersect the line segment.
3796     * 
3797     * @see #intersectRayLineSegment(double, double, double, double, double, double, double, double)
3798     * 
3799     * @param origin
3800     *              the ray's origin
3801     * @param dir
3802     *              the ray's direction
3803     * @param a
3804     *              the line segment's first end point
3805     * @param b
3806     *              the line segment's second end point
3807     * @return the value of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> of the intersection point, if the ray
3808     *         intersects the line segment; <code>-1.0</code> otherwise
3809     */
3810 public static double intersectRayLineSegment(Vector2d origin, Vector2d dir, Vector2d a, Vector2d b) {
3811     return intersectRayLineSegment(origin.x, origin.y, dir.x, dir.y, a.x, a.y, b.x, b.y);
3812 }
3813 
3814 /**
3815     * Test whether the axis-aligned rectangle with minimum corner <code>(minX, minY)</code> and maximum corner <code>(maxX, maxY)</code>
3816     * intersects the circle with the given center <code>(centerX, centerY)</code> and square radius <code>radiusSquared</code>.
3817     * <p>
3818     * Reference: <a href="http://stackoverflow.com/questions/4578967/cube-sphere-intersection-test#answer-4579069">http://stackoverflow.com</a>
3819     * 
3820     * @param minX
3821     *          the x coordinate of the minimum corner of the axis-aligned rectangle
3822     * @param minY
3823     *          the y coordinate of the minimum corner of the axis-aligned rectangle
3824     * @param maxX
3825     *          the x coordinate of the maximum corner of the axis-aligned rectangle
3826     * @param maxY
3827     *          the y coordinate of the maximum corner of the axis-aligned rectangle
3828     * @param centerX
3829     *          the x coordinate of the circle's center
3830     * @param centerY
3831     *          the y coordinate of the circle's center
3832     * @param radiusSquared
3833     *          the square of the circle's radius
3834     * @return <code>true</code> iff the axis-aligned rectangle intersects the circle; <code>false</code> otherwise
3835     */
3836 public static bool testAarCircle(double minX, double minY, double maxX, double maxY, double centerX, double centerY, double radiusSquared) {
3837     double radius2 = radiusSquared;
3838     if (centerX < minX) {
3839         double d = (centerX - minX);
3840         radius2 -= d * d;
3841     } else if (centerX > maxX) {
3842         double d = (centerX - maxX);
3843         radius2 -= d * d;
3844     }
3845     if (centerY < minY) {
3846         double d = (centerY - minY);
3847         radius2 -= d * d;
3848     } else if (centerY > maxY) {
3849         double d = (centerY - maxY);
3850         radius2 -= d * d;
3851     }
3852     return radius2 >= 0.0;
3853 }
3854 
3855 /**
3856     * Test whether the axis-aligned rectangle with minimum corner <code>min</code> and maximum corner <code>max</code>
3857     * intersects the circle with the given <code>center</code> and square radius <code>radiusSquared</code>.
3858     * <p>
3859     * Reference: <a href="http://stackoverflow.com/questions/4578967/cube-sphere-intersection-test#answer-4579069">http://stackoverflow.com</a>
3860     * 
3861     * @param min
3862     *          the minimum corner of the axis-aligned rectangle
3863     * @param max
3864     *          the maximum corner of the axis-aligned rectangle
3865     * @param center
3866     *          the circle's center
3867     * @param radiusSquared
3868     *          the squared of the circle's radius
3869     * @return <code>true</code> iff the axis-aligned rectangle intersects the circle; <code>false</code> otherwise
3870     */
3871 public static bool testAarCircle(Vector2d min, Vector2d max, Vector2d center, double radiusSquared) {
3872     return testAarCircle(min.x, min.y, max.x, max.y, center.x, center.y, radiusSquared);
3873 }
3874 
3875 /**
3876     * Determine the closest point on the triangle with the given vertices <code>(v0X, v0Y)</code>, <code>(v1X, v1Y)</code>, <code>(v2X, v2Y)</code>
3877     * between that triangle and the given point <code>(pX, pY)</code> and store that point into the given <code>result</code>.
3878     * <p>
3879     * Additionally, this method returns whether the closest point is a vertex ({@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1}, {@link #POINT_ON_TRIANGLE_VERTEX_2})
3880     * of the triangle, lies on an edge ({@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12}, {@link #POINT_ON_TRIANGLE_EDGE_20})
3881     * or on the {@link #POINT_ON_TRIANGLE_FACE face} of the triangle.
3882     * <p>
3883     * Reference: Book "Real-Time Collision Detection" chapter 5.1.5 "Closest Point on Triangle to Point"
3884     * 
3885     * @param v0X
3886     *          the x coordinate of the first vertex of the triangle
3887     * @param v0Y
3888     *          the y coordinate of the first vertex of the triangle
3889     * @param v1X
3890     *          the x coordinate of the second vertex of the triangle
3891     * @param v1Y
3892     *          the y coordinate of the second vertex of the triangle
3893     * @param v2X
3894     *          the x coordinate of the third vertex of the triangle
3895     * @param v2Y
3896     *          the y coordinate of the third vertex of the triangle
3897     * @param pX
3898     *          the x coordinate of the point
3899     * @param pY
3900     *          the y coordinate of the point
3901     * @param result
3902     *          will hold the closest point
3903     * @return one of {@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1}, {@link #POINT_ON_TRIANGLE_VERTEX_2},
3904     *                {@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12}, {@link #POINT_ON_TRIANGLE_EDGE_20} or
3905     *                {@link #POINT_ON_TRIANGLE_FACE}
3906     */
3907 public static int findClosestPointOnTriangle(double v0X, double v0Y, double v1X, double v1Y, double v2X, double v2Y, double pX, double pY, Vector2d result) {
3908     double abX = v1X - v0X, abY = v1Y - v0Y;
3909     double acX = v2X - v0X, acY = v2Y - v0Y;
3910     double apX = pX - v0X, apY = pY - v0Y;
3911     double d1 = abX * apX + abY * apY;
3912     double d2 = acX * apX + acY * apY;
3913     if (d1 <= 0.0 && d2 <= 0.0) {
3914         result.x = v0X;
3915         result.y = v0Y;
3916         return POINT_ON_TRIANGLE_VERTEX_0;
3917     }
3918     double bpX = pX - v1X, bpY = pY - v1Y;
3919     double d3 = abX * bpX + abY * bpY;
3920     double d4 = acX * bpX + acY * bpY;
3921     if (d3 >= 0.0 && d4 <= d3) {
3922         result.x = v1X;
3923         result.y = v1Y;
3924         return POINT_ON_TRIANGLE_VERTEX_1;
3925     }
3926     double vc = d1 * d4 - d3 * d2;
3927     if (vc <= 0.0 && d1 >= 0.0 && d3 <= 0.0) {
3928         double v = d1 / (d1 - d3);
3929         result.x = v0X + v * abX;
3930         result.y = v0Y + v * abY;
3931         return POINT_ON_TRIANGLE_EDGE_01;
3932     }
3933     double cpX = pX - v2X, cpY = pY - v2Y;
3934     double d5 = abX * cpX + abY * cpY;
3935     double d6 = acX * cpX + acY * cpY;
3936     if (d6 >= 0.0 && d5 <= d6) {
3937         result.x = v2X;
3938         result.y = v2Y;
3939         return POINT_ON_TRIANGLE_VERTEX_2;
3940     }
3941     double vb = d5 * d2 - d1 * d6;
3942     if (vb <= 0.0 && d2 >= 0.0 && d6 <= 0.0) {
3943         double w = d2 / (d2 - d6);
3944         result.x = v0X + w * acX;
3945         result.y = v0Y + w * acY;
3946         return POINT_ON_TRIANGLE_EDGE_20;
3947     }
3948     double va = d3 * d6 - d5 * d4;
3949     if (va <= 0.0 && d4 - d3 >= 0.0 && d5 - d6 >= 0.0) {
3950         double w = (d4 - d3) / (d4 - d3 + d5 - d6);
3951         result.x = v1X + w * (v2X - v1X);
3952         result.y = v1Y + w * (v2Y - v1Y);
3953         return POINT_ON_TRIANGLE_EDGE_12;
3954     }
3955     double denom = 1.0 / (va + vb + vc);
3956     double v = vb * denom;
3957     double w = vc * denom;
3958     result.x = v0X + abX * v + acX * w;
3959     result.y = v0Y + abY * v + acY * w;
3960     return POINT_ON_TRIANGLE_FACE;
3961 }
3962 
3963 /**
3964     * Determine the closest point on the triangle with the vertices <code>v0</code>, <code>v1</code>, <code>v2</code>
3965     * between that triangle and the given point <code>p</code> and store that point into the given <code>result</code>.
3966     * <p>
3967     * Additionally, this method returns whether the closest point is a vertex ({@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1}, {@link #POINT_ON_TRIANGLE_VERTEX_2})
3968     * of the triangle, lies on an edge ({@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12}, {@link #POINT_ON_TRIANGLE_EDGE_20})
3969     * or on the {@link #POINT_ON_TRIANGLE_FACE face} of the triangle.
3970     * <p>
3971     * Reference: Book "Real-Time Collision Detection" chapter 5.1.5 "Closest Point on Triangle to Point"
3972     * 
3973     * @param v0
3974     *          the first vertex of the triangle
3975     * @param v1
3976     *          the second vertex of the triangle
3977     * @param v2
3978     *          the third vertex of the triangle
3979     * @param p
3980     *          the point
3981     * @param result
3982     *          will hold the closest point
3983     * @return one of {@link #POINT_ON_TRIANGLE_VERTEX_0}, {@link #POINT_ON_TRIANGLE_VERTEX_1}, {@link #POINT_ON_TRIANGLE_VERTEX_2},
3984     *                {@link #POINT_ON_TRIANGLE_EDGE_01}, {@link #POINT_ON_TRIANGLE_EDGE_12}, {@link #POINT_ON_TRIANGLE_EDGE_20} or
3985     *                {@link #POINT_ON_TRIANGLE_FACE}
3986     */
3987 public static int findClosestPointOnTriangle(Vector2d v0, Vector2d v1, Vector2d v2, Vector2d p, Vector2d result) {
3988     return findClosestPointOnTriangle(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y, p.x, p.y, result);
3989 }
3990 
3991 /**
3992     * Test whether the given ray with the origin <code>(originX, originY)</code> and direction <code>(dirX, dirY)</code>
3993     * intersects the given circle with center <code>(centerX, centerY)</code> and square radius <code>radiusSquared</code>,
3994     * and store the values of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> for both points (near
3995     * and far) of intersections into the given <code>result</code> vector.
3996     * <p>
3997     * This method returns <code>true</code> for a ray whose origin lies inside the circle.
3998     * <p>
3999     * Reference: <a href="http://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection">http://www.scratchapixel.com/</a>
4000     * 
4001     * @param originX
4002     *              the x coordinate of the ray's origin
4003     * @param originY
4004     *              the y coordinate of the ray's origin
4005     * @param dirX
4006     *              the x coordinate of the ray's direction
4007     * @param dirY
4008     *              the y coordinate of the ray's direction
4009     * @param centerX
4010     *              the x coordinate of the circle's center
4011     * @param centerY
4012     *              the y coordinate of the circle's center
4013     * @param radiusSquared
4014     *              the circle radius squared
4015     * @param result
4016     *              a vector that will contain the values of the parameter <i>t</i> in the ray equation
4017     *              <i>p(t) = origin + t * dir</i> for both points (near, far) of intersections with the circle
4018     * @return <code>true</code> if the ray intersects the circle; <code>false</code> otherwise
4019     */
4020 public static bool intersectRayCircle(double originX, double originY, double dirX, double dirY, 
4021         double centerX, double centerY, double radiusSquared, Vector2d result) {
4022     double Lx = centerX - originX;
4023     double Ly = centerY - originY;
4024     double tca = Lx * dirX + Ly * dirY;
4025     double d2 = Lx * Lx + Ly * Ly - tca * tca;
4026     if (d2 > radiusSquared)
4027         return false;
4028     double thc = Math.sqrt(radiusSquared - d2);
4029     double t0 = tca - thc;
4030     double t1 = tca + thc;
4031     if (t0 < t1 && t1 >= 0.0) {
4032         result.x = t0;
4033         result.y = t1;
4034         return true;
4035     }
4036     return false;
4037 }
4038 
4039 /**
4040     * Test whether the ray with the given <code>origin</code> and direction <code>dir</code>
4041     * intersects the circle with the given <code>center</code> and square radius <code>radiusSquared</code>,
4042     * and store the values of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> for both points (near
4043     * and far) of intersections into the given <code>result</code> vector.
4044     * <p>
4045     * This method returns <code>true</code> for a ray whose origin lies inside the circle.
4046     * <p>
4047     * Reference: <a href="http://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection">http://www.scratchapixel.com/</a>
4048     * 
4049     * @param origin
4050     *              the ray's origin
4051     * @param dir
4052     *              the ray's direction
4053     * @param center
4054     *              the circle's center
4055     * @param radiusSquared
4056     *              the circle radius squared
4057     * @param result
4058     *              a vector that will contain the values of the parameter <i>t</i> in the ray equation
4059     *              <i>p(t) = origin + t * dir</i> for both points (near, far) of intersections with the circle
4060     * @return <code>true</code> if the ray intersects the circle; <code>false</code> otherwise
4061     */
4062 public static bool intersectRayCircle(Vector2d origin, Vector2d dir, Vector2d center, double radiusSquared, Vector2d result) {
4063     return intersectRayCircle(origin.x, origin.y, dir.x, dir.y, center.x, center.y, radiusSquared, result);
4064 }
4065 
4066 /**
4067     * Test whether the given ray with the origin <code>(originX, originY)</code> and direction <code>(dirX, dirY)</code>
4068     * intersects the given circle with center <code>(centerX, centerY)</code> and square radius <code>radiusSquared</code>.
4069     * <p>
4070     * This method returns <code>true</code> for a ray whose origin lies inside the circle.
4071     * <p>
4072     * Reference: <a href="http://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection">http://www.scratchapixel.com/</a>
4073     * 
4074     * @param originX
4075     *              the x coordinate of the ray's origin
4076     * @param originY
4077     *              the y coordinate of the ray's origin
4078     * @param dirX
4079     *              the x coordinate of the ray's direction
4080     * @param dirY
4081     *              the y coordinate of the ray's direction
4082     * @param centerX
4083     *              the x coordinate of the circle's center
4084     * @param centerY
4085     *              the y coordinate of the circle's center
4086     * @param radiusSquared
4087     *              the circle radius squared
4088     * @return <code>true</code> if the ray intersects the circle; <code>false</code> otherwise
4089     */
4090 public static bool testRayCircle(double originX, double originY, double dirX, double dirY, 
4091         double centerX, double centerY, double radiusSquared) {
4092     double Lx = centerX - originX;
4093     double Ly = centerY - originY;
4094     double tca = Lx * dirX + Ly * dirY;
4095     double d2 = Lx * Lx + Ly * Ly - tca * tca;
4096     if (d2 > radiusSquared)
4097         return false;
4098     double thc = Math.sqrt(radiusSquared - d2);
4099     double t0 = tca - thc;
4100     double t1 = tca + thc;
4101     return t0 < t1 && t1 >= 0.0;
4102 }
4103 
4104 /**
4105     * Test whether the ray with the given <code>origin</code> and direction <code>dir</code>
4106     * intersects the circle with the given <code>center</code> and square radius.
4107     * <p>
4108     * This method returns <code>true</code> for a ray whose origin lies inside the circle.
4109     * <p>
4110     * Reference: <a href="http://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection">http://www.scratchapixel.com/</a>
4111     * 
4112     * @param origin
4113     *              the ray's origin
4114     * @param dir
4115     *              the ray's direction
4116     * @param center
4117     *              the circle's center
4118     * @param radiusSquared
4119     *              the circle radius squared
4120     * @return <code>true</code> if the ray intersects the circle; <code>false</code> otherwise
4121     */
4122 public static bool testRayCircle(Vector2d origin, Vector2d dir, Vector2d center, double radiusSquared) {
4123     return testRayCircle(origin.x, origin.y, dir.x, dir.y, center.x, center.y, radiusSquared);
4124 }
4125 
4126 /**
4127     * Determine whether the given ray with the origin <code>(originX, originY)</code> and direction <code>(dirX, dirY)</code>
4128     * intersects the axis-aligned rectangle given as its minimum corner <code>(minX, minY)</code> and maximum corner <code>(maxX, maxY)</code>,
4129     * and return the values of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> of the near and far point of intersection
4130     * as well as the side of the axis-aligned rectangle the ray intersects.
4131     * <p>
4132     * This method also detects an intersection for a ray whose origin lies inside the axis-aligned rectangle.
4133     * <p>
4134     * Reference: <a href="https://dl.acm.org/citation.cfm?id=1198748">An Efficient and Robust Ray–Box Intersection</a>
4135     * 
4136     * @see #intersectRayAar(Vector2d, Vector2d, Vector2d, Vector2d, Vector2d)
4137     * 
4138     * @param originX
4139     *              the x coordinate of the ray's origin
4140     * @param originY
4141     *              the y coordinate of the ray's origin
4142     * @param dirX
4143     *              the x coordinate of the ray's direction
4144     * @param dirY
4145     *              the y coordinate of the ray's direction
4146     * @param minX
4147     *              the x coordinate of the minimum corner of the axis-aligned rectangle
4148     * @param minY
4149     *              the y coordinate of the minimum corner of the axis-aligned rectangle
4150     * @param maxX
4151     *              the x coordinate of the maximum corner of the axis-aligned rectangle
4152     * @param maxY
4153     *              the y coordinate of the maximum corner of the axis-aligned rectangle
4154     * @param result
4155     *              a vector which will hold the values of the parameter <i>t</i> in the ray equation
4156     *              <i>p(t) = origin + t * dir</i> of the near and far point of intersection
4157     * @return the side on which the near intersection occurred as one of
4158     *         {@link #AAR_SIDE_MINX}, {@link #AAR_SIDE_MINY}, {@link #AAR_SIDE_MAXX} or {@link #AAR_SIDE_MAXY};
4159     *         or <code>-1</code> if the ray does not intersect the axis-aligned rectangle;
4160     */
4161 public static int intersectRayAar(double originX, double originY, double dirX, double dirY, 
4162         double minX, double minY, double maxX, double maxY, Vector2d result) {
4163     double invDirX = 1.0 / dirX, invDirY = 1.0 / dirY;
4164     double tNear, tFar, tymin, tymax;
4165     if (invDirX >= 0.0) {
4166         tNear = (minX - originX) * invDirX;
4167         tFar = (maxX - originX) * invDirX;
4168     } else {
4169         tNear = (maxX - originX) * invDirX;
4170         tFar = (minX - originX) * invDirX;
4171     }
4172     if (invDirY >= 0.0) {
4173         tymin = (minY - originY) * invDirY;
4174         tymax = (maxY - originY) * invDirY;
4175     } else {
4176         tymin = (maxY - originY) * invDirY;
4177         tymax = (minY - originY) * invDirY;
4178     }
4179     if (tNear > tymax || tymin > tFar)
4180         return OUTSIDE;
4181     tNear = tymin > tNear || isNaN(tNear) ? tymin : tNear;
4182     tFar = tymax < tFar || isNaN(tFar) ? tymax : tFar;
4183     int side = -1; // no intersection side
4184     if (tNear < tFar && tFar >= 0.0) {
4185         double px = originX + tNear * dirX;
4186         double py = originY + tNear * dirY;
4187         result.x = tNear;
4188         result.y = tFar;
4189         double daX = Math.abs(px - minX);
4190         double daY = Math.abs(py - minY);
4191         double dbX = Math.abs(px - maxX);
4192         double dbY = Math.abs(py - maxY);
4193         side = 0; // min x coordinate
4194         double min = daX;
4195         if (daY < min) {
4196             min = daY;
4197             side = 1; // min y coordinate
4198         }
4199         if (dbX < min) {
4200             min = dbX;
4201             side = 2; // max xcoordinate
4202         }
4203         if (dbY < min)
4204             side = 3; // max y coordinate
4205     }
4206     return side;
4207 }
4208 
4209 /**
4210     * Determine whether the given ray with the given <code>origin</code> and direction <code>dir</code>
4211     * intersects the axis-aligned rectangle given as its minimum corner <code>min</code> and maximum corner <code>max</code>,
4212     * and return the values of the parameter <i>t</i> in the ray equation <i>p(t) = origin + t * dir</i> of the near and far point of intersection
4213     * as well as the side of the axis-aligned rectangle the ray intersects.
4214     * <p>
4215     * This method also detects an intersection for a ray whose origin lies inside the axis-aligned rectangle.
4216     * <p>
4217     * Reference: <a href="https://dl.acm.org/citation.cfm?id=1198748">An Efficient and Robust Ray–Box Intersection</a>
4218     * 
4219     * @see #intersectRayAar(double, double, double, double, double, double, double, double, Vector2d)
4220     * 
4221     * @param origin
4222     *              the ray's origin
4223     * @param dir
4224     *              the ray's direction
4225     * @param min
4226     *              the minimum corner of the axis-aligned rectangle
4227     * @param max
4228     *              the maximum corner of the axis-aligned rectangle
4229     * @param result
4230     *              a vector which will hold the values of the parameter <i>t</i> in the ray equation
4231     *              <i>p(t) = origin + t * dir</i> of the near and far point of intersection
4232     * @return the side on which the near intersection occurred as one of
4233     *         {@link #AAR_SIDE_MINX}, {@link #AAR_SIDE_MINY}, {@link #AAR_SIDE_MAXX} or {@link #AAR_SIDE_MAXY};
4234     *         or <code>-1</code> if the ray does not intersect the axis-aligned rectangle;
4235     */
4236 public static int intersectRayAar(Vector2d origin, Vector2d dir, Vector2d min, Vector2d max, Vector2d result) {
4237     return intersectRayAar(origin.x, origin.y, dir.x, dir.y, min.x, min.y, max.x, max.y, result);
4238 }
4239 
4240 /**
4241     * Determine whether the undirected line segment with the end points <code>(p0X, p0Y)</code> and <code>(p1X, p1Y)</code>
4242     * intersects the axis-aligned rectangle given as its minimum corner <code>(minX, minY)</code> and maximum corner <code>(maxX, maxY)</code>,
4243     * and store the values of the parameter <i>t</i> in the ray equation <i>p(t) = p0 + t * (p1 - p0)</i> of the near and far point of intersection
4244     * into <code>result</code>.
4245     * <p>
4246     * This method also detects an intersection of a line segment whose either end point lies inside the axis-aligned rectangle.
4247     * <p>
4248     * Reference: <a href="https://dl.acm.org/citation.cfm?id=1198748">An Efficient and Robust Ray–Box Intersection</a>
4249     *
4250     * @see #intersectLineSegmentAar(Vector2d, Vector2d, Vector2d, Vector2d, Vector2d)
4251     * 
4252     * @param p0X
4253     *              the x coordinate of the line segment's first end point
4254     * @param p0Y
4255     *              the y coordinate of the line segment's first end point
4256     * @param p1X
4257     *              the x coordinate of the line segment's second end point
4258     * @param p1Y
4259     *              the y coordinate of the line segment's second end point
4260     * @param minX
4261     *              the x coordinate of the minimum corner of the axis-aligned rectangle
4262     * @param minY
4263     *              the y coordinate of the minimum corner of the axis-aligned rectangle
4264     * @param maxX
4265     *              the x coordinate of the maximum corner of the axis-aligned rectangle
4266     * @param maxY
4267     *              the y coordinate of the maximum corner of the axis-aligned rectangle
4268     * @param result
4269     *              a vector which will hold the values of the parameter <i>t</i> in the ray equation
4270     *              <i>p(t) = p0 + t * (p1 - p0)</i> of the near and far point of intersection
4271     * @return {@link #INSIDE} if the line segment lies completely inside of the axis-aligned rectangle; or
4272     *         {@link #OUTSIDE} if the line segment lies completely outside of the axis-aligned rectangle; or
4273     *         {@link #ONE_INTERSECTION} if one of the end points of the line segment lies inside of the axis-aligned rectangle; or
4274     *         {@link #TWO_INTERSECTION} if the line segment intersects two edges of the axis-aligned rectangle or lies on one edge of the rectangle
4275     */
4276 public static int intersectLineSegmentAar(double p0X, double p0Y, double p1X, double p1Y, 
4277         double minX, double minY, double maxX, double maxY, Vector2d result) {
4278     double dirX = p1X - p0X, dirY = p1Y - p0Y;
4279     double invDirX = 1.0 / dirX, invDirY = 1.0 / dirY;
4280     double tNear, tFar, tymin, tymax;
4281     if (invDirX >= 0.0) {
4282         tNear = (minX - p0X) * invDirX;
4283         tFar = (maxX - p0X) * invDirX;
4284     } else {
4285         tNear = (maxX - p0X) * invDirX;
4286         tFar = (minX - p0X) * invDirX;
4287     }
4288     if (invDirY >= 0.0) {
4289         tymin = (minY - p0Y) * invDirY;
4290         tymax = (maxY - p0Y) * invDirY;
4291     } else {
4292         tymin = (maxY - p0Y) * invDirY;
4293         tymax = (minY - p0Y) * invDirY;
4294     }
4295     if (tNear > tymax || tymin > tFar)
4296         return OUTSIDE;
4297     tNear = tymin > tNear || isNaN(tNear) ? tymin : tNear;
4298     tFar = tymax < tFar || isNaN(tFar) ? tymax : tFar;
4299     int type = OUTSIDE;
4300     if (tNear <= tFar && tNear <= 1.0f && tFar >= 0.0f) {
4301         if (tNear >= 0.0f && tFar > 1.0f) {
4302             tFar = tNear;
4303             type = ONE_INTERSECTION;
4304         } else if (tNear < 0.0f && tFar <= 1.0f) {
4305             tNear = tFar;
4306             type = ONE_INTERSECTION;
4307         } else if (tNear < 0.0f && tFar > 1.0f) {
4308             type = INSIDE;
4309         } else {
4310             type = TWO_INTERSECTION;
4311         }
4312         result.x = tNear;
4313         result.y = tFar;
4314     }
4315     return type;
4316 }
4317 
4318 /**
4319     * Determine whether the undirected line segment with the end points <code>p0</code> and <code>p1</code>
4320     * intersects the axis-aligned rectangle given as its minimum corner <code>min</code> and maximum corner <code>max</code>,
4321     * and store the values of the parameter <i>t</i> in the ray equation <i>p(t) = p0 + t * (p1 - p0)</i> of the near and far point of intersection
4322     * into <code>result</code>.
4323     * <p>
4324     * This method also detects an intersection of a line segment whose either end point lies inside the axis-aligned rectangle.
4325     * <p>
4326     * Reference: <a href="https://dl.acm.org/citation.cfm?id=1198748">An Efficient and Robust Ray–Box Intersection</a>
4327     *
4328     * #see {@link #intersectLineSegmentAar(double, double, double, double, double, double, double, double, Vector2d)}
4329     * 
4330     * @param p0
4331     *              the line segment's first end point
4332     * @param p1
4333     *              the line segment's second end point
4334     * @param min
4335     *              the minimum corner of the axis-aligned rectangle
4336     * @param max
4337     *              the maximum corner of the axis-aligned rectangle
4338     * @param result
4339     *              a vector which will hold the values of the parameter <i>t</i> in the ray equation
4340     *              <i>p(t) = p0 + t * (p1 - p0)</i> of the near and far point of intersection
4341     * @return {@link #INSIDE} if the line segment lies completely inside of the axis-aligned rectangle; or
4342     *         {@link #OUTSIDE} if the line segment lies completely outside of the axis-aligned rectangle; or
4343     *         {@link #ONE_INTERSECTION} if one of the end points of the line segment lies inside of the axis-aligned rectangle; or
4344     *         {@link #TWO_INTERSECTION} if the line segment intersects two edges of the axis-aligned rectangle
4345     */
4346 public static int intersectLineSegmentAar(Vector2d p0, Vector2d p1, Vector2d min, Vector2d max, Vector2d result) {
4347     return intersectLineSegmentAar(p0.x, p0.y, p1.x, p1.y, min.x, min.y, max.x, max.y, result);
4348 }
4349 
4350 /**
4351     * Test whether the given ray with the origin <code>(originX, originY)</code> and direction <code>(dirX, dirY)</code>
4352     * intersects the given axis-aligned rectangle given as its minimum corner <code>(minX, minY)</code> and maximum corner <code>(maxX, maxY)</code>.
4353     * <p>
4354     * This method returns <code>true</code> for a ray whose origin lies inside the axis-aligned rectangle.
4355     * <p>
4356     * Reference: <a href="https://dl.acm.org/citation.cfm?id=1198748">An Efficient and Robust Ray–Box Intersection</a>
4357     * 
4358     * @see #testRayAar(Vector2d, Vector2d, Vector2d, Vector2d)
4359     * 
4360     * @param originX
4361     *              the x coordinate of the ray's origin
4362     * @param originY
4363     *              the y coordinate of the ray's origin
4364     * @param dirX
4365     *              the x coordinate of the ray's direction
4366     * @param dirY
4367     *              the y coordinate of the ray's direction
4368     * @param minX
4369     *          the x coordinate of the minimum corner of the axis-aligned rectangle
4370     * @param minY
4371     *          the y coordinate of the minimum corner of the axis-aligned rectangle
4372     * @param maxX
4373     *          the x coordinate of the maximum corner of the axis-aligned rectangle
4374     * @param maxY
4375     *          the y coordinate of the maximum corner of the axis-aligned rectangle
4376     * @return <code>true</code> if the given ray intersects the axis-aligned rectangle; <code>false</code> otherwise
4377     */
4378 public static bool testRayAar(double originX, double originY, double dirX, double dirY, double minX, double minY, double maxX, double maxY) {
4379     double invDirX = 1.0 / dirX, invDirY = 1.0 / dirY;
4380     double tNear, tFar, tymin, tymax;
4381     if (invDirX >= 0.0) {
4382         tNear = (minX - originX) * invDirX;
4383         tFar = (maxX - originX) * invDirX;
4384     } else {
4385         tNear = (maxX - originX) * invDirX;
4386         tFar = (minX - originX) * invDirX;
4387     }
4388     if (invDirY >= 0.0) {
4389         tymin = (minY - originY) * invDirY;
4390         tymax = (maxY - originY) * invDirY;
4391     } else {
4392         tymin = (maxY - originY) * invDirY;
4393         tymax = (minY - originY) * invDirY;
4394     }
4395     if (tNear > tymax || tymin > tFar)
4396         return false;
4397     tNear = tymin > tNear || isNaN(tNear) ? tymin : tNear;
4398     tFar = tymax < tFar || isNaN(tFar) ? tymax : tFar;
4399     return tNear < tFar && tFar >= 0.0;
4400 }
4401 
4402 /**
4403     * Test whether the ray with the given <code>origin</code> and direction <code>dir</code>
4404     * intersects the given axis-aligned rectangle specified as its minimum corner <code>min</code> and maximum corner <code>max</code>.
4405     * <p>
4406     * This method returns <code>true</code> for a ray whose origin lies inside the axis-aligned rectangle.
4407     * <p>
4408     * Reference: <a href="https://dl.acm.org/citation.cfm?id=1198748">An Efficient and Robust Ray–Box Intersection</a>
4409     * 
4410     * @see #testRayAar(double, double, double, double, double, double, double, double)
4411     * 
4412     * @param origin
4413     *              the ray's origin
4414     * @param dir
4415     *              the ray's direction
4416     * @param min
4417     *              the minimum corner of the axis-aligned rectangle
4418     * @param max
4419     *              the maximum corner of the axis-aligned rectangle
4420     * @return <code>true</code> if the given ray intersects the axis-aligned rectangle; <code>false</code> otherwise
4421     */
4422 public static bool testRayAar(Vector2d origin, Vector2d dir, Vector2d min, Vector2d max) {
4423     return testRayAar(origin.x, origin.y, dir.x, dir.y, min.x, min.y, max.x, max.y);
4424 }
4425 
4426 /**
4427     * Test whether the given point <code>(pX, pY)</code> lies inside the triangle with the vertices <code>(v0X, v0Y)</code>, <code>(v1X, v1Y)</code>, <code>(v2X, v2Y)</code>.
4428     * 
4429     * @param pX
4430     *          the x coordinate of the point
4431     * @param pY
4432     *          the y coordinate of the point
4433     * @param v0X
4434     *          the x coordinate of the first vertex of the triangle
4435     * @param v0Y
4436     *          the y coordinate of the first vertex of the triangle
4437     * @param v1X
4438     *          the x coordinate of the second vertex of the triangle
4439     * @param v1Y
4440     *          the y coordinate of the second vertex of the triangle
4441     * @param v2X
4442     *          the x coordinate of the third vertex of the triangle
4443     * @param v2Y
4444     *          the y coordinate of the third vertex of the triangle
4445     * @return <code>true</code> iff the point lies inside the triangle; <code>false</code> otherwise
4446     */
4447 public static bool testPointTriangle(double pX, double pY, double v0X, double v0Y, double v1X, double v1Y, double v2X, double v2Y) {
4448     bool b1 = (pX - v1X) * (v0Y - v1Y) - (v0X - v1X) * (pY - v1Y) < 0.0;
4449     bool b2 = (pX - v2X) * (v1Y - v2Y) - (v1X - v2X) * (pY - v2Y) < 0.0;
4450     if (b1 != b2)
4451         return false;
4452     bool b3 = (pX - v0X) * (v2Y - v0Y) - (v2X - v0X) * (pY - v0Y) < 0.0;
4453     return b2 == b3;
4454 }
4455 
4456 /**
4457     * Test whether the given <code>point</code> lies inside the triangle with the vertices <code>v0</code>, <code>v1</code>, <code>v2</code>.
4458     * 
4459     * @param v0
4460     *          the first vertex of the triangle
4461     * @param v1
4462     *          the second vertex of the triangle
4463     * @param v2
4464     *          the third vertex of the triangle
4465     * @param point
4466     *          the point
4467     * @return <code>true</code> iff the point lies inside the triangle; <code>false</code> otherwise
4468     */
4469 public static bool testPointTriangle(Vector2d point, Vector2d v0, Vector2d v1, Vector2d v2) {
4470     return testPointTriangle(point.x, point.y, v0.x, v0.y, v1.x, v1.y, v2.x, v2.y);
4471 }
4472 
4473 /**
4474     * Test whether the given point <code>(pX, pY)</code> lies inside the axis-aligned rectangle with the minimum corner <code>(minX, minY)</code>
4475     * and maximum corner <code>(maxX, maxY)</code>.
4476     * 
4477     * @param pX
4478     *          the x coordinate of the point
4479     * @param pY
4480     *          the y coordinate of the point
4481     * @param minX
4482     *          the x coordinate of the minimum corner of the axis-aligned rectangle
4483     * @param minY
4484     *          the y coordinate of the minimum corner of the axis-aligned rectangle
4485     * @param maxX
4486     *          the x coordinate of the maximum corner of the axis-aligned rectangle
4487     * @param maxY
4488     *          the y coordinate of the maximum corner of the axis-aligned rectangle
4489     * @return <code>true</code> iff the point lies inside the axis-aligned rectangle; <code>false</code> otherwise
4490     */
4491 public static bool testPointAar(double pX, double pY, double minX, double minY, double maxX, double maxY) {
4492     return pX >= minX && pY >= minY && pX <= maxX && pY <= maxY;
4493 }
4494 
4495 /**
4496     * Test whether the point <code>(pX, pY)</code> lies inside the circle with center <code>(centerX, centerY)</code> and square radius <code>radiusSquared</code>.
4497     * 
4498     * @param pX
4499     *          the x coordinate of the point
4500     * @param pY
4501     *          the y coordinate of the point
4502     * @param centerX
4503     *          the x coordinate of the circle's center
4504     * @param centerY
4505     *          the y coordinate of the circle's center
4506     * @param radiusSquared
4507     *          the square radius of the circle
4508     * @return <code>true</code> iff the point lies inside the circle; <code>false</code> otherwise
4509     */
4510 public static bool testPointCircle(double pX, double pY, double centerX, double centerY, double radiusSquared) {
4511     double dx = pX - centerX;
4512     double dy = pY - centerY;
4513     double dx2 = dx * dx;
4514     double dy2 = dy * dy;
4515     return dx2 + dy2 <= radiusSquared;
4516 }
4517 
4518 /**
4519     * Test whether the circle with center <code>(centerX, centerY)</code> and square radius <code>radiusSquared</code> intersects the triangle with counter-clockwise vertices
4520     * <code>(v0X, v0Y)</code>, <code>(v1X, v1Y)</code>, <code>(v2X, v2Y)</code>.
4521     * <p>
4522     * The vertices of the triangle must be specified in counter-clockwise order.
4523     * <p>
4524     * Reference: <a href="http://www.phatcode.net/articles.php?id=459">http://www.phatcode.net/</a>
4525     * 
4526     * @param centerX
4527     *          the x coordinate of the circle's center
4528     * @param centerY
4529     *          the y coordinate of the circle's center
4530     * @param radiusSquared
4531     *          the square radius of the circle
4532     * @param v0X
4533     *          the x coordinate of the first vertex of the triangle
4534     * @param v0Y
4535     *          the y coordinate of the first vertex of the triangle
4536     * @param v1X
4537     *          the x coordinate of the second vertex of the triangle
4538     * @param v1Y
4539     *          the y coordinate of the second vertex of the triangle
4540     * @param v2X
4541     *          the x coordinate of the third vertex of the triangle
4542     * @param v2Y
4543     *          the y coordinate of the third vertex of the triangle
4544     * @return <code>true</code> iff the circle intersects the triangle; <code>false</code> otherwise
4545     */
4546 public static bool testCircleTriangle(double centerX, double centerY, double radiusSquared, double v0X, double v0Y, double v1X, double v1Y, double v2X, double v2Y) {
4547     double c1x = centerX - v0X, c1y = centerY - v0Y;
4548     double c1sqr = c1x * c1x + c1y * c1y - radiusSquared;
4549     if (c1sqr <= 0.0)
4550         return true;
4551     double c2x = centerX - v1X, c2y = centerY - v1Y;
4552     double c2sqr = c2x * c2x + c2y * c2y - radiusSquared;
4553     if (c2sqr <= 0.0)
4554         return true;
4555     double c3x = centerX - v2X, c3y = centerY - v2Y;
4556     double c3sqr = c3x * c3x + c3y * c3y - radiusSquared;
4557     if (c3sqr <= 0.0)
4558         return true;
4559     double e1x = v1X - v0X, e1y = v1Y - v0Y;
4560     double e2x = v2X - v1X, e2y = v2Y - v1Y;
4561     double e3x = v0X - v2X, e3y = v0Y - v2Y;
4562     if (e1x * c1y - e1y * c1x >= 0.0 && e2x * c2y - e2y * c2x >= 0.0 && e3x * c3y - e3y * c3x >= 0.0)
4563         return true;
4564     double k = c1x * e1x + c1y * e1y;
4565     if (k >= 0.0) {
4566         double len = e1x * e1x + e1y * e1y;
4567         if (k <= len) {
4568             if (c1sqr * len <= k * k)
4569                 return true;
4570         }
4571     }
4572     k = c2x * e2x + c2y * e2y;
4573     if (k > 0.0) {
4574         double len = e2x * e2x + e2y * e2y;
4575         if (k <= len) {
4576             if (c2sqr * len <= k * k)
4577                 return true;
4578         }
4579     }
4580     k = c3x * e3x + c3y * e3y;
4581     if (k >= 0.0) {
4582         double len = e3x * e3x + e3y * e3y;
4583         if (k < len) {
4584             if (c3sqr * len <= k * k)
4585                 return true;
4586         }
4587     }
4588     return false;
4589 }
4590 
4591 /**
4592     * Test whether the circle with given <code>center</code> and square radius <code>radiusSquared</code> intersects the triangle with counter-clockwise vertices
4593     * <code>v0</code>, <code>v1</code>, <code>v2</code>.
4594     * <p>
4595     * The vertices of the triangle must be specified in counter-clockwise order.
4596     * <p>
4597     * Reference: <a href="http://www.phatcode.net/articles.php?id=459">http://www.phatcode.net/</a>
4598     * 
4599     * @param center
4600     *          the circle's center
4601     * @param radiusSquared
4602     *          the square radius of the circle
4603     * @param v0
4604     *          the first vertex of the triangle
4605     * @param v1
4606     *          the second vertex of the triangle
4607     * @param v2
4608     *          the third vertex of the triangle
4609     * @return <code>true</code> iff the circle intersects the triangle; <code>false</code> otherwise
4610     */
4611 public static bool testCircleTriangle(Vector2d center, double radiusSquared, Vector2d v0, Vector2d v1, Vector2d v2) {
4612     return testCircleTriangle(center.x, center.y, radiusSquared, v0.x, v0.y, v1.x, v1.y, v2.x, v2.y);
4613 }
4614 
4615 /**
4616     * Determine whether the polygon specified by the given sequence of <code>(x, y)</code> coordinate pairs intersects with the ray
4617     * with given origin <code>(originX, originY, originZ)</code> and direction <code>(dirX, dirY, dirZ)</code>, and store the point of intersection
4618     * into the given vector <code>p</code>.
4619     * <p>
4620     * If the polygon intersects the ray, this method returns the index of the polygon edge intersecting the ray, that is, the index of the 
4621     * first vertex of the directed line segment. The second vertex is always that index + 1, modulus the number of polygon vertices.
4622     * 
4623     * @param verticesXY
4624     *          the sequence of <code>(x, y)</code> coordinate pairs of all vertices of the polygon
4625     * @param originX
4626     *          the x coordinate of the ray's origin
4627     * @param originY
4628     *          the y coordinate of the ray's origin
4629     * @param dirX
4630     *          the x coordinate of the ray's direction
4631     * @param dirY
4632     *          the y coordinate of the ray's direction
4633     * @param p
4634     *          will hold the point of intersection
4635     * @return the index of the first vertex of the polygon edge that intersects the ray; or <code>-1</code> if the ray does not intersect the polygon
4636     */
4637 public static int intersectPolygonRay(double[] verticesXY, double originX, double originY, double dirX, double dirY, Vector2d p) {
4638     double nearestT = double.infinity;
4639     int count = cast(int)(verticesXY.length >> 1);
4640     int edgeIndex = -1;
4641     double aX = verticesXY[(count-1)<<1], aY = verticesXY[((count-1)<<1) + 1];
4642     for (int i = 0; i < count; i++) {
4643         double bX = verticesXY[i << 1], bY = verticesXY[(i << 1) + 1];
4644         double doaX = originX - aX, doaY = originY - aY;
4645         double dbaX = bX - aX, dbaY = bY - aY;
4646         double invDbaDir = 1.0 / (dbaY * dirX - dbaX * dirY);
4647         double t = (dbaX * doaY - dbaY * doaX) * invDbaDir;
4648         if (t >= 0.0 && t < nearestT) {
4649             double t2 = (doaY * dirX - doaX * dirY) * invDbaDir;
4650             if (t2 >= 0.0 && t2 <= 1.0) {
4651                 edgeIndex = (i - 1 + count) % count;
4652                 nearestT = t;
4653                 p.x = originX + t * dirX;
4654                 p.y = originY + t * dirY;
4655             }
4656         }
4657         aX = bX;
4658         aY = bY;
4659     }
4660     return edgeIndex;
4661 }
4662 
4663 /**
4664     * Determine whether the polygon specified by the given sequence of <code>vertices</code> intersects with the ray
4665     * with given origin <code>(originX, originY, originZ)</code> and direction <code>(dirX, dirY, dirZ)</code>, and store the point of intersection
4666     * into the given vector <code>p</code>.
4667     * <p>
4668     * If the polygon intersects the ray, this method returns the index of the polygon edge intersecting the ray, that is, the index of the 
4669     * first vertex of the directed line segment. The second vertex is always that index + 1, modulus the number of polygon vertices.
4670     * 
4671     * @param vertices
4672     *          the sequence of <code>(x, y)</code> coordinate pairs of all vertices of the polygon
4673     * @param originX
4674     *          the x coordinate of the ray's origin
4675     * @param originY
4676     *          the y coordinate of the ray's origin
4677     * @param dirX
4678     *          the x coordinate of the ray's direction
4679     * @param dirY
4680     *          the y coordinate of the ray's direction
4681     * @param p
4682     *          will hold the point of intersection
4683     * @return the index of the first vertex of the polygon edge that intersects the ray; or <code>-1</code> if the ray does not intersect the polygon
4684     */
4685 public static int intersectPolygonRay(Vector2d[] vertices, double originX, double originY, double dirX, double dirY, Vector2d p) {
4686     double nearestT = double.infinity;
4687     int count = cast(int)vertices.length;
4688     int edgeIndex = -1;
4689     double aX = vertices[count-1].x, aY = vertices[count-1].y;
4690     for (int i = 0; i < count; i++) {
4691         Vector2d b = vertices[i];
4692         double bX = b.x, bY = b.y;
4693         double doaX = originX - aX, doaY = originY - aY;
4694         double dbaX = bX - aX, dbaY = bY - aY;
4695         double invDbaDir = 1.0 / (dbaY * dirX - dbaX * dirY);
4696         double t = (dbaX * doaY - dbaY * doaX) * invDbaDir;
4697         if (t >= 0.0 && t < nearestT) {
4698             double t2 = (doaY * dirX - doaX * dirY) * invDbaDir;
4699             if (t2 >= 0.0 && t2 <= 1.0) {
4700                 edgeIndex = (i - 1 + count) % count;
4701                 nearestT = t;
4702                 p.x = originX + t * dirX;
4703                 p.y = originY + t * dirY;
4704             }
4705         }
4706         aX = bX;
4707         aY = bY;
4708     }
4709     return edgeIndex;
4710 }
4711 
4712 /**
4713     * Determine whether the two lines, specified via two points lying on each line, intersect each other, and store the point of intersection
4714     * into the given vector <code>p</code>.
4715     * 
4716     * @param ps1x
4717     *          the x coordinate of the first point on the first line
4718     * @param ps1y
4719     *          the y coordinate of the first point on the first line
4720     * @param pe1x
4721     *          the x coordinate of the second point on the first line
4722     * @param pe1y
4723     *          the y coordinate of the second point on the first line
4724     * @param ps2x
4725     *          the x coordinate of the first point on the second line
4726     * @param ps2y
4727     *          the y coordinate of the first point on the second line
4728     * @param pe2x
4729     *          the x coordinate of the second point on the second line
4730     * @param pe2y
4731     *          the y coordinate of the second point on the second line
4732     * @param p
4733     *          will hold the point of intersection
4734     * @return <code>true</code> iff the two lines intersect; <code>false</code> otherwise
4735     */
4736 public static bool intersectLineLine(double ps1x, double ps1y, double pe1x, double pe1y, double ps2x, double ps2y, double pe2x, double pe2y, Vector2d p) {
4737     double d1x = ps1x - pe1x;
4738     double d1y = pe1y - ps1y;
4739     double d1ps1 = d1y * ps1x + d1x * ps1y;
4740     double d2x = ps2x - pe2x;
4741     double d2y = pe2y - ps2y;
4742     double d2ps2 = d2y * ps2x + d2x * ps2y;
4743     double det = d1y * d2x - d2y * d1x;
4744     if (det == 0.0)
4745         return false;
4746     p.x = (d2x * d1ps1 - d1x * d2ps2) / det;
4747     p.y = (d1y * d2ps2 - d2y * d1ps1) / det;
4748     return true;
4749 }
4750 
4751 private static bool separatingAxis(Vector2d[] v1s, Vector2d[] v2s, double aX, double aY) {
4752     double minA = double.infinity, maxA = -double.infinity;
4753     double minB = double.infinity, maxB = -double.infinity;
4754     int maxLen = cast(int)Math.max(v1s.length, v2s.length);
4755     /* Project both polygons on axis */
4756     for (int k = 0; k < maxLen; k++) {
4757         if (k < v1s.length) {
4758             Vector2d v1 = v1s[k];
4759             double d = v1.x * aX + v1.y * aY;
4760             if (d < minA) minA = d;
4761             if (d > maxA) maxA = d;
4762         }
4763         if (k < v2s.length) {
4764             Vector2d v2 = v2s[k];
4765             double d = v2.x * aX + v2.y * aY;
4766             if (d < minB) minB = d;
4767             if (d > maxB) maxB = d;
4768         }
4769         /* Early-out if overlap found */
4770         if (minA <= maxB && minB <= maxA) {
4771             return false;
4772         }
4773     }
4774     return true;
4775 }
4776 
4777 /**
4778     * Test if the two convex polygons, given via their vertices, intersect.
4779     * 
4780     * @param v1s
4781     *          the vertices of the first convex polygon
4782     * @param v2s
4783     *          the vertices of the second convex polygon
4784     * @return <code>true</code> if the convex polygons intersect; <code>false</code> otherwise
4785     */
4786 public static bool testPolygonPolygon(Vector2d[] v1s, Vector2d[] v2s) {
4787     /* Try to find a separating axis using the first polygon's edges */
4788     for (int i = 0, j = cast(int)v1s.length - 1; i < v1s.length; j = i, i++) {
4789         Vector2d s = v1s[i], t = v1s[j];
4790         if (separatingAxis(v1s, v2s, s.y - t.y, t.x - s.x))
4791             return false;
4792     }
4793     /* Try to find a separating axis using the second polygon's edges */
4794     for (int i = 0, j = cast(int)v2s.length - 1; i < v2s.length; j = i, i++) {
4795         Vector2d s = v2s[i], t = v2s[j];
4796         if (separatingAxis(v1s, v2s, s.y - t.y, t.x - s.x))
4797             return false;
4798     }
4799     return true;
4800 }