/// <summary> /// Removes the specified geometry from the tree. /// </summary> /// <param name="geometry">The geometry.</param> /// <returns><c>true</c>, if the tree contains the geometry, otherwise, <c>false</c>.</returns> protected virtual Boolean RemoveGeometry(IGeometry geometry) { RTreeNode leafContainer = null; FindLeafContainer(geometry, _root, ref leafContainer); if (leafContainer == null) { return(false); } RTreeNode nodeToRemove = leafContainer.Children.First(x => x.Geometry == geometry); leafContainer.RemoveChild(nodeToRemove); CondenseTree(leafContainer); while (_root.ChildrenCount == 1 && !_root.IsLeafContainer) { _root = _root.Children[0]; _root.Parent = null; _height--; } if (_root.ChildrenCount == 0) // occurs when the last element is removed { Clear(); } return(true); }
/// <summary> /// Adjusts the tree after insertion, and corrects the bounding envelope of the nodes. /// </summary> /// <param name="node">The node where the adjustment starts.</param> /// <param name="splitted">The second part of the node if the original node was split.</param> /// <param name="nodeToRemove">The original node which should be removed if the original node was split.</param> protected void AdjustTree(RTreeNode node, RTreeNode splitted = null, RTreeNode nodeToRemove = null) { RTreeNode n = node; RTreeNode nn = splitted; while (n.Parent != null) { RTreeNode parent = n.Parent; parent.CorrectBounding(n.Envelope); if (nn == null) { n = parent; } else { if (nodeToRemove != null) { parent.RemoveChild(nodeToRemove); parent.AddChild(n); } if (!parent.IsFull) { parent.AddChild(nn); n = parent; nn = null; } else { parent.AddChild(nn); SplitNode(parent, out n, out nn); nodeToRemove = parent; } } } // create new root node if the root is split if (nn != null) { _root = new RTreeNode(n.MaxChildren); _root.AddChild(n); _root.AddChild(nn); _height++; } }
/// <summary> /// Condenses the tree after removing a leaf node. /// </summary> /// <param name="leafContainerNode">The node which contained the removed node.</param> private void CondenseTree(RTreeNode leafContainerNode) { Dictionary <RTreeNode, Int32> deletedNodes = new Dictionary <RTreeNode, Int32>(); RTreeNode p = leafContainerNode; Int32 height = Height - 1; while (p.Parent != null) { RTreeNode parent = p.Parent; if (p.ChildrenCount < MinChildren) { parent.RemoveChild(p); if (p.Children != null) { foreach (RTreeNode node in p.Children) { deletedNodes.Add(node, height); } } } else { p.CorrectBounding(); } p = parent; height--; } Int32 startHeight = Height; foreach (KeyValuePair <RTreeNode, Int32> reInsert in deletedNodes) { AddNode(reInsert.Key, reInsert.Value + (Height - startHeight)); } }