in MREUnityRuntimeLib/ProceduralToolkit/Geometry/Closest2D.cs [429:568]
public static void RayRay(Vector2 originA, Vector2 directionA, Vector2 originB, Vector2 directionB,
out Vector2 pointA, out Vector2 pointB)
{
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)
{
if (originBProjection > -Geometry.Epsilon)
{
// Projection of originA is on rayB
pointA = originA;
pointB = originB + directionA*originBProjection;
return;
}
else
{
pointA = originA - directionA*originBProjection;
pointB = originB;
return;
}
}
else
{
if (originBProjection > 0)
{
pointA = originA;
pointB = originB;
return;
}
else
{
// Projection of originA is on rayB
pointA = originA;
pointB = originB + directionA*originBProjection;
return;
}
}
}
// Collinear
if (codirected)
{
// Ray intersection
if (originBProjection > -Geometry.Epsilon)
{
// Projection of originA is on rayB
pointA = pointB = originA;
return;
}
else
{
pointA = pointB = originB;
return;
}
}
else
{
if (originBProjection > 0)
{
// No intersection
pointA = originA;
pointB = originB;
return;
}
else
{
// Segment intersection
pointA = pointB = originA;
return;
}
}
}
// 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)
{
pointA = originA;
pointB = originB + directionB*originAProjection;
return;
}
float originBProjection = -Vector2.Dot(directionA, originBToA);
if (originBProjection > -Geometry.Epsilon)
{
pointA = originA + directionA*originBProjection;
pointB = originB;
return;
}
pointA = originA;
pointB = originB;
return;
}
else
{
if (distanceA > -Geometry.Epsilon)
{
float originBProjection = -Vector2.Dot(directionA, originBToA);
if (originBProjection > -Geometry.Epsilon)
{
pointA = originA + directionA*originBProjection;
pointB = originB;
return;
}
}
else if (distanceB > -Geometry.Epsilon)
{
float originAProjection = Vector2.Dot(directionB, originBToA);
if (originAProjection > -Geometry.Epsilon)
{
pointA = originA;
pointB = originB + directionB*originAProjection;
return;
}
}
pointA = originA;
pointB = originB;
return;
}
}
// Point intersection
pointA = pointB = originA + directionA*distanceA;
}