using System; using System.Collections; using GeoAPI.Geometries; namespace GisSharpBlog.NetTopologySuite.GeometriesGraph.Index { /// /// MonotoneChains are a way of partitioning the segments of an edge to /// allow for fast searching of intersections. /// They have the following properties: /// the segments within a monotone chain will never intersect each other, and /// the envelope of any contiguous subset of the segments in a monotone chain /// is simply the envelope of the endpoints of the subset. /// Property 1 means that there is no need to test pairs of segments from within /// the same monotone chain for intersection. /// Property 2 allows /// binary search to be used to find the intersection points of two monotone chains. /// For many types of real-world data, these properties eliminate a large number of /// segment comparisons, producing substantial speed gains. /// public class MonotoneChainIndexer { /// /// /// /// /// public static int[] ToIntArray(IList list) { int[] array = new int[list.Count]; for (int i = 0; i < array.Length; i++) array[i] = Convert.ToInt32(list[i]); return array; } /// /// Default empty constructor. /// public MonotoneChainIndexer() { } /// /// /// /// /// public int[] GetChainStartIndices(ICoordinate[] pts) { // find the startpoint (and endpoints) of all monotone chains in this edge int start = 0; IList startIndexList = new ArrayList(); startIndexList.Add(start); do { int last = FindChainEnd(pts, start); startIndexList.Add(last); start = last; } while (start < pts.Length - 1); // copy list to an array of ints, for efficiency int[] startIndex = ToIntArray(startIndexList); return startIndex; } /// /// The index of the last point in the monotone chain. /// /// private int FindChainEnd(ICoordinate[] pts, int start) { // determine quadrant for chain int chainQuad = QuadrantOp.Quadrant(pts[start], pts[start + 1]); int last = start + 1; while (last < pts.Length) { // compute quadrant for next possible segment in chain int quad = QuadrantOp.Quadrant(pts[last - 1], pts[last]); if (quad != chainQuad) break; last++; } return last - 1; } } }