Finding shortest line segment between two rays / Closest Point of Approach

Assuming I have two rays (or, alternately, two position vectors and 2 corresponding speed vectors), what is the fastest / most resource-efficient (i.e. no for loops etc.) way to find the shortest possible line segment connecting the two rays, OR the Closest Point of Approach (for the 2+2 vectors)?
Thanks in advance!

Nobody answered, and I figured on my own. Sample solution in case somebody else is interested:

public static float ClosestTimeOfApproach(Vector3 pos1, Vector3 vel1, Vector3 pos2, Vector3 vel2)
{
	//float t = 0;
	var dv = vel1 - vel2;
	var dv2 = Vector3.Dot(dv, dv);
	if (dv2 < 0.0000001f)      // the tracks are almost parallel
	{
		return 0.0f; // any time is ok.  Use time 0.
	}
	
	var w0 = pos1 - pos2;
	return (-Vector3.Dot(w0, dv)/dv2);
}

public static float ClosestDistOfApproach(Vector3 pos1, Vector3 vel1, Vector3 pos2, Vector3 vel2, out Vector3 p1, out Vector3 p2)
{
	var t = ClosestTimeOfApproach(pos1,vel1,pos2,vel2);
	p1 = pos1 + (t * vel1);
	p2 = pos2 + (t*vel2);

	return Vector3.Distance(p1, p2);           // distance at CPA
}

public static Vector3 ClosestPointOfApproach(Vector3 pos1, Vector3 vel1, Vector3 pos2, Vector3 vel2)
{
	var t = ClosestTimeOfApproach(pos1, vel1, pos2, vel2);
	if (t<0) // don't detect approach points in the past, only in the future;
	{
		return (pos1); 
	}

	return (pos1 + (t * vel1));
	
}

Found this post that helped me when I couldn’t get this solution to work.

The answer links to these resources (the function ClosestPointsOnTwoLines helped me out the most with my problem):
http://wiki.unity3d.com/index.php/3d_Math_functions?_ga=2.104569024.1350420062.1572253629-1502904723.1553610781

Hope it helps :slight_smile:

I had the same problem but i wanted to find the closest points between two lines and i came up with the following solution:

// Piece wise mult
Vector3 PWMult(Vector3 left, Vector3 right)
{
    return new Vector3(left.x*right.x,left.y*right.y,left.z*right.z);
}

// Vector Sum
float VSum(Vector3 vec)
{
    return vec.x+vec.y+vec.z;
}


/// <summary>
/// returns the t values for the points where the rays are closest.
/// </summary>
/// <returns> Vector2 wher x is t value for ray1 and y is t value for ray 2</returns>
public static Vector2 ClosestPointRays(Vector3 origin1, Vector3 vel1, Vector3 origin2, Vector3 vel2)
{
    float t1 = VSum(PWMult(origin2 - origin1, vel1 * Vector3.Dot(vel2, vel2) - vel2 * Vector3.Dot(vel2, vel1))) / VSum(PWMult(vel1, vel1) * Vector3.Dot(vel2, vel2) - PWMult(vel2, vel1) * Vector3.Dot(vel2, vel1));
    float t2 = VSum(PWMult(origin1 - origin2, vel2 * Vector3.Dot(vel1, vel1) - vel1 * Vector3.Dot(vel1, vel2))) / VSum(PWMult(vel2, vel2) * Vector3.Dot(vel1, vel1) - PWMult(vel1, vel2) * Vector3.Dot(vel1, vel2));
    return new Vector2(t1,t2);
}

I used origin and velocity instead of the builtin ray because it normalizes it’s direction and I would need to rescale the values otherwise.
I tested it myself (using it to attach spider strings to other strings) so i can confirm that it worked.
From this it is easy to find the distance of the closest points and so on.