Exemple #1
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]);
        }
Exemple #2
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);
        }
Exemple #3
0
        private static void AddPointsBetweenForward(
            List <Point2> results,
            Ring2 ring,
            PolygonBoundaryLocation from,
            PolygonBoundaryLocation to
            )
        {
            Contract.Requires(results != null);
            Contract.Requires(ring != null);
            Contract.Requires(from != null);
            Contract.Requires(to != null);
            Contract.Ensures(results.Count >= Contract.OldValue(results).Count);

            if (from.SegmentIndex == to.SegmentIndex && from.SegmentRatio <= to.SegmentRatio)
            {
                return; // no points will result from this
            }
            var segmentCount        = ring.SegmentCount;
            var currentSegmentIndex = IterationUtils.AdvanceLoopingIndex(from.SegmentIndex, segmentCount);

            do
            {
                if (to.SegmentIndex == currentSegmentIndex)
                {
                    if (to.SegmentRatio > 0)
                    {
                        results.Add(ring[currentSegmentIndex]);
                    }
                    return;
                }
                results.Add(ring[currentSegmentIndex]);
                currentSegmentIndex = IterationUtils.AdvanceLoopingIndex(currentSegmentIndex, segmentCount);
            } while (true);
        }
Exemple #4
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]);
            }
        }
Exemple #5
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]);
        }
        private static int Compare(int indexAStart, int indexBStart, Ring2 ring)
        {
            Contract.Requires(ring != null);
            Contract.Requires(indexAStart >= 0);
            Contract.Requires(indexAStart < ring.Count);
            Contract.Requires(indexBStart >= 0);
            Contract.Requires(indexBStart < ring.Count);

            var ax = ring[indexAStart].X;
            var bx = ring[IterationUtils.AdvanceLoopingIndex(indexAStart, ring.Count)].X;
            var cx = ring[indexBStart].X;
            var dx = ring[IterationUtils.AdvanceLoopingIndex(indexBStart, ring.Count)].X;
            int compareResult;

            if (dx < cx)
            {
                compareResult = Math.Min(ax, bx).CompareTo(dx);
                return(compareResult != 0 ? compareResult : Math.Max(ax, bx).CompareTo(cx));
            }
            compareResult = Math.Min(ax, bx).CompareTo(cx);
            return(compareResult != 0 ? compareResult : Math.Max(ax, bx).CompareTo(dx));
        }
        /// <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);
        }