/// <summary> /// Find the intersection of the segment with the half-plane and throw away the result if it is contained /// entirely in the boundary of the half-plane. The method name is a little imprecise, but it gets across the /// basic idea. /// </summary> public static Segment2D IntersectWithOpenHalfPlane(this Segment2D segment, HalfPlane2D halfPlane) { var basePointOffset = halfPlane.GetOffsetFromBoundaryTowardInside(segment.BasePoint); var endPointOffset = halfPlane.GetOffsetFromBoundaryTowardInside(segment.EndPoint); var basePointIsInInterior = !(basePointOffset <= Unit.ZeroDistance); var endPointIsInInterior = !(endPointOffset <= Unit.ZeroDistance); if (!basePointIsInInterior && !endPointIsInInterior) { return(null); } var containsBasePointExactly = !(basePointOffset < Unit.ZeroDistance); var containsEndPointExactly = !(endPointOffset < Unit.ZeroDistance); if (containsBasePointExactly && containsEndPointExactly) { return(segment); } var pointOnBoundary = halfPlane.Boundary.PointIntersectionWithLine(segment.AsLine()); return (containsBasePointExactly ? new Segment2D(segment.BasePoint, pointOnBoundary.Value) : new Segment2D(pointOnBoundary.Value, segment.EndPoint)); }
public static Either <Null, Point2D, Segment2D> IntersectWithLine(this Segment2D segment, BoundaryLine2D line) { var baseOffset = line.HalfPlane.GetOffsetFromBoundaryTowardInside(segment.BasePoint); var endOffset = line.HalfPlane.GetOffsetFromBoundaryTowardInside(segment.EndPoint); var lineContainsBase = baseOffset == Unit.ZeroDistance; var lineContainsEnd = endOffset == Unit.ZeroDistance; if (lineContainsBase && lineContainsEnd) { return(segment); } if (baseOffset.Sign() != endOffset.Sign()) { return(segment.AsLine().PointIntersectionWithLineUnstable(line)); } if (lineContainsBase) { return(segment.BasePoint); } if (lineContainsEnd) { return(segment.EndPoint); } return(Null.Instance); }
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 Distance DistanceTo(this Point2D point, Segment2D segment) => point.ProjectedSignedDistanceAlong(segment.AsLine()) < Distance.Zero ? point.DistanceTo(segment.BasePoint) : point.ProjectedSignedDistanceAlong(segment.Reverse().AsLine()) < Distance.Zero ? point.DistanceTo(segment.EndPoint) : point.DistanceTo(segment.AsLine());