Ejemplo n.º 1
0
        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)
                }
            };
        }