Пример #1
0
        /// <summary>
        /// Builds required crossing data.
        /// </summary>
        /// <param name="crossings">The crossings to calculate. (Note: collection is modified)</param>
        /// <param name="a">The left hand polygon.</param>
        /// <param name="b">The right hand polygon.</param>
        private PolygonCrossingsAlgorithmKernel CreateIntersectionKernelFromCrossings(List <PolygonCrossing> crossings, Polygon2 a, Polygon2 b)
        {
            Contract.Requires(crossings != null);
            Contract.Requires(a != null);
            Contract.Requires(b != null);
            Contract.Ensures(Contract.Result <PolygonCrossingsAlgorithmKernel>() != null);

            var kernel = new PolygonCrossingsAlgorithmKernel(a, b, crossings);

            if (crossings.Count == 0)
            {
                return(kernel);
            }

            foreach (var currentCrossing in crossings)
            {
                var ringIndexA = currentCrossing.LocationA.RingIndex;
                Contract.Assume(ringIndexA < a.Count);
                var ringA = a[ringIndexA];
                Contract.Assume(ringA != null);
                var crossingsOnRingA = kernel.RingCrossingsA.Get(ringIndexA);

                var priorPointA = FindPreviousRingPoint(currentCrossing, crossingsOnRingA, ringA, GetLocationA, PolygonCrossing.LocationAComparer.Default);
                var nextPointA  = FindNextRingPoint(currentCrossing, crossingsOnRingA, ringA, GetLocationA, PolygonCrossing.LocationAComparer.Default);

                var ringIndexB = currentCrossing.LocationB.RingIndex;
                Contract.Assume(ringIndexB < b.Count);
                var ringB = b[ringIndexB];
                Contract.Assume(ringB != null);
                var crossingsOnRingB = kernel.RingCrossingsB.Get(ringIndexB);

                var priorPointB = FindPreviousRingPoint(currentCrossing, crossingsOnRingB, ringB, GetLocationB, PolygonCrossing.LocationBComparer.Default);
                var nextPointB  = FindNextRingPoint(currentCrossing, crossingsOnRingB, ringB, GetLocationB, PolygonCrossing.LocationBComparer.Default);

                // based on the vectors, need to classify the crossing type
                currentCrossing.CrossType = PolygonCrossing.DetermineCrossingType(
                    (nextPointA - currentCrossing.Point).GetNormalized(),
                    (priorPointA - currentCrossing.Point).GetNormalized(),
                    (nextPointB - currentCrossing.Point).GetNormalized(),
                    (priorPointB - currentCrossing.Point).GetNormalized()
                    );
            }

            foreach (var ringCrossings in kernel.RingCrossingsA.RingCrossings)
            {
                Contract.Assume(ringCrossings.Key >= 0 && ringCrossings.Key < a.Count);
                if (a[ringCrossings.Key].FillSide == RelativeDirectionType.Right)
                {
                    foreach (var crossing in ringCrossings.Value)
                    {
                        Contract.Assume(crossing != null);
                        var crossLegType = crossing.CrossType & CrossingType.Parallel;
                        if (crossLegType == CrossingType.CrossToRight || crossLegType == CrossingType.DivergeRight)
                        {
                            kernel.Entrances.Add(crossing);
                        }
                        else if (crossLegType == CrossingType.CrossToLeft || crossLegType == CrossingType.ConvergeRight)
                        {
                            kernel.Exits.Add(crossing);
                        }
                    }
                }
                else
                {
                    foreach (var crossing in ringCrossings.Value)
                    {
                        Contract.Assume(crossing != null);
                        var crossLegType = crossing.CrossType & CrossingType.Parallel;
                        if (crossLegType == CrossingType.CrossToLeft || crossLegType == CrossingType.DivergeLeft)
                        {
                            kernel.Entrances.Add(crossing);
                        }
                        else if (crossLegType == CrossingType.CrossToRight || crossLegType == CrossingType.ConvergeLeft)
                        {
                            kernel.Exits.Add(crossing);
                        }
                    }
                }
            }

            var sortedEntrances = kernel.Entrances.ToArray();

            Array.Sort(sortedEntrances, PolygonCrossing.LocationAComparer.CompareNonNull);
            Contract.Assume(kernel.Exits != null);
            var sortedExits = kernel.Exits.ToArray();

            Array.Sort(sortedExits, PolygonCrossing.LocationBComparer.CompareNonNull);

            for (int i = 0; i < sortedExits.Length; i++)
            {
                var exit          = sortedExits[i];
                var locationIndex = Array.BinarySearch(sortedEntrances, exit, PolygonCrossing.LocationAComparer.Default);
                if (locationIndex >= 0)
                {
                    kernel.ExitHops.Add(exit, sortedEntrances[locationIndex]);
                }
            }
            for (int i = 0; i < sortedEntrances.Length; i++)
            {
                var entrance      = sortedEntrances[i];
                var locationIndex = Array.BinarySearch(sortedExits, entrance, PolygonCrossing.LocationBComparer.Default);
                if (locationIndex >= 0)
                {
                    kernel.EntranceHops.Add(entrance, sortedExits[locationIndex]);
                }
            }

            return(kernel);
        }
        /// <summary>
        /// Builds required crossing data. 
        /// </summary>
        /// <param name="crossings">The crossings to calculate. (Note: collection is modified)</param>
        /// <param name="a">The left hand polygon.</param>
        /// <param name="b">The right hand polygon.</param>
        private PolygonCrossingsAlgorithmKernel CreateIntersectionKernelFromCrossings(List<PolygonCrossing> crossings, Polygon2 a, Polygon2 b) {
            Contract.Requires(crossings != null);
            Contract.Requires(a != null);
            Contract.Requires(b != null);
            Contract.Ensures(Contract.Result<PolygonCrossingsAlgorithmKernel>() != null);

            var kernel = new PolygonCrossingsAlgorithmKernel(a, b, crossings);

            if (crossings.Count == 0)
                return kernel;

            foreach (var currentCrossing in crossings) {
                var ringIndexA = currentCrossing.LocationA.RingIndex;
                Contract.Assume(ringIndexA < a.Count);
                var ringA = a[ringIndexA];
                Contract.Assume(ringA != null);
                var crossingsOnRingA = kernel.RingCrossingsA.Get(ringIndexA);

                var priorPointA = FindPreviousRingPoint(currentCrossing, crossingsOnRingA, ringA, GetLocationA, PolygonCrossing.LocationAComparer.Default);
                var nextPointA = FindNextRingPoint(currentCrossing, crossingsOnRingA, ringA, GetLocationA, PolygonCrossing.LocationAComparer.Default);

                var ringIndexB = currentCrossing.LocationB.RingIndex;
                Contract.Assume(ringIndexB < b.Count);
                var ringB = b[ringIndexB];
                Contract.Assume(ringB != null);
                var crossingsOnRingB = kernel.RingCrossingsB.Get(ringIndexB);

                var priorPointB = FindPreviousRingPoint(currentCrossing, crossingsOnRingB, ringB, GetLocationB, PolygonCrossing.LocationBComparer.Default);
                var nextPointB = FindNextRingPoint(currentCrossing, crossingsOnRingB, ringB, GetLocationB, PolygonCrossing.LocationBComparer.Default);

                // based on the vectors, need to classify the crossing type
                currentCrossing.CrossType = PolygonCrossing.DetermineCrossingType(
                    (nextPointA - currentCrossing.Point).GetNormalized(),
                    (priorPointA - currentCrossing.Point).GetNormalized(),
                    (nextPointB - currentCrossing.Point).GetNormalized(),
                    (priorPointB - currentCrossing.Point).GetNormalized()
                );
            }

            foreach (var ringCrossings in kernel.RingCrossingsA.RingCrossings) {
                Contract.Assume(ringCrossings.Key >= 0 && ringCrossings.Key < a.Count);
                if (a[ringCrossings.Key].FillSide == RelativeDirectionType.Right) {
                    foreach (var crossing in ringCrossings.Value) {
                        Contract.Assume(crossing != null);
                        var crossLegType = crossing.CrossType & CrossingType.Parallel;
                        if (crossLegType == CrossingType.CrossToRight || crossLegType == CrossingType.DivergeRight)
                            kernel.Entrances.Add(crossing);
                        else if (crossLegType == CrossingType.CrossToLeft || crossLegType == CrossingType.ConvergeRight)
                            kernel.Exits.Add(crossing);
                    }
                }
                else {
                    foreach (var crossing in ringCrossings.Value) {
                        Contract.Assume(crossing != null);
                        var crossLegType = crossing.CrossType & CrossingType.Parallel;
                        if (crossLegType == CrossingType.CrossToLeft || crossLegType == CrossingType.DivergeLeft)
                            kernel.Entrances.Add(crossing);
                        else if (crossLegType == CrossingType.CrossToRight || crossLegType == CrossingType.ConvergeLeft)
                            kernel.Exits.Add(crossing);
                    }
                }
            }

            var sortedEntrances = kernel.Entrances.ToArray();
            Array.Sort(sortedEntrances, PolygonCrossing.LocationAComparer.CompareNonNull);
            Contract.Assume(kernel.Exits != null);
            var sortedExits = kernel.Exits.ToArray();
            Array.Sort(sortedExits, PolygonCrossing.LocationBComparer.CompareNonNull);

            for (int i = 0; i < sortedExits.Length; i++) {
                var exit = sortedExits[i];
                var locationIndex = Array.BinarySearch(sortedEntrances, exit, PolygonCrossing.LocationAComparer.Default);
                if(locationIndex >= 0)
                    kernel.ExitHops.Add(exit, sortedEntrances[locationIndex]);
            }
            for (int i = 0; i < sortedEntrances.Length; i++) {
                var entrance = sortedEntrances[i];
                var locationIndex = Array.BinarySearch(sortedExits, entrance, PolygonCrossing.LocationBComparer.Default);
                if(locationIndex >= 0)
                    kernel.EntranceHops.Add(entrance, sortedExits[locationIndex]);
            }

            return kernel;
        }