/// <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);
        }
Пример #4
0
 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());