/// <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; }