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