public static IEnumerable <Point2D> IntersectWithLine(this Circle2D circle, BoundaryLine2D line) { var offsetToCenter = line.HalfPlane.GetOffsetFromBoundaryTowardInside(circle.Center); if (!(offsetToCenter.AbsoluteValue() <= circle.Radius)) { return(Enumerable.Empty <Point2D>()); } var intersectionOfLineWithPerpendicularRadius = circle.Center + line.HalfPlane.DirectionTowardInterior.ToVector(-offsetToCenter); var distanceFromPerpendicularRadiusToIntersectionsSquared = circle.Radius.Square() - offsetToCenter.Square(); // If it's negative, the line doesn't quite intersect the circle. if (distanceFromPerpendicularRadiusToIntersectionsSquared > Unit.ZeroArea) { var distanceFromPerpendicularRadiusToIntersections = distanceFromPerpendicularRadiusToIntersectionsSquared.SquareRoot(); var intersectionPoints = line .ParallelDirections .Select(direction => intersectionOfLineWithPerpendicularRadius + direction.ToVector(distanceFromPerpendicularRadiusToIntersections)) .ToList(); if (intersectionPoints.DistinctEquatable().Count() > 1) { return(intersectionPoints); } } return(intersectionOfLineWithPerpendicularRadius.Singleton()); }
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());