private static List <PolygonCrossing> GenerateRingCrossingsBruteForce(Ring2 ringA, Ring2 ringB, int ringIndexA, int ringIndexB) { Contract.Requires(ringA != null); Contract.Requires(ringA.Count > 0); Contract.Requires(ringB != null); Contract.Requires(ringB.Count > 0); Contract.Requires(ringIndexA >= 0); Contract.Requires(ringIndexB >= 0); Contract.Ensures(Contract.Result <List <PolygonCrossing> >() != null); var ringACount = ringA.Count; var ringBCount = ringB.Count; var segmentStartIndexA = ringACount - 1; var b = ringA[segmentStartIndexA]; var crossings = new List <PolygonCrossing>(); for (int segmentEndIndexA = 0; segmentEndIndexA < ringACount; segmentStartIndexA = segmentEndIndexA++) { var a = b; b = ringA[segmentEndIndexA]; var segmentDataA = new Segment2Data( new Segment2(a, b), segmentStartIndexA, ringIndexA ); var segmentMbrA = segmentDataA.Segment.GetMbr(); var segmentStartIndexB = ringBCount - 1; var d = ringB[segmentStartIndexB]; for (int segmentEndIndexB = 0; segmentEndIndexB < ringBCount; segmentStartIndexB = segmentEndIndexB++) { var c = d; d = ringB[segmentEndIndexB]; if (!segmentMbrA.Intersects(c, d)) { continue; } AddPointCrossings( crossings, segmentDataA, new Segment2Data( new Segment2(c, d), segmentStartIndexB, ringIndexB ) ); } } return(crossings); }
private static PolygonCrossing CreatePolygonCrossing( SegmentIntersectionOperation.PointResult pointResult, Segment2Data segmentDataA, Segment2Data segmentDataB ) { Contract.Ensures(Contract.Result <PolygonCrossing>() != null); Contract.Assume(segmentDataA.RingIndex >= 0); Contract.Assume(segmentDataA.SegmentIndex >= 0); Contract.Assume(segmentDataB.RingIndex >= 0); Contract.Assume(segmentDataB.SegmentIndex >= 0); return(new PolygonCrossing( pointResult.P, new PolygonBoundaryLocation(segmentDataA.RingIndex, segmentDataA.SegmentIndex, pointResult.S), new PolygonBoundaryLocation(segmentDataB.RingIndex, segmentDataB.SegmentIndex, pointResult.T) )); }
private static void AddPointCrossings(List <PolygonCrossing> results, Segment2Data segmentDataA, Segment2Data segmentDataB) { Contract.Requires(results != null); Contract.Ensures(results.Count >= Contract.OldValue(results).Count); Contract.Assume(null != segmentDataA.Segment); Contract.Assume(null != segmentDataB.Segment); var intersectionDetails = SegmentIntersectionOperation.IntersectionDetails(segmentDataA.Segment, segmentDataB.Segment); if (intersectionDetails is SegmentIntersectionOperation.PointResult) { var pointResult = (SegmentIntersectionOperation.PointResult)intersectionDetails; if (IsNotHead(pointResult)) { results.Add(CreatePolygonCrossing(pointResult, segmentDataA, segmentDataB)); } } else if (intersectionDetails is SegmentIntersectionOperation.SegmentResult) { var segmentResult = intersectionDetails as SegmentIntersectionOperation.SegmentResult; var bIsNotHead = IsNotHead(segmentResult.B); if (IsNotHead(segmentResult.A)) { var resultA = CreatePolygonCrossing(segmentResult.A, segmentDataA, segmentDataB); if (bIsNotHead) { results.AddRange(new[] { resultA, CreatePolygonCrossing(segmentResult.B, segmentDataA, segmentDataB) }); } else { results.Add(resultA); } } else if (bIsNotHead) { results.Add(CreatePolygonCrossing(segmentResult.B, segmentDataA, segmentDataB)); } } }
/// <summary> /// Determines the points that would need to be inserted into the resulting /// intersection geometry between the two given rings, at the location where /// their boundaries cross. /// </summary> /// <param name="ringA">The first ring to test.</param> /// <param name="ringB">The second ring to test.</param> /// <param name="ringIndexA">The ring index on polygon a.</param> /// <param name="ringIndexB">The ring index on polygon b.</param> private List <PolygonCrossing> GenerateRingCrossingsSorted(Ring2 ringA, Ring2 ringB, int ringIndexA, int ringIndexB) { Contract.Requires(ringA != null); Contract.Requires(ringA.Count > 0); Contract.Requires(ringIndexA >= 0); Contract.Requires(ringIndexA < ringA.Count); Contract.Requires(ringB != null); Contract.Requires(ringB.Count > 0); Contract.Requires(ringIndexB >= 0); Contract.Requires(ringIndexB < ringB.Count); Contract.Ensures(Contract.Result <List <PolygonCrossing> >() != null); int minSegmentSearchIndicesB = 0; var segmentSearchIndicesA = GetSortedRingSegmentIndices(ringA); var segmentSearchIndicesB = GetSortedRingSegmentIndices(ringB); var countA = ringA.Count; var countB = ringB.Count; var crossings = new List <PolygonCrossing>(); for (var segmentSearchIndexA = 0; segmentSearchIndexA < segmentSearchIndicesA.Length; segmentSearchIndexA++) { double temp; var segmentStartIndexA = segmentSearchIndicesA[segmentSearchIndexA]; Contract.Assume(segmentStartIndexA >= 0); Contract.Assume(segmentStartIndexA < ringA.Count); var a = ringA[segmentStartIndexA]; var smallestXValueOnA = a.X; var b = ringA[IterationUtils.AdvanceLoopingIndex(segmentStartIndexA, countA)]; var largestXValueOnA = b.X; if (largestXValueOnA < smallestXValueOnA) { temp = largestXValueOnA; largestXValueOnA = smallestXValueOnA; smallestXValueOnA = temp; } var segmentDataA = new Segment2Data( new Segment2(a, b), segmentStartIndexA, ringIndexA ); var segmentAMbr = segmentDataA.Segment.GetMbr(); for (int segmentSearchIndexB = minSegmentSearchIndicesB; segmentSearchIndexB < segmentSearchIndicesB.Length; segmentSearchIndexB++) { int segmentStartIndexB = segmentSearchIndicesB[segmentSearchIndexB]; Contract.Assume(segmentStartIndexB >= 0); Contract.Assume(segmentStartIndexB < ringB.Count); var c = ringB[segmentStartIndexB]; var smallestXValueOnC = c.X; var d = ringB[IterationUtils.AdvanceLoopingIndex(segmentStartIndexB, countB)]; var largestXValueOnD = d.X; if (largestXValueOnD < smallestXValueOnC) { temp = largestXValueOnD; largestXValueOnD = smallestXValueOnC; smallestXValueOnC = temp; } //if (largestXValueOnD < smallestXValueOnA) { // minSegmentSearchIndicesB = segmentSearchIndexB + 1; // continue; //} if (smallestXValueOnC > largestXValueOnA) { break; } if (!segmentAMbr.Intersects(c, d)) { continue; } AddPointCrossings( crossings, segmentDataA, new Segment2Data( new Segment2(c, d), segmentStartIndexB, ringIndexB ) ); } if (minSegmentSearchIndicesB >= segmentSearchIndicesB.Length) { break; // wont do anything else } } return(crossings); }