private static IEnumerable <SegmentIntersection> GetSegmentIntersectionsXY( int sourceLineIdx, [NotNull] Line3D sourceLine, [NotNull] ISegmentList segmentList, double tolerance, [CanBeNull] SegmentIntersection previousLinearIntersection) { if (previousLinearIntersection != null) { // speculation: this segment also runs along the next / previous target SegmentIntersection continuousIntersection = TryGetContinuousLinearIntersection( sourceLineIdx, sourceLine, segmentList, previousLinearIntersection, tolerance); if (continuousIntersection != null) { yield return(continuousIntersection); yield break; } } IEnumerable <KeyValuePair <int, Line3D> > segmentsByIndex = segmentList.FindSegments(sourceLine, tolerance); foreach (SegmentIntersection intersection in IntersectLineWithLinestringXY( sourceLine, sourceLineIdx, segmentsByIndex, tolerance)) { yield return(intersection); } }
public static bool LinesContainXY([NotNull] ISegmentList segments, [NotNull] Pnt3D testPoint, double tolerance) { foreach (KeyValuePair <int, Line3D> segmentsAroundPoint in segments.FindSegments(testPoint, tolerance)) { Line3D segment = segmentsAroundPoint.Value; if (segment.IntersectsPointXY(testPoint, tolerance)) { return(true); } } return(false); }
/// <summary> /// Returns all self intersections except the intersection between consecutive segments. /// </summary> /// <param name="sourceLineGlobalIdx"></param> /// <param name="sourceLine"></param> /// <param name="containingSegmentList"></param> /// <param name="tolerance"></param> /// <returns></returns> public static IEnumerable <SegmentIntersection> GetRelevantSelfIntersectionsXY( int sourceLineGlobalIdx, [NotNull] Line3D sourceLine, [NotNull] ISegmentList containingSegmentList, double tolerance) { // a predicate, i.e. i != sourceGlobalIdx && i != sourceGlobalIdx - 1 && i != sourceGlobalIdx + 1 Predicate <int> predicate = i => i != sourceLineGlobalIdx; IEnumerable <KeyValuePair <int, Line3D> > segmentsByGlobalIdx = containingSegmentList.FindSegments(sourceLine, tolerance, true, predicate); foreach (SegmentIntersection intersection in IntersectLineWithLinestringXY( sourceLine, sourceLineGlobalIdx, segmentsByGlobalIdx, tolerance)) { int?nextSegmentIndex = containingSegmentList.NextSegmentIndex(intersection.SourceIndex); if (nextSegmentIndex == intersection.TargetIndex && !intersection.HasLinearIntersection) { continue; } int?previousSegmentIndex = containingSegmentList.PreviousSegmentIndex(intersection.SourceIndex); if (previousSegmentIndex == intersection.TargetIndex && !intersection.HasLinearIntersection) { continue; } yield return(intersection); } }
/// <summary> /// Determines whether the horizontal ray from the test point to XMin crosses /// the specified segments an odd number of times. /// NOTE: For test points exactly on the boundary the result depends on whether /// the the point is on the right or the left boundary! /// </summary> /// <param name="segments"></param> /// <param name="testPoint"></param> /// <param name="tolerance"></param> /// <returns></returns> private static bool HasRayOddCrossingNumber([NotNull] ISegmentList segments, [NotNull] IPnt testPoint, double tolerance) { bool result = false; // Get the intersecting segments along the horizontal line from XMin to the testPoint IEnumerable <KeyValuePair <int, Line3D> > intersectingSegments = segments.FindSegments(segments.XMin, testPoint.Y, testPoint.X, testPoint.Y, tolerance); foreach (KeyValuePair <int, Line3D> path2Segment in intersectingSegments.OrderBy( kvp => kvp.Key)) { Line3D segment = path2Segment.Value; Pnt3D previous = segment.StartPoint; Pnt3D vertex = segment.EndPoint; if (vertex.Y < testPoint.Y && previous.Y >= testPoint.Y || // downward crossing previous.Y < testPoint.Y && vertex.Y >= testPoint.Y) // upward crossing { double dX = previous.X - vertex.X; double dY = previous.Y - vertex.Y; double y = testPoint.Y - vertex.Y; if (vertex.X + y * dX / dY < testPoint.X) { result = !result; } } } return(result); }