public MapItemQuadTreeNode(MapItemQuadTreeNode parent, int childIdx) { Parent = parent; if (Parent == null) { Rect = new Rect(0, 0, 1, 1); ZoomLevel = 0; X = Y = 0L; } else { Rect = parent.GetChildRect(childIdx); ZoomLevel = parent.ZoomLevel + 1; X = (Parent.X << 1) + (childIdx % 2); Y = (Parent.Y << 1) + (childIdx / 2); } _Children = new MapItemQuadTreeNode[4]; _Items = new HashSet<MapItem>(); }
public MapItemQuadTree() { _RootNode = new MapItemQuadTreeNode(null, 0); _NodesToVisit = new Stack<MapItemQuadTreeNode>(); }
/// <summary> /// Clusters the map items contained in the node. Clustered items are modified and new items are added /// to the tree to represent the clusters. /// </summary> private static void ClusterNodeItems(MapItemQuadTree tree, MapItemQuadTreeNode node) { var clumps = new List<List<MapItem>>(); var clusters = new List<Tuple<List<MapItem>, Point>>(); HashSet<MapItem> visitedNodes = new HashSet<MapItem>(); // Create the set of clusters of intersecting items. foreach (var item in node.Items) { List<MapItem> clump = new List<MapItem>(); GrowClump(tree, item, node.ZoomLevel, visitedNodes, clump); if (clump.Count > 1) { foreach (var cluster in ClusterClump(clump, node.ZoomLevel)) { if (cluster.Item1.Count > 1) { clusters.Add(cluster); } } } } // For each cluster, modify the existing items in the cluster such that they don't appear at the same // LOD as the cluster and add new item(s) to the tree that represent the cluster. foreach (var cluster in clusters) { Debug.Assert(cluster.Item1.Count > 1); Point clusterLocation = cluster.Item2; var clusterItem = new FixedSizeInScreenSpaceMapItem( clusterLocation.ToLocation(), PositionOrigin.Center, new Size(20, 20), 0, node.ZoomLevel); tree.Add(clusterItem); foreach (var item in cluster.Item1) { tree.Remove(item); // If this item isn't present at a finer LOD than this, then it's been totally // subsumed by the cluster; otherwise, re-add it to the tree with adjusted // min zoom level. if (item.MaxZoomLevel > node.ZoomLevel) { var adjustedItem = new FixedSizeInScreenSpaceMapItem( item.Location, PositionOrigin.Center, new Size(20, 20), node.ZoomLevel + 1, item.MaxZoomLevel) { Parent = clusterItem }; // We're removing the item, so re-assign the children's parent to the cluster that's // standing in for it. foreach (var child in item.Children) { child.Parent = adjustedItem; adjustedItem.AddChild(child); } clusterItem.AddChild(adjustedItem); tree.Add(adjustedItem); } } } }
public MapItemQuadTreeNode EnsureChild(int childIdx) { MapItemQuadTreeNode child = _Children[childIdx]; if (child == null) { child = _Children[childIdx] = new MapItemQuadTreeNode(this, childIdx); } return child; }