private static PolygonCrossing FindPreviousCrossingNotEqual( PolygonCrossing currentCrossing, PolygonCrossing[] crossingsOnRing, IComparer <PolygonCrossing> crossingComparer ) { Contract.Requires(currentCrossing != null); Contract.Requires(crossingsOnRing != null); Contract.Requires(Contract.ForAll(crossingsOnRing, x => x != null)); Contract.Requires(crossingComparer != null); var currentPoint = currentCrossing.Point; int currentCrossingIndex = Array.BinarySearch(crossingsOnRing, currentCrossing, crossingComparer); if (currentCrossingIndex < 0) { return(null); } int crossingsCount = crossingsOnRing.Length; // find the first crossing before this one that has a different point location for ( int i = IterationUtils.RetreatLoopingIndex(currentCrossingIndex, crossingsCount); i != currentCrossingIndex; i = IterationUtils.RetreatLoopingIndex(i, crossingsCount) ) { var crossing = crossingsOnRing[i]; if (crossing.Point != currentPoint) { return(crossing); } } return(null); }
private static IEnumerable <PolygonCrossing> TraverseCrossings( PolygonCrossing fromCrossing, PolygonCrossing[] ringCrossings, int fromCrossingIndex ) { Contract.Requires(fromCrossing != null); Contract.Requires(ringCrossings != null); //Contract.Requires(crossingComparer != null); Contract.Requires(fromCrossingIndex >= 0); Contract.Ensures(Contract.Result <IEnumerable <PolygonCrossing> >() != null); //var fromCrossingIndex = ringCrossings.BinarySearch(fromCrossing, crossingComparer); var ringCrossingsCount = ringCrossings.Length; Stack <PolygonCrossing> priorResults = null; var backTrackIndex = fromCrossingIndex; do { var priorIndex = IterationUtils.RetreatLoopingIndex(backTrackIndex, ringCrossingsCount); var priorCrossing = ringCrossings[priorIndex]; if (priorCrossing.Point != fromCrossing.Point) { break; } backTrackIndex = priorIndex; (priorResults ?? (priorResults = new Stack <PolygonCrossing>())) .Push(priorCrossing); } while (backTrackIndex != fromCrossingIndex); if (null != priorResults) { while (priorResults.Count > 0) { yield return(priorResults.Pop()); } } for ( int i = IterationUtils.AdvanceLoopingIndex(fromCrossingIndex, ringCrossingsCount); i != fromCrossingIndex; i = IterationUtils.AdvanceLoopingIndex(i, ringCrossingsCount) ) { yield return(ringCrossings[i]); } }
private static Point2 FindPreviousRingPoint( PolygonCrossing currentCrossing, PolygonCrossing[] crossingsOnRing, Ring2 ring, Func <PolygonCrossing, PolygonBoundaryLocation> getLocation, IComparer <PolygonCrossing> crossingComparer ) { Contract.Requires(currentCrossing != null); Contract.Requires(crossingsOnRing != null); Contract.Requires(Contract.ForAll(crossingsOnRing, x => x != null)); Contract.Requires(ring != null); Contract.Requires(getLocation != null); Contract.Requires(crossingComparer != null); var currentLocation = getLocation(currentCrossing); var segmentCount = ring.SegmentCount; Contract.Assume(currentLocation.SegmentIndex < segmentCount); var previousSegmentIndex = IterationUtils.RetreatLoopingIndex(currentLocation.SegmentIndex, segmentCount); var previousCrossing = FindPreviousCrossingNotEqual(currentCrossing, crossingsOnRing, crossingComparer); if (null == previousCrossing) { return(ring[ currentLocation.SegmentRatio == 0 ? previousSegmentIndex : currentLocation.SegmentIndex ]); } var previousCrossingLocation = getLocation(previousCrossing); Contract.Assume(previousCrossingLocation != null); if (currentLocation.SegmentRatio == 0) { return(previousSegmentIndex == previousCrossingLocation.SegmentIndex ? previousCrossing.Point : ring[previousSegmentIndex]); } return(currentLocation.SegmentIndex == previousCrossingLocation.SegmentIndex && currentLocation.SegmentRatio > previousCrossingLocation.SegmentRatio ? previousCrossing.Point : ring[currentLocation.SegmentIndex]); }