public static void GetClosestPointsBetweenLines(ref Vector3 p1, ref Vector3 q1, ref Vector3 p2, ref Vector3 q2,
out float s, out float t, out Vector3 c1, out Vector3 c2)
{
//Segment direction vectors
Vector3 d1;
Vector3.Subtract(ref q1, ref p1, out d1);
Vector3 d2;
Vector3.Subtract(ref q2, ref p2, out d2);
Vector3 r;
Vector3.Subtract(ref p1, ref p2, out r);
//distance
float a = d1.LengthSquared();
float e = d2.LengthSquared();
float f;
Vector3.Dot(ref d2, ref r, out f);
if (a <= Epsilon && e <= Epsilon)
{
//These segments are more like points.
s = t = 0.0f;
c1 = p1;
c2 = p2;
return;
}
if (a <= Epsilon)
{
// First segment is basically a point.
s = 0.0f;
t = MathHelper.Clamp(f / e, 0.0f, 1.0f);
}
else
{
float c = Vector3.Dot(d1, r);
if (e <= Epsilon)
{
// Second segment is basically a point.
t = 0.0f;
s = MathHelper.Clamp(-c / a, 0.0f, 1.0f);
}
else
{
float b = Vector3.Dot(d1, d2);
float denom = a * e - b * b;
// If segments not parallel, compute closest point on L1 to L2, and
// clamp to segment S1. Else pick some s (here .5f)
if (denom != 0f)
s = (b * f - c * e) / denom;
else //Parallel, just use .5f
s = .5f;
t = (b * s + f) / e;
}
}
Vector3.Multiply(ref d1, s, out c1);
Vector3.Add(ref c1, ref p1, out c1);
Vector3.Multiply(ref d2, t, out c2);
Vector3.Add(ref c2, ref p2, out c2);
}