예제 #1
0
        /// <summary>
        /// Calculates the intersection between two 2D segments.
        /// </summary>
        /// <param name="segment1">The first 2D segment.</param>
        /// <param name="segment2">The second 2D segment.</param>
        /// <returns>The intersection calculation result.</returns>
        /// <exception cref="ArgumentNullException">Thrown when <paramref name="segment1"/> or
        /// <paramref name="segment2"/> is <c>null</c>.</exception>
        /// <remarks>Implementation from http://geomalgorithms.com/a05-_intersect-1.html
        /// based on method <c>intersect2D_2Segments</c>.</remarks>
        public static Segment2DIntersectSegment2DResult GetIntersectionBetweenSegments(Segment2D segment1, Segment2D segment2)
        {
            if (segment1 == null)
            {
                throw new ArgumentNullException(nameof(segment1));
            }

            if (segment2 == null)
            {
                throw new ArgumentNullException(nameof(segment2));
            }

            Vector <double> u = segment1.SecondPoint - segment1.FirstPoint;
            Vector <double> v = segment2.SecondPoint - segment2.FirstPoint;
            Vector <double> w = segment1.FirstPoint - segment2.FirstPoint;
            double          d = PerpDotProduct(u, v);

            if (Math.Abs(d) < epsilonForComparisons)
            {
                // Segments can be considered parallel...
                if (AreCollinear(u, v, w))
                {
                    // ... and collinear ...
                    if (IsSegmentAsPointIntersectionDegenerateScenario(segment1, segment2))
                    {
                        // ... but either or both segments are point degenerates:
                        return(HandleSegmentAsPointIntersectionDegenerates(segment1, segment2));
                    }

                    // ... so there is a possibility of overlapping or connected lines:
                    return(HandleCollinearSegmentIntersection(segment1, segment2, v, w));
                }

                // ... but not collinear, so no intersection possible:
                return(Segment2DIntersectSegment2DResult.CreateNoIntersectResult());
            }

            // Segments are at an angle and may intersect:
            double sI = PerpDotProduct(v, w) / d;

            if (sI < 0.0 || sI > 1.0)
            {
                return(Segment2DIntersectSegment2DResult.CreateNoIntersectResult());
            }

            double tI = PerpDotProduct(u, w) / d;

            if (tI < 0.0 || tI > 1.0)
            {
                return(Segment2DIntersectSegment2DResult.CreateNoIntersectResult());
            }

            Point2D intersectionPoint = segment1.FirstPoint + u.Multiply(sI);

            return(Segment2DIntersectSegment2DResult.CreateIntersectionResult(intersectionPoint));
        }
예제 #2
0
        private static Segment2DIntersectSegment2DResult HandleCollinearSegmentIntersection(Segment2D segment1, Segment2D segment2, Vector <double> v, Vector <double> w)
        {
            double          t0, t1;
            Vector <double> w2 = segment1.SecondPoint - segment2.FirstPoint;

            if (Math.Abs(v[0]) > double.Epsilon)
            {
                t0 = w[0] / v[0];
                t1 = w2[0] / v[0];
            }
            else
            {
                t0 = w[1] / v[1];
                t1 = w2[1] / v[1];
            }

            // Require t0 to be smaller than t1, swapping if needed:
            if (t0 > t1)
            {
                double tempSwapVariable = t0;
                t0 = t1;
                t1 = tempSwapVariable;
            }

            if (t0 > 1.0 || t1 < 0.0)
            {
                // There is no overlap:
                return(Segment2DIntersectSegment2DResult.CreateNoIntersectResult());
            }

            t0 = Math.Max(0.0, t0);
            t1 = Math.Min(1.0, t1);
            Point2D intersectionPoint1 = segment2.FirstPoint + v.Multiply(t0);

            if (Math.Abs(t0 - t1) < epsilonForComparisons)
            {
                // Segments intersect at a point:
                return(Segment2DIntersectSegment2DResult.CreateIntersectionResult(intersectionPoint1));
            }

            // Segments overlap:
            Point2D intersectionPoint2 = segment2.FirstPoint + v.Multiply(t1);

            return(Segment2DIntersectSegment2DResult.CreateOverlapResult(intersectionPoint1, intersectionPoint2));
        }
예제 #3
0
        private static Segment2DIntersectSegment2DResult HandleSegmentAsPointIntersectionDegenerates(Segment2D segment1, Segment2D segment2)
        {
            bool segment1IsPointDegenerate = IsSegmentActuallyPointDegenerate(segment1);
            bool segment2IsPointDegenerate = IsSegmentActuallyPointDegenerate(segment2);

            if (segment1IsPointDegenerate)
            {
                if (segment2IsPointDegenerate)
                {
                    // Both segments can be considered Point2D
                    return(segment1.FirstPoint.Equals(segment2.FirstPoint)
                               ? Segment2DIntersectSegment2DResult.CreateIntersectionResult(segment1.FirstPoint)
                               : Segment2DIntersectSegment2DResult.CreateNoIntersectResult());
                }

                return(IsPointInCollinearSegment(segment1.FirstPoint, segment2)
                           ? Segment2DIntersectSegment2DResult.CreateIntersectionResult(segment1.FirstPoint)
                           : Segment2DIntersectSegment2DResult.CreateNoIntersectResult());
            }

            return(IsPointInCollinearSegment(segment2.FirstPoint, segment1)
                       ? Segment2DIntersectSegment2DResult.CreateIntersectionResult(segment2.FirstPoint)
                       : Segment2DIntersectSegment2DResult.CreateNoIntersectResult());
        }