/// <summary> /// Propagates resizing of the nodes upwards. Additionally, performs /// any splitting of nodes along the way if a node needed to split. /// Returns whether the root node was split. /// </summary> /// <param name="adjustPath">Path along which the nodes need be adjusted</param> /// <param name="node">Node above which needs to be adjusted</param> /// <param name="splitNode">Node that needs to be inserted.</param> /// <returns>True if the root node was split</returns> private bool adjustTree(List <NodeRecord <T> > adjustPath, NodeRecord <T> node, ref NodeRecord <T> splitNode) { // AT1. NodeRecord <T> N = node; NodeRecord <T> NN = splitNode; while (true) { // AT2. if (N == root) { return(NN != null); } // AT3. N.ResizeBBox(); // AT4. // Try to add the extra node to this parent node. // If the parent has no more room, split the parent, // and propagate the split node upwards to continue // looking for an insertion point. int level = adjustPath.IndexOf(N); NodeRecord <T> P = adjustPath[level - 1]; if (NN != null) { if (!P.TryInsert(NN)) { NodeRecord <T> PP = P.Split(NN); NN = PP; } else { NN = null; } } N = P; } }
/// <summary> /// Removes unfull nodes and shrinks BBoxs along the leafpath. /// </summary> /// <param name="deletedRecordNode">node with leaf deleted</param> /// <param name="leafPath">Path from root to node with deletion</param> private void condenseTree(NodeRecord <T> deletedRecordNode, List <NodeRecord <T> > leafPath) { List <NodeRecord <T> > Q = new List <NodeRecord <T> >(); NodeRecord <T> N = deletedRecordNode; while (true) { if (N == root) { break; } int level = leafPath.IndexOf(N); NodeRecord <T> P = leafPath[level - 1]; if (N.Node.GetRecordCount() < RTreeNode <T> .m) { P.Node.GetRecords().Remove(N); Q.Add(N); } else { N.ResizeBBox(); } N = P; } // We don't have to worry about doubling down because // at each level, we separated the removed node from its // parents. So even if an 'ex-parent' is present with its // 'ex-child' in the list, we won't double down. foreach (var orphan in Q) { reinsertNode(orphan); } }