in MREUnityRuntimeLib/ProceduralToolkit/Geometry/Intersect2D.cs [888:999]
public static bool SegmentSegment(Vector2 segment1A, Vector2 segment1B, Vector2 segment2A, Vector2 segment2B,
out IntersectionSegmentSegment2 intersection)
{
Vector2 from2ATo1A = segment1A - segment2A;
Vector2 direction1 = segment1B - segment1A;
Vector2 direction2 = segment2B - segment2A;
float sqrSegment1Length = direction1.sqrMagnitude;
float sqrSegment2Length = direction2.sqrMagnitude;
bool segment1IsAPoint = sqrSegment1Length < Geometry.Epsilon;
bool segment2IsAPoint = sqrSegment2Length < Geometry.Epsilon;
if (segment1IsAPoint && segment2IsAPoint)
{
if (segment1A == segment2A)
{
intersection = IntersectionSegmentSegment2.Point(segment1A);
return true;
}
intersection = IntersectionSegmentSegment2.None();
return false;
}
if (segment1IsAPoint)
{
if (PointSegment(segment1A, segment2A, direction2, sqrSegment2Length))
{
intersection = IntersectionSegmentSegment2.Point(segment1A);
return true;
}
intersection = IntersectionSegmentSegment2.None();
return false;
}
if (segment2IsAPoint)
{
if (PointSegment(segment2A, segment1A, direction1, sqrSegment1Length))
{
intersection = IntersectionSegmentSegment2.Point(segment2A);
return true;
}
intersection = IntersectionSegmentSegment2.None();
return false;
}
float denominator = VectorE.PerpDot(direction1, direction2);
float perpDot1 = VectorE.PerpDot(direction1, from2ATo1A);
float perpDot2 = VectorE.PerpDot(direction2, from2ATo1A);
if (Mathf.Abs(denominator) < Geometry.Epsilon)
{
// Parallel
if (Mathf.Abs(perpDot1) > Geometry.Epsilon || Mathf.Abs(perpDot2) > Geometry.Epsilon)
{
// Not collinear
intersection = IntersectionSegmentSegment2.None();
return false;
}
// Collinear
bool codirected = Vector2.Dot(direction1, direction2) > 0;
if (codirected)
{
// Codirected
float segment2AProjection = -Vector2.Dot(direction1, from2ATo1A);
if (segment2AProjection > -Geometry.Epsilon)
{
// 1A------1B
// 2A------2B
return SegmentSegmentCollinear(segment1A, segment1B, sqrSegment1Length, segment2A, segment2B, out intersection);
}
else
{
// 1A------1B
// 2A------2B
return SegmentSegmentCollinear(segment2A, segment2B, sqrSegment2Length, segment1A, segment1B, out intersection);
}
}
else
{
// Contradirected
float segment2BProjection = Vector2.Dot(direction1, segment2B - segment1A);
if (segment2BProjection > -Geometry.Epsilon)
{
// 1A------1B
// 2B------2A
return SegmentSegmentCollinear(segment1A, segment1B, sqrSegment1Length, segment2B, segment2A, out intersection);
}
else
{
// 1A------1B
// 2B------2A
return SegmentSegmentCollinear(segment2B, segment2A, sqrSegment2Length, segment1A, segment1B, out intersection);
}
}
}
// Not parallel
float distance1 = perpDot2/denominator;
if (distance1 < -Geometry.Epsilon || distance1 > 1 + Geometry.Epsilon)
{
intersection = IntersectionSegmentSegment2.None();
return false;
}
float distance2 = perpDot1/denominator;
if (distance2 < -Geometry.Epsilon || distance2 > 1 + Geometry.Epsilon)
{
intersection = IntersectionSegmentSegment2.None();
return false;
}
intersection = IntersectionSegmentSegment2.Point(segment1A + direction1*distance1);
return true;
}