private void insertToLeaf(RTreeNode newNode) { if (Root == null) { Root = new RTreeNode(maxKeysPerNode, null); Root.AddChild(newNode); return; } var leafToInsert = findInsertionLeaf(Root, newNode); insertAndSplit(leafToInsert, newNode); }
/// <summary> /// Insert and split recursively up until no split is required /// </summary> /// <param name="node"></param> /// <param name="newValue"></param> private void insertAndSplit(RTreeNode node, RTreeNode newValue) { //newValue have room to fit in this node if (node.KeyCount < maxKeysPerNode) { node.AddChild(newValue); expandAncestorMBRs(node); return; } var e = new List <RTreeNode>(new RTreeNode[] { newValue }); e.AddRange(node.Children); var distantPairs = getDistantPairs(e); //Let E be the set consisting of all current entries and new entry. //Select as seeds two entries e1, e2 ∈ E, where the distance between //left and right is the maximum among all other pairs of entries from E var e1 = new RTreeNode(maxKeysPerNode, null); var e2 = new RTreeNode(maxKeysPerNode, null); e1.AddChild(distantPairs.Item1); e2.AddChild(distantPairs.Item2); e = e.Where(x => x != distantPairs.Item1 && x != distantPairs.Item2) .ToList(); /*Examine the remaining members of E one by one and assign them * to e1 or e2, depending on which of the MBRs of these nodes * will require the minimum area enlargement so as to cover this entry. * If a tie occurs, assign the entry to the node whose MBR has the smaller area. * If a tie occurs again, assign the entry to the node that contains the smaller number of entries*/ while (e.Count > 0) { var current = e[e.Count - 1]; var leftEnlargementArea = e1.MBRectangle.GetEnlargementArea(current.MBRectangle); var rightEnlargementArea = e2.MBRectangle.GetEnlargementArea(current.MBRectangle); if (leftEnlargementArea == rightEnlargementArea) { var leftArea = e1.MBRectangle.Area(); var rightArea = e2.MBRectangle.Area(); if (leftArea == rightArea) { if (e1.KeyCount < e2.KeyCount) { e1.AddChild(current); } else { e2.AddChild(current); } } else if (leftArea < rightArea) { e1.AddChild(current); } else { e2.AddChild(current); } } else if (leftEnlargementArea < rightEnlargementArea) { e1.AddChild(current); } else { e2.AddChild(current); } e.RemoveAt(e.Count - 1); var remaining = e.Count; /*if during the assignment of entries, there remain λ entries to be assigned * and the one node contains minKeysPerNode − λ entries then * assign all the remaining entries to this node without considering * the aforementioned criteria * so that the node will contain at least minKeysPerNode entries */ if (e1.KeyCount == minKeysPerNode - remaining) { foreach (var entry in e) { e1.AddChild(entry); } e.Clear(); } else if (e2.KeyCount == minKeysPerNode - remaining) { foreach (var entry in e) { e2.AddChild(entry); } e.Clear(); } } var parent = node.Parent; if (parent != null) { //replace current node with e1 parent.SetChild(node.Index, e1); //insert overflow element to parent insertAndSplit(parent, e2); } else { //node is the root. //increase the height of RTree by one by adding a new root. Root = new RTreeNode(maxKeysPerNode, null); Root.AddChild(e1); Root.AddChild(e2); } }