in MREUnityRuntimeLib/ProceduralToolkit/Geometry/Distance2D.cs [291:387]
public static float RayRay(Vector2 originA, Vector2 directionA, Vector2 originB, Vector2 directionB)
{
Vector2 originBToA = originA - originB;
float denominator = VectorE.PerpDot(directionA, directionB);
float perpDotA = VectorE.PerpDot(directionA, originBToA);
float perpDotB = VectorE.PerpDot(directionB, originBToA);
bool codirected = Vector2.Dot(directionA, directionB) > 0;
if (Mathf.Abs(denominator) < Geometry.Epsilon)
{
// Parallel
float originBProjection = -Vector2.Dot(directionA, originBToA);
if (Mathf.Abs(perpDotA) > Geometry.Epsilon || Mathf.Abs(perpDotB) > Geometry.Epsilon)
{
// Not collinear
if (!codirected && originBProjection < Geometry.Epsilon)
{
return Vector2.Distance(originA, originB);
}
float distanceSqr = originBToA.sqrMagnitude - originBProjection*originBProjection;
// distanceSqr can be negative
return distanceSqr <= 0 ? 0 : Mathf.Sqrt(distanceSqr);
}
// Collinear
if (codirected)
{
// Ray intersection
return 0;
}
else
{
if (originBProjection < Geometry.Epsilon)
{
// No intersection
return Vector2.Distance(originA, originB);
}
else
{
// Segment intersection
return 0;
}
}
}
// Not parallel
float distanceA = perpDotB/denominator;
float distanceB = perpDotA/denominator;
if (distanceA < -Geometry.Epsilon || distanceB < -Geometry.Epsilon)
{
// No intersection
if (codirected)
{
float originAProjection = Vector2.Dot(directionB, originBToA);
if (originAProjection > -Geometry.Epsilon)
{
Vector2 rayPointA = originA;
Vector2 rayPointB = originB + directionB*originAProjection;
return Vector2.Distance(rayPointA, rayPointB);
}
float originBProjection = -Vector2.Dot(directionA, originBToA);
if (originBProjection > -Geometry.Epsilon)
{
Vector2 rayPointA = originA + directionA*originBProjection;
Vector2 rayPointB = originB;
return Vector2.Distance(rayPointA, rayPointB);
}
return Vector2.Distance(originA, originB);
}
else
{
if (distanceA > -Geometry.Epsilon)
{
float originBProjection = -Vector2.Dot(directionA, originBToA);
if (originBProjection > -Geometry.Epsilon)
{
Vector2 rayPointA = originA + directionA*originBProjection;
Vector2 rayPointB = originB;
return Vector2.Distance(rayPointA, rayPointB);
}
}
else if (distanceB > -Geometry.Epsilon)
{
float originAProjection = Vector2.Dot(directionB, originBToA);
if (originAProjection > -Geometry.Epsilon)
{
Vector2 rayPointA = originA;
Vector2 rayPointB = originB + directionB*originAProjection;
return Vector2.Distance(rayPointA, rayPointB);
}
}
return Vector2.Distance(originA, originB);
}
}
// Point intersection
return 0;
}