/// <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)); }
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)); }
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()); }