aboutsummaryrefslogtreecommitdiffstats
path: root/src/javax/media/j3d/Utils.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/javax/media/j3d/Utils.java')
-rw-r--r--src/javax/media/j3d/Utils.java746
1 files changed, 746 insertions, 0 deletions
diff --git a/src/javax/media/j3d/Utils.java b/src/javax/media/j3d/Utils.java
new file mode 100644
index 0000000..dda1dca
--- /dev/null
+++ b/src/javax/media/j3d/Utils.java
@@ -0,0 +1,746 @@
+/*
+ * Copyright 2013 Harvey Harrison <[email protected]>
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ */
+package javax.media.j3d;
+
+import javax.vecmath.Point3d;
+import javax.vecmath.Vector3d;
+
+/**
+ * A small utility class for internal use. Mainly contains some distance-calculation
+ * methods.
+ *
+ */
+class Utils {
+
+/**
+ * Returns the square of the minimum distance from the given point to the segment
+ * defined by start, end.
+ */
+static final double ptToSegSquare(Point3d pt, Point3d start, Point3d end, Point3d closest) {
+ Vector3d dir = new Vector3d();
+ dir.sub(end, start);
+
+ Vector3d dt = new Vector3d();
+ dt.sub(pt, start);
+
+ // Project the point onto the line defined by the segment
+ double proj = dir.dot(dt);
+
+ // We projected 'before' the start point, just return the dSquared between
+ // the point and the start
+ if (proj <= 0.0d) {
+ if (closest != null) closest.set(start);
+ return dt.lengthSquared();
+ }
+
+ // Project the segment onto itself
+ double segSquared = dir.lengthSquared();
+
+ // If our point projected off the end of the segment, return the dSquared between
+ // the point and the end
+ if (proj >= segSquared) {
+ if (closest != null) closest.set(end);
+ dt.sub(pt, end);
+ return dt.lengthSquared();
+ }
+
+ // We projected somewhere along the segment, calculate the closest point
+ dt.scaleAdd(proj / segSquared, dir, start);
+ if (closest != null) closest.set(dt);
+
+ // return the distance from the point to the closest point on the segment
+ dt.sub(pt, dt);
+ return dt.lengthSquared();
+}
+
+/**
+ * Returns the square of the minimum distance from the given point to the ray
+ * defined by start, dir.
+ */
+static final double ptToRaySquare(Point3d pt, Point3d start, Vector3d dir, Point3d closest) {
+ Vector3d dt = new Vector3d();
+ dt.sub(pt, start);
+
+ // Project the point onto the ray
+ double proj = dir.dot(dt);
+
+ // We projected 'before' the start point, just return the dSquared between
+ // the point and the start
+ if (proj <= 0.0d) {
+ if (closest != null) closest.set(start);
+ return dt.lengthSquared();
+ }
+
+ // Project the ray onto itself
+ double raySquared = dir.lengthSquared();
+
+ // We projected somewhere along the ray, calculate the closest point
+ dt.scaleAdd(proj / raySquared, dir, start);
+ if (closest != null) closest.set(dt);
+
+ // return the distance from the point to the closest point on the ray
+ dt.sub(pt, dt);
+ return dt.lengthSquared();
+}
+
+private static final double ZERO_TOL = 1e-5d;
+
+/**
+ * Return the square of the minimum distance between a ray and a segment.
+ * Geometric Tools, LLC
+ * Copyright (c) 1998-2012
+ * Distributed under the Boost Software License, Version 1.0.
+ * http://www.boost.org/LICENSE_1_0.txt
+ * http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
+ * http://www.geometrictools.com/LibMathematics/Distance/Wm5DistRay3Segment3.cpp
+ * File Version: 5.0.1 (2010/10/01)
+ */
+static public double rayToSegment(Point3d rayorig, Vector3d raydir,
+ Point3d segstart, Point3d segend,
+ Point3d rayint, Point3d segint, double[] param) {
+ double s, t;
+
+ Vector3d diff = new Vector3d();
+ diff.sub(rayorig, segstart);
+ Vector3d segdir = new Vector3d();
+ segdir.sub(segend, segstart);
+
+ double A = raydir.dot(raydir);// Dot(ray.m,ray.m);
+ double B = -raydir.dot(segdir);// -Dot(ray.m,seg.m);
+ double C = segdir.dot(segdir);// Dot(seg.m,seg.m);
+ double D = raydir.dot(diff);// Dot(ray.m,diff);
+ double E; // -Dot(seg.m,diff), defer until needed
+ double F = diff.dot(diff);// Dot(diff,diff);
+ double det = Math.abs(A * C - B * B); // A*C-B*B = |Cross(M0,M1)|^2 >= 0
+
+ double tmp;
+
+ if (det >= ZERO_TOL) {
+ // ray and segment are not parallel
+ E = -segdir.dot(diff);// -Dot(seg.m,diff);
+ s = B * E - C * D;
+ t = B * D - A * E;
+
+ if (s >= 0) {
+ if (t >= 0) {
+ if (t <= det) { // region 0
+ // minimum at interior points of ray and segment
+ double invDet = 1.0f / det;
+ s *= invDet;
+ t *= invDet;
+ if (rayint != null) rayint.scaleAdd(s, raydir, rayorig);
+ if (segint != null) segint.scaleAdd(t, segdir, segstart);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(s * (A * s + B * t + 2 * D) + t
+ * (B * s + C * t + 2 * E) + F);
+ }
+ else { // region 1
+
+ t = 1;
+ if (D >= 0) {
+ s = 0;
+ if (rayint != null) rayint.set(rayorig);
+ if (segint != null) segint.set(segend);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(C + 2 * E + F);
+ }
+ else {
+ s = -D / A;
+ if (rayint != null) rayint.scaleAdd(s, raydir, rayorig);
+ if (segint != null) segint.set(segend);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs((D + 2 * B) * s + C + 2 * E + F);
+ }
+ }
+ }
+ else { // region 5
+ t = 0;
+ if (D >= 0) {
+ s = 0;
+ if (rayint != null) rayint.set(rayorig);
+ if (segint != null) segint.set(segstart);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(F);
+ }
+ else {
+ s = -D / A;
+ if (rayint != null) rayint.scaleAdd(s, raydir, rayorig);
+ if (segint != null) segint.set(segstart);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(D * s + F);
+ }
+ }
+ }
+ else {
+ if (t <= 0) { // region 4
+ if (D < 0) {
+ s = -D / A;
+ t = 0;
+ if (rayint != null) rayint.scaleAdd(s, raydir, rayorig);
+ if (segint != null) segint.set(segstart);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(D * s + F);
+ }
+ else {
+ s = 0;
+ if (E >= 0) {
+ t = 0;
+ if (rayint != null) rayint.set(rayorig);
+ if (segint != null) segint.set(segstart);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(F);
+ }
+ else if (-E >= C) {
+ t = 1;
+ if (rayint != null) rayint.set(rayorig);
+ if (segint != null) segint.set(segend);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(C + 2 * E + F);
+ }
+ else {
+ t = -E / C;
+ if (rayint != null) rayint.set(rayorig);
+ if (segint != null) segint.scaleAdd(t, segdir, segstart);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(E * t + F);
+ }
+ }
+ }
+ else if (t <= det) { // region 3
+ s = 0;
+ if (E >= 0) {
+ t = 0;
+ if (rayint != null) rayint.set(rayorig);
+ if (segint != null) segint.set(segstart);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(F);
+ }
+ else if (-E >= C) {
+ t = 1;
+ if (rayint != null) rayint.set(rayorig);
+ if (segint != null) segint.set(segend);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(C + 2 * E + F);
+ }
+ else {
+ t = -E / C;
+ if (rayint != null) rayint.set(rayorig);
+ if (segint != null) segint.scaleAdd(t, segdir, segstart);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(E * t + F);
+ }
+ }
+ else { // region 2
+ tmp = B + D;
+ if (tmp < 0) {
+ s = -tmp / A;
+ t = 1;
+ if (rayint != null) rayint.scaleAdd(s, raydir, rayorig);
+ if (segint != null) segint.set(segend);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(tmp * s + C + 2 * E + F);
+ }
+ else {
+ s = 0;
+ if (E >= 0) {
+ t = 0;
+ if (rayint != null) rayint.set(rayorig);
+ if (segint != null) segint.set(segstart);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(F);
+ }
+ else if (-E >= C) {
+ t = 1;
+ if (rayint != null) rayint.set(rayorig);
+ if (segint != null) segint.set(segend);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(C + 2 * E + F);
+ }
+ else {
+ t = -E / C;
+ if (rayint != null) rayint.set(rayorig);
+ if (segint != null) segint.scaleAdd(t, segdir, segstart);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(E * t + F);
+ }
+ }
+ }
+ }
+ }
+ else {
+ // ray and segment are parallel
+ if (B > 0) {
+ // opposite direction vectors
+ t = 0;
+ if (D >= 0) {
+ s = 0;
+ if (rayint != null) rayint.set(rayorig);
+ if (segint != null) segint.set(segstart);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(F);
+ }
+ else {
+ s = -D / A;
+ if (rayint != null) rayint.scaleAdd(s, raydir, rayorig);
+ if (segint != null) segint.set(segstart);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(D * s + F);
+ }
+ }
+ else {
+ // same direction vectors
+ E = segdir.dot(diff);// -Dot(seg.m,diff);
+ t = 1;
+ tmp = B + D;
+ if (tmp >= 0) {
+ s = 0;
+ if (rayint != null) rayint.set(rayorig);
+ if (segint != null) segint.set(segend);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(C + 2 * E + F);
+ }
+ else {
+ s = -tmp / A;
+ if (rayint != null) rayint.scaleAdd(s, raydir, rayorig);
+ if (segint != null) segint.set(segend);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(tmp * s + C + 2 * E + F);
+ }
+ }
+ }
+}
+
+/**
+ * Return the square of the minimum distance between two line segments.
+ *
+ * Code in this method adapted from:
+ * Geometric Tools, LLC
+ * Copyright (c) 1998-2012
+ * Distributed under the Boost Software License, Version 1.0.
+ * http://www.boost.org/LICENSE_1_0.txt
+ * http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
+ * http://www.geometrictools.com/LibMathematics/Distance/Wm5DistSegment3Segment3.cpp
+ * File Version: 5.0.1 (2010/10/01)
+ */
+static public double segmentToSegment(Point3d s0start, Point3d s0end,
+ Point3d s1start, Point3d s1end,
+ Point3d s0int, Point3d s1int, double[] param) {
+ double s, t;
+
+ Vector3d diff = new Vector3d();
+ diff.sub(s0start, s1start);
+
+ Vector3d seg0dir = new Vector3d();
+ seg0dir.sub(s0end, s0start);
+ Vector3d seg1dir = new Vector3d();
+ seg1dir.sub(s1end, s1start);
+
+ double A = seg0dir.dot(seg0dir); // Dot(seg0dir,seg0dir);
+ double B = -seg0dir.dot(seg1dir); // -Dot(seg0dir,seg1dir);
+ double C = seg1dir.dot(seg1dir); // Dot(seg1dir,seg1dir);
+ double D = seg0dir.dot(diff); // Dot(seg0dir,diff);
+ double E; // -Dot(seg1dir,diff), defer until needed
+ double F = diff.dot(diff); // Dot(diff,diff);
+ double det = Math.abs(A * C - B * B); // A*C-B*B = |Cross(M0,M1)|^2 >= 0
+
+ double tmp;
+
+ if (det >= ZERO_TOL) {
+ // line segments are not parallel
+ E = -seg1dir.dot(diff); // -Dot(seg1dir,diff);
+ s = B * E - C * D;
+ t = B * D - A * E;
+
+ if (s >= 0) {
+ if (s <= det) {
+ if (t >= 0) {
+ if (t <= det) { // region 0 (interior)
+ // minimum at two interior points of 3D lines
+ double invDet = 1.0f / det;
+ s *= invDet;
+ t *= invDet;
+ if (s0int != null) s0int.scaleAdd(s, seg0dir, s0start);
+ if (s1int != null) s1int.scaleAdd(t, seg1dir, s1start);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(s * (A * s + B * t + 2 * D) + t
+ * (B * s + C * t + 2 * E) + F);
+ }
+ else { // region 3 (side)
+ t = 1;
+ tmp = B + D;
+ if (tmp >= 0) {
+ s = 0;
+ if (s0int != null) s0int.set(s0start);
+ if (s1int != null) s1int.set(s1end);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(C + 2 * E + F);
+ }
+ else if (-tmp >= A) {
+ s = 1;
+ if (s0int != null) s0int.set(s0end);
+ if (s1int != null) s1int.set(s1end);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(A + C + F + 2 * (E + tmp));
+ }
+ else {
+ s = -tmp / A;
+ if (s0int != null) s0int.scaleAdd(s, seg0dir, s0start);
+ if (s1int != null) s1int.set(s1end);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(tmp * s + C + 2 * E + F);
+ }
+ }
+ }
+ else { // region 7 (side)
+ t = 0;
+ if (D >= 0) {
+ s = 0;
+ if (s0int != null) s0int.set(s0start);
+ if (s1int != null) s1int.set(s1start);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(F);
+ }
+ else if (-D >= A) {
+ s = 1;
+ if (s0int != null) s0int.set(s0end);
+ if (s1int != null) s1int.set(s1start);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(A + 2 * D + F);
+ }
+ else {
+ s = -D / A;
+ if (s0int != null) s0int.scaleAdd(s, seg0dir, s0start);
+ if (s1int != null) s1int.set(s1start);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(D * s + F);
+ }
+ }
+ }
+ else {
+ if (t >= 0) {
+ if (t <= det) { // region 1 (side)
+ s = 1;
+ tmp = B + E;
+ if (tmp >= 0) {
+ t = 0;
+ if (s0int != null) s0int.set(s0end);
+ if (s1int != null) s1int.set(s1start);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(A + 2 * D + F);
+ }
+ else if (-tmp >= C) {
+ t = 1;
+ if (s0int != null) s0int.set(s0end);
+ if (s1int != null) s1int.set(s1end);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(A + C + F + 2 * (D + tmp));
+ }
+ else {
+ t = -tmp / C;
+ if (s0int != null) s0int.set(s0end);
+ if (s1int != null) s1int.scaleAdd(t, seg1dir, s1start);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(tmp * t + A + 2 * D + F);
+ }
+ }
+ else { // region 2 (corner)
+ tmp = B + D;
+ if (-tmp <= A) {
+ t = 1;
+ if (tmp >= 0) {
+ s = 0;
+ if (s0int != null) s0int.set(s0start);
+ if (s1int != null) s1int.set(s1end);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(C + 2 * E + F);
+ }
+ else {
+ s = -tmp / A;
+ if (s0int != null) s0int.scaleAdd(s, seg0dir, s0start);
+ if (s1int != null) s1int.set(s1end);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(tmp * s + C + 2 * E + F);
+ }
+ }
+ else {
+ s = 1;
+ tmp = B + E;
+ if (tmp >= 0) {
+ t = 0;
+ if (s0int != null) s0int.set(s0end);
+ if (s1int != null) s1int.set(s1start);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(A + 2 * D + F);
+ }
+ else if (-tmp >= C) {
+ t = 1;
+ if (s0int != null) s0int.set(s0end);
+ if (s1int != null) s1int.set(s1end);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(A + C + F + 2 * (D + tmp));
+ }
+ else {
+ t = -tmp / C;
+ if (s0int != null) s0int.set(s0end);
+ if (s1int != null) s1int.scaleAdd(t, seg1dir, s1start);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(tmp * t + A + 2 * D + F);
+ }
+ }
+ }
+ }
+ else { // region 8 (corner)
+ if (-D < A) {
+ t = 0;
+ if (D >= 0) {
+ s = 0;
+ if (s0int != null) s0int.set(s0start);
+ if (s1int != null) s1int.set(s1start);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(F);
+ }
+ else {
+ s = -D / A;
+ if (s0int != null) s0int.scaleAdd(s, seg0dir, s0start);
+ if (s1int != null) s1int.set(s1start);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(D * s + F);
+ }
+ }
+ else {
+ s = 1;
+ tmp = B + E;
+ if (tmp >= 0) {
+ t = 0;
+ if (s0int != null) s0int.set(s0end);
+ if (s1int != null) s1int.set(s1start);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(A + 2 * D + F);
+ }
+ else if (-tmp >= C) {
+ t = 1;
+ if (s0int != null) s0int.set(s0end);
+ if (s1int != null) s1int.set(s1end);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(A + C + F + 2 * (D + tmp));
+ }
+ else {
+ t = -tmp / C;
+ if (s0int != null) s0int.set(s0end);
+ if (s1int != null) s1int.scaleAdd(t, seg1dir, s1start);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(tmp * t + A + 2 * D + F);
+ }
+ }
+ }
+ }
+ }
+ else {
+ if (t >= 0) {
+ if (t <= det) { // region 5 (side)
+ s = 0;
+ if (E >= 0) {
+ t = 0;
+ if (s0int != null) s0int.set(s0start);
+ if (s1int != null) s1int.set(s1start);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(F);
+ }
+ else if (-E >= C) {
+ t = 1;
+ if (s0int != null) s0int.set(s0start);
+ if (s1int != null) s1int.set(s1end);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(C + 2 * E + F);
+ }
+ else {
+ t = -E / C;
+ if (s0int != null) s0int.set(s0start);
+ if (s1int != null) s1int.scaleAdd(t, seg1dir, s1start);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(E * t + F);
+ }
+ }
+ else { // region 4 (corner)
+ tmp = B + D;
+ if (tmp < 0) {
+ t = 1;
+ if (-tmp >= A) {
+ s = 1;
+ if (s0int != null) s0int.set(s0end);
+ if (s1int != null) s1int.set(s1end);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(A + C + F + 2 * (E + tmp));
+ }
+ else {
+ s = -tmp / A;
+ if (s0int != null) s0int.scaleAdd(s, seg0dir, s0start);
+ if (s1int != null) s1int.set(s1end);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(tmp * s + C + 2 * E + F);
+ }
+ }
+ else {
+ s = 0;
+ if (E >= 0) {
+ t = 0;
+ if (s0int != null) s0int.set(s0start);
+ if (s1int != null) s1int.set(s1start);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(F);
+ }
+ else if (-E >= C) {
+ t = 1;
+ if (s0int != null) s0int.set(s0start);
+ if (s1int != null) s1int.set(s1end);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(C + 2 * E + F);
+ }
+ else {
+ t = -E / C;
+ if (s0int != null) s0int.set(s0start);
+ if (s1int != null) s1int.scaleAdd(t, seg1dir, s1start);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(E * t + F);
+ }
+ }
+ }
+ }
+ else { // region 6 (corner)
+ if (D < 0) {
+ t = 0;
+ if (-D >= A) {
+ s = 1;
+ if (s0int != null) s0int.set(s0end);
+ if (s1int != null) s1int.set(s1start);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(A + 2 * D + F);
+ }
+ else {
+ s = -D / A;
+ if (s0int != null) s0int.scaleAdd(s, seg0dir, s0start);
+ if (s1int != null) s1int.set(s1start);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(D * s + F);
+ }
+ }
+ else {
+ s = 0;
+ if (E >= 0) {
+ t = 0;
+ if (s0int != null) s0int.set(s0start);
+ if (s1int != null) s1int.set(s1start);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(F);
+ }
+ else if (-E >= C) {
+ t = 1;
+ if (s0int != null) s0int.set(s0start);
+ if (s1int != null) s1int.set(s1end);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(C + 2 * E + F);
+ }
+ else {
+ t = -E / C;
+ if (s0int != null) s0int.set(s0start);
+ if (s1int != null) s1int.scaleAdd(t, seg1dir, s1start);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(E * t + F);
+ }
+ }
+ }
+ }
+ }
+ else {
+ // line segments are parallel
+ if (B > 0) {
+ // direction vectors form an obtuse angle
+ if (D >= 0) {
+ s = 0;
+ t = 0;
+ if (s0int != null) s0int.set(s0start);
+ if (s1int != null) s1int.set(s1start);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(F);
+ }
+ else if (-D <= A) {
+ s = -D / A;
+ t = 0;
+ if (s0int != null) s0int.scaleAdd(s, seg0dir, s0start);
+ if (s1int != null) s1int.set(s1start);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(D * s + F);
+ }
+ else {
+ E = -seg1dir.dot(diff); // -Dot(seg1dir,diff);
+ s = 1;
+ tmp = A + D;
+ if (-tmp >= B) {
+ t = 1;
+ if (s0int != null) s0int.set(s0end);
+ if (s1int != null) s1int.set(s1end);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(A + C + F + 2 * (B + D + E));
+ }
+ else {
+ t = -tmp / B;
+ if (s0int != null) s0int.set(s0end);
+ if (s1int != null) s1int.scaleAdd(t, seg1dir, s1start);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(A + 2 * D + F + t * (C * t + 2 * (B + E)));
+ }
+ }
+ }
+ else {
+ // direction vectors form an acute angle
+ if (-D >= A) {
+ s = 1;
+ t = 0;
+ if (s0int != null) s0int.set(s0end);
+ if (s1int != null) s1int.set(s1start);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(A + 2 * D + F);
+ }
+ else if (D <= 0) {
+ s = -D / A;
+ t = 0;
+ if (s0int != null) s0int.scaleAdd(s, seg0dir, s0start);
+ if (s1int != null) s1int.set(s1start);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(D * s + F);
+ }
+ else {
+ E = -seg1dir.dot(diff); // -Dot(seg1dir,diff);
+ s = 0;
+ if (D >= -B) {
+ t = 1;
+ if (s0int != null) s0int.set(s0start);
+ if (s1int != null) s1int.set(s1end);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(C + 2 * E + F);
+ }
+ else {
+ t = -D / B;
+ if (s0int != null) s0int.set(s0start);
+ if (s1int != null) s1int.scaleAdd(t, seg1dir, s1start);
+ if (param != null) { param[0] = s; param[1] = t; }
+ return Math.abs(F + t * (2 * E + C * t));
+ }
+ }
+ }
+ }
+}
+}