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