private static bool SegmentSegmentCollinear(Vector2 leftA, Vector2 leftB, Vector2 rightA, Vector2 rightB, out IntersectionSegmentSegment2 intersection) { Vector2 leftDirection = leftB - leftA; float projectionRA = Vector2.Dot(leftDirection, leftB - rightA); if (Mathf.Abs(projectionRA) < Geometry.Epsilon) { // LB == RA // LA------LB // RA------RB intersection = IntersectionSegmentSegment2.Point(leftB); return(true); } if (projectionRA > 0) { // LB > RA // LA------LB // RARB // RA--RB // RA------RB Vector2 pointB; float projectionRB = Vector2.Dot(leftDirection, rightB - leftA); if (projectionRB > leftDirection.sqrMagnitude) { pointB = leftB; } else { pointB = rightB; } intersection = IntersectionSegmentSegment2.Segment(rightA, pointB); return(true); } // LB < RA // LA------LB // RA------RB intersection = IntersectionSegmentSegment2.None(); return(false); }
private static bool SegmentSegmentCollinear(Vector2 leftA, Vector2 leftB, float sqrLeftLength, Vector2 rightA, Vector2 rightB, out IntersectionSegmentSegment2 intersection) { Vector2 leftDirection = leftB - leftA; float rightAProjection = Vector2.Dot(leftDirection, rightA - leftB); if (Mathf.Abs(rightAProjection) < Geometry.Epsilon) { // LB == RA // LA------LB // RA------RB intersection = IntersectionSegmentSegment2.Point(leftB); return(true); } if (rightAProjection < 0) { // LB > RA // LA------LB // RARB // RA--RB // RA------RB Vector2 pointB; float rightBProjection = Vector2.Dot(leftDirection, rightB - leftA); if (rightBProjection > sqrLeftLength) { pointB = leftB; } else { pointB = rightB; } intersection = IntersectionSegmentSegment2.Segment(rightA, pointB); return(true); } // LB < RA // LA------LB // RA------RB intersection = IntersectionSegmentSegment2.None(); return(false); }
/// <summary> /// Computes an intersection of the segments /// </summary> 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); }
/// <summary> /// Computes an intersection of the segments /// </summary> 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 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 or degenerate bool segment1IsAPoint = direction1.sqrMagnitude < Geometry.Epsilon; bool segment2IsAPoint = direction2.sqrMagnitude < Geometry.Epsilon; if (segment1IsAPoint && segment2IsAPoint) { if (segment1A == segment2A) { intersection = IntersectionSegmentSegment2.Point(segment1A); return(true); } intersection = IntersectionSegmentSegment2.None(); return(false); } if (segment1IsAPoint) { if (CollinearPointInSegment(segment2A, segment2B, point: segment1A)) { intersection = IntersectionSegmentSegment2.Point(segment1A); return(true); } intersection = IntersectionSegmentSegment2.None(); return(false); } if (segment2IsAPoint) { if (CollinearPointInSegment(segment1A, segment1B, point: segment2A)) { intersection = IntersectionSegmentSegment2.Point(segment2A); return(true); } intersection = IntersectionSegmentSegment2.None(); return(false); } bool codirected = Vector2.Dot(direction1, direction2) > 0; if (codirected) { // Codirected float projectionFrom2ATo1A = Vector2.Dot(direction1, from2ATo1A); if (projectionFrom2ATo1A > 0) { // 2A------2B // 1A------1B return(SegmentSegmentCollinear(segment2A, segment2B, segment1A, segment1B, out intersection)); } else { // 1A------1B // 2A------2B return(SegmentSegmentCollinear(segment1A, segment1B, segment2A, segment2B, out intersection)); } } else { // Contradirected float projectionFrom1ATo2B = Vector2.Dot(direction1, segment2B - segment1A); if (projectionFrom1ATo2B > 0) { // 1A------1B // 2B------2A return(SegmentSegmentCollinear(segment1A, segment1B, segment2B, segment2A, out intersection)); } else { // 2B------2A // 1A------1B return(SegmentSegmentCollinear(segment2B, segment2A, segment1A, segment1B, out intersection)); } } } // The segments are skew 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); }