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