public static Either <Null, Point2D, Segment2D> IntersectWithDisk(this Segment2D segment, Circle2D diskBoundary) { var lineIntersectionsWithBoundary = diskBoundary.IntersectWithLine(segment.AsLine()).ToList(); if (lineIntersectionsWithBoundary.Count == 0) { return(Null.Instance); } if (lineIntersectionsWithBoundary.Count == 1) { var point = lineIntersectionsWithBoundary.Single(); if (segment.Contains(point)) { return(point); } return(Null.Instance); } var segmentDirection = segment.GetDirection(); var(baseSideIntersection, endSideIntersection) = (lineIntersectionsWithBoundary[0], lineIntersectionsWithBoundary[1]).ReverseIf( (lineIntersectionsWithBoundary[0].DirectionTo(lineIntersectionsWithBoundary[1]) .Value .DotProduct(segmentDirection) ) < 0); var clipBase = (baseSideIntersection - segment.BasePoint).GetComponentInDirection(segmentDirection) > Unit.ZeroDistance; var clipEnd = (endSideIntersection - segment.EndPoint).GetComponentInDirection(segmentDirection) < Unit.ZeroDistance; var clippedBase = clipBase ? baseSideIntersection : segment.BasePoint; var clippedEnd = clipEnd ? endSideIntersection : segment.EndPoint; if (clippedBase == clippedEnd) { return(clipBase ? segment.EndPoint : segment.BasePoint); } var signedDistance = (clippedEnd - clippedBase).GetComponentInDirection(segmentDirection); if (signedDistance > Unit.ZeroDistance) { return(new Segment2D(clippedBase, clippedEnd)); } return(Null.Instance); }
public static IEnumerable <Point2D> IntersectWithLine(this Circle2D circle, Line2D line) => circle.IntersectWithLine(line.AsBoundaryLine());