コード例 #1
0
            public PolygonCrossing[] Get(int ringIndex) {
                Contract.Requires(ringIndex >= 0);
                Contract.Ensures(Contract.Result<PolygonCrossing[]>() != null);
                Contract.Ensures(Contract.ForAll(Contract.Result<PolygonCrossing[]>(), x => x != null));
                if (_cache.Key == ringIndex)
                    return _cache.Value;

                PolygonCrossing[] crossings;
                if (!RingCrossings.TryGetValue(ringIndex, out crossings)) {
                    crossings = new PolygonCrossing[0];
                }
                _cache = new KeyValuePair<int, PolygonCrossing[]>(ringIndex, crossings);
                Contract.Assume(crossings != null);
                return crossings;
            }
コード例 #2
0
        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];
        }
コード例 #3
0
        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;
        }
コード例 #4
0
        private static Point2 FindNextRingPoint(
            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;
            int nextSegmentIndex = IterationUtils.AdvanceLoopingIndex(currentLocation.SegmentIndex, segmentCount);
            var nextCrossing = FindNextCrossingNotEqual(currentCrossing, crossingsOnRing, crossingComparer);
            // NOTE: this method assumes a segment ratio less than 1, verify we can trust this
            if (null == nextCrossing) {
                return ring[nextSegmentIndex];
            }
            var nextCrossingLocation = getLocation(nextCrossing);
            Contract.Assume(nextCrossingLocation != null);
            return currentLocation.SegmentIndex == nextCrossingLocation.SegmentIndex
                && currentLocation.SegmentRatio < nextCrossingLocation.SegmentRatio
                ? nextCrossing.Point
                : ring[nextSegmentIndex];
        }
コード例 #5
0
        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];
            }
        }
コード例 #6
0
 [Pure] private static int GetRingIndexB(PolygonCrossing crossing) {
     Contract.Requires(crossing != null);
     Contract.Ensures(Contract.Result<int>() >= 0);
     return crossing.LocationB.RingIndex;
 }
コード例 #7
0
 private PolygonCrossing TraverseBSide(
     PolygonCrossing entrance,
     List<Point2> buildingRing
 ) {
     Contract.Requires(entrance != null);
     Contract.Requires(buildingRing != null);
     Contract.Ensures(buildingRing.Count >= Contract.OldValue(buildingRing).Count);
     PolygonCrossing exit;
     do {
         exit = TraverseBSideRing(buildingRing, entrance, RingCrossingsB.Get(entrance.LocationB.RingIndex));
         if (exit == null)
             return null;
     } while ((entrance = TraverseBSideHops(exit)) != null);
     return exit;
 }
コード例 #8
0
 [Pure] private static PolygonBoundaryLocation GetLocationB(PolygonCrossing crossing) {
     Contract.Requires(crossing != null);
     Contract.Ensures(Contract.Result<PolygonBoundaryLocation>() != null);
     return crossing.LocationB;
 }
コード例 #9
0
            private PolygonCrossing TraverseBSideRing(
                List<Point2> buildingRing,
                PolygonCrossing fromCrossing,
                PolygonCrossing[] ringCrossings
            ) {
                Contract.Requires(buildingRing != null);
                Contract.Requires(fromCrossing != null);
                Contract.Requires(ringCrossings != null);
                Contract.Requires(Contract.ForAll(ringCrossings, x => x != null));
                Contract.Ensures(buildingRing.Count >= Contract.OldValue(buildingRing).Count);

                var fromSegmentLocationB = fromCrossing.LocationB;
                if (0 == buildingRing.Count || buildingRing[buildingRing.Count - 1] != fromCrossing.Point)
                    buildingRing.Add(fromCrossing.Point);

                var fromCrossingIndex = Array.BinarySearch(ringCrossings, fromCrossing, PolygonCrossing.LocationBComparer.Default);
                Contract.Assume(fromCrossingIndex >= 0);
                foreach (var crossing in TraverseCrossings(fromCrossing, ringCrossings, fromCrossingIndex)) {
                    // hops should have already been taken care of
                    if (crossing.Point == fromCrossing.Point && ExitHops.ContainsKey(crossing))
                        continue; // no, lets go somewhere useful with this

                    var locationB = crossing.LocationB;
                    Contract.Assume(locationB.RingIndex < B.Count);
                    Contract.Assume(B[locationB.RingIndex] != null);
                    AddPointsBetweenForward(buildingRing, B[locationB.RingIndex], fromSegmentLocationB, locationB);
                    fromSegmentLocationB = locationB; // for later...

                    if (Exits.Contains(crossing))
                        return crossing; // if we found it, stop

                    if (buildingRing.Count == 0 || buildingRing[buildingRing.Count - 1] != crossing.Point)
                        buildingRing.Add(crossing.Point); // if it is something else, lets add it
                }
                return null;
            }
コード例 #10
0
 private PolygonCrossing TraverseBSideHops(PolygonCrossing start) {
     Contract.Requires(start != null);
     PolygonCrossing current = start;
     PolygonCrossing result = null;
     PolygonCrossing next;
     while (
         Exits.Contains(current)
         && ExitHops.TryGetValue(current, out next)
         && Entrances.Contains(next)
         && next.LocationB != start.LocationB
     ) {
         result = next;
         VisitEntrance(next);
         Contract.Assume(current != null);
         VisitExit(current);
         if (!EntranceHops.TryGetValue(next, out current))
             break;
     }
     return result;
 }
コード例 #11
0
 private void VisitExit(PolygonCrossing exit) {
     Contract.Requires(exit != null);
     if (Exits.Remove(exit))
         ApplyCrossingVisit(exit);
 }
コード例 #12
0
 private void VisitEntrance(PolygonCrossing entrance) {
     Contract.Requires(entrance != null);
     if (Entrances.Remove(entrance))
         ApplyCrossingVisit(entrance);
 }
コード例 #13
0
 private void ApplyCrossingVisit(PolygonCrossing crossing) {
     Contract.Requires(crossing != null);
     VisitedCrossings.Add(crossing);
     VisitedCrossingsRingIndicesA.Add(crossing.LocationA.RingIndex);
     VisitedCrossingsRingIndicesB.Add(crossing.LocationB.RingIndex);
 }