Example #1
0
        public Segment Intersection(Segment segment)
        {
            // if either segment is empty, the intersection is also empty
            if (IsEmpty || segment.IsEmpty)
            {
                return(Empty);
            }

            // if the segments are equal, just return a new equal segment
            if (this == segment)
            {
                return(new Segment(_p1, _p2, IsP1Excluded, IsP2Excluded));
            }

            // if either segment is a Point, just see if the point is contained in the other segment
            if (IsPoint)
            {
                return(segment.Contains(_p1) ? new Segment(_p1) : Empty);
            }

            if (segment.IsPoint)
            {
                return(Contains(segment._p1) ? new Segment(segment._p1) : Empty);
            }

            // okay, no easy answer, so let's do the math...
            var p1             = _p1;
            var v1             = _p2 - _p1;
            var p2             = segment._p1;
            var v2             = segment._p2 - segment._p1;
            var endpointVector = p2 - p1;

            var xProd = Vector.CrossProduct(v1, v2);

            // if segments are not parallel, then look for intersection on each segment
            if (!DoubleHelper.AreVirtuallyEqual(Slope, segment.Slope))
            {
                // check for intersection on other segment
                var s = Vector.CrossProduct(endpointVector, v1) / xProd;
                if (s < 0 || s > 1)
                {
                    return(Empty);
                }

                // check for intersection on this segment
                s = Vector.CrossProduct(endpointVector, v2) / xProd;
                if (s < 0 || s > 1)
                {
                    return(Empty);
                }

                // intersection of segments is a point
                return(new Segment(p1 + s * v1));
            }

            // segments are parallel
            xProd = Vector.CrossProduct(endpointVector, v1);
            if (xProd * xProd > 1.0e-06 * v1.LengthSquared * endpointVector.LengthSquared)
            {
                // segments do not intersect
                return(Empty);
            }

            // intersection is overlapping segment
            var result = new Segment();

            // to determine the overlapping segment, create reference segments where the endpoints are *not* excluded
            var refThis    = new Segment(_p1, _p2);
            var refSegment = new Segment(segment._p1, segment._p2);

            // check whether this segment is contained in the other segment
            var includeThisP1 = refSegment.Contains(refThis._p1);
            var includeThisP2 = refSegment.Contains(refThis._p2);

            if (includeThisP1 && includeThisP2)
            {
                result._p1          = _p1;
                result._p2          = _p2;
                result.IsP1Excluded = IsP1Excluded || !segment.Contains(_p1);
                result.IsP2Excluded = IsP2Excluded || !segment.Contains(_p2);
                return(result);
            }

            // check whether the other segment is contained in this segment
            var includeSegmentP1 = refThis.Contains(refSegment._p1);
            var includeSegmentP2 = refThis.Contains(refSegment._p2);

            if (includeSegmentP1 && includeSegmentP2)
            {
                result._p1          = segment._p1;
                result._p2          = segment._p2;
                result.IsP1Excluded = segment.IsP1Excluded || !Contains(segment._p1);
                result.IsP2Excluded = segment.IsP2Excluded || !Contains(segment._p2);
                return(result);
            }

            // the intersection must include one endpoint from this segment and one endpoint from the other segment
            if (includeThisP1)
            {
                result._p1          = _p1;
                result.IsP1Excluded = IsP1Excluded || !segment.Contains(_p1);
            }
            else
            {
                result._p1          = _p2;
                result.IsP1Excluded = IsP2Excluded || !segment.Contains(_p2);
            }

            if (includeSegmentP1)
            {
                result._p2          = segment._p1;
                result.IsP2Excluded = segment.IsP1Excluded || !Contains(segment._p1);
            }
            else
            {
                result._p2          = segment._p2;
                result.IsP2Excluded = segment.IsP2Excluded || !Contains(segment._p2);
            }

            return(result);
        }