/// <summary> /// Initializes a new instance of the <see cref="McIndexPointSnapper"/> class. /// </summary> /// <param name="index"></param> public McIndexPointSnapper(ISpatialIndex index) { _index = (StRtree)index; }
/// <summary> /// /// </summary> /// <param name="container"></param> public AnonymousYComparerImpl(StRtree container) { _container = container; }
private static QuadTree<byte> BuildQuadTree(StRtree Tree, Dictionary<string, byte> Countries, Coordinate TopLeft, Coordinate BottomRight, int MaxDepth, int Depth = 0) { // Bounding box for this node. var envelope = new Envelope(TopLeft, BottomRight); // Find all countries whose bounding boxes intersect with this node. var coarseResults = Tree.Query(envelope); // Of those countries, find those whose geometry actually intersects with this node. var fineResults = (from Tuple<string, IGeometry> r in coarseResults select r).Where(r => r.Item2.Intersects(envelope.ToPolygon())); // In case of either: // 1) No countries intersect, in which case we mark this node as empty. Or; // 2) Exactly one country intersects, in which case we mark this node as that country. var results = fineResults as IList<Tuple<string, IGeometry>> ?? fineResults.ToList(); if (results.Count() <= 1) { var country = results.FirstOrDefault(); var countryName = country != null ? country.Item1 : ""; Console.WriteLine("Adding {0}, Depth {1}, {2}x{3}", countryName, Depth, BottomRight.X - TopLeft.X, BottomRight.Y - TopLeft.Y); ++_nleafs; return new QuadTreeLeaf<byte> { Data = Countries[countryName], TopLeft = TopLeft.ToGeomoirCoordinate(), BottomRight = BottomRight.ToGeomoirCoordinate() }; } // If we have reached the maximum depth and multiple countries interect // with this node, mark it as the country with the largest overlap. if (Depth >= MaxDepth) { byte label = 0; // Take country with largest area intersecting. var r = (from Tuple<string, IGeometry> t in results orderby t.Item2.Intersection(envelope.ToPolygon()).Area descending select t).First(); if (r.Item2.Intersection(envelope.ToPolygon()).Area > 0) label = Countries[r.Item1]; ++_nleafs; return new QuadTreeLeaf<byte> { Data = label, TopLeft = TopLeft.ToGeomoirCoordinate(), BottomRight = BottomRight.ToGeomoirCoordinate() }; } // Split the node into 4 quadrants and recurse on each. var middleTop = new Coordinate((BottomRight.X + TopLeft.X) / 2, TopLeft.Y); var middleBottom = new Coordinate((BottomRight.X + TopLeft.X) / 2, BottomRight.Y); var middleLeft = new Coordinate(TopLeft.X, (BottomRight.Y + TopLeft.Y) / 2); var middleRight = new Coordinate(BottomRight.X, (BottomRight.Y + TopLeft.Y) / 2); var middle = new Coordinate(middleTop.X, middleLeft.Y); return new QuadTreeNode<byte> { TopLeft = TopLeft.ToGeomoirCoordinate(), BottomRight = BottomRight.ToGeomoirCoordinate(), Children = new [] { BuildQuadTree(Tree, Countries, TopLeft, middle, MaxDepth, Depth + 1), BuildQuadTree(Tree, Countries, middleTop, middleRight, MaxDepth, Depth + 1), BuildQuadTree(Tree, Countries, middleLeft, middleBottom, MaxDepth, Depth + 1), BuildQuadTree(Tree, Countries, middle, BottomRight, MaxDepth, Depth + 1) } }; }
// Loads a shapefile (*.shp), i.e. downloaded from http://www.naturalearthdata.com/, // adds each polygon to an R-tree, and adds each country name to a dictionary. private static void ProcessShapeFile(string ShapeFilePath, out StRtree Tree, out Dictionary<string, byte> Countries) { Countries = new Dictionary<string, byte>(); Countries.Add(string.Empty, 0); using (var p = Shapefile.OpenFile(ShapeFilePath)) { Tree = new StRtree(p.NumRows()); for (int i = 0; i < p.NumRows(); ++i) { var row = p.GetFeature(i); var country = row.DataRow["name"].ToString(); checked { } if (!Countries.ContainsKey(country)) Countries.Add(country, checked((byte)Countries.Count)); var shape = row.ToShape(); var geometry = shape.ToGeometry(); Tree.Insert(geometry.Envelope, new Tuple<string, IGeometry>(country, geometry)); } } Tree.Build(); }