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);
        }
Example #2
0
        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);
        }
Example #3
0
        /// <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);
        }