/// <summary> /// Splits the given node in two other nodes. /// </summary> /// <param name="node"></param> /// <param name="minimumSize"></param> /// <returns></returns> private static Node[] SplitNode(Node node, int minimumSize) { bool leaf = (node.Children is List <T>); // create the target nodes. var nodes = new Node[2]; nodes[0] = new Node(); nodes[0].Boxes = new List <BoxF2D>(); if (leaf) { nodes[0].Children = new List <T>(); } else { nodes[0].Children = new List <Node>(); } nodes[1] = new Node(); nodes[1].Boxes = new List <BoxF2D>(); if (leaf) { nodes[1].Children = new List <T>(); } else { nodes[1].Children = new List <Node>(); } // select the seed boxes. int[] seeds = RTreeMemoryIndex <T> .SelectSeeds(node.Boxes); // add the boxes. nodes[0].Boxes.Add(node.Boxes[seeds[0]]); nodes[1].Boxes.Add(node.Boxes[seeds[1]]); nodes[0].Children.Add(node.Children[seeds[0]]); nodes[1].Children.Add(node.Children[seeds[1]]); // create the boxes. var boxes = new BoxF2D[2] { node.Boxes[seeds[0]], node.Boxes[seeds[1]] }; node.Boxes.RemoveAt(seeds[0]); // seeds[1] is always < seeds[0]. node.Boxes.RemoveAt(seeds[1]); node.Children.RemoveAt(seeds[0]); node.Children.RemoveAt(seeds[1]); while (node.Boxes.Count > 0) { // check if one of them needs em all! if (nodes[0].Boxes.Count + node.Boxes.Count == minimumSize) { // all remaining boxes need te be assigned here. for (int idx = 0; node.Boxes.Count > 0; idx++) { boxes[0] = boxes[0].Union(node.Boxes[0]); nodes[0].Boxes.Add(node.Boxes[0]); nodes[0].Children.Add(node.Children[0]); node.Boxes.RemoveAt(0); node.Children.RemoveAt(0); } } else if (nodes[1].Boxes.Count + node.Boxes.Count == minimumSize) { // all remaining boxes need te be assigned here. for (int idx = 0; node.Boxes.Count > 0; idx++) { boxes[1] = boxes[1].Union(node.Boxes[0]); nodes[1].Boxes.Add(node.Boxes[0]); nodes[1].Children.Add(node.Children[0]); node.Boxes.RemoveAt(0); node.Children.RemoveAt(0); } } else { // choose one of the leaves. int leafIdx; int nextId = RTreeMemoryIndex <T> .PickNext(boxes, node.Boxes, out leafIdx); boxes[leafIdx] = boxes[leafIdx].Union(node.Boxes[nextId]); nodes[leafIdx].Boxes.Add(node.Boxes[nextId]); nodes[leafIdx].Children.Add(node.Children[nextId]); node.Boxes.RemoveAt(nextId); node.Children.RemoveAt(nextId); } } RTreeMemoryIndex <T> .SetParents(nodes[0]); RTreeMemoryIndex <T> .SetParents(nodes[1]); return(nodes); }
/// <summary> /// Adds the given item to the given box. /// </summary> /// <param name="leaf"></param> /// <param name="box"></param> /// <param name="item"></param> /// <param name="minimumSize"></param> /// <param name="maximumSize"></param> private static Node Add(Node leaf, BoxF2D box, T item, int minimumSize, int maximumSize) { if (box == null) { throw new ArgumentNullException("box"); } if (leaf == null) { throw new ArgumentNullException("leaf"); } Node ll = null; if (leaf.Boxes.Count == maximumSize) { // split the node. // add the child. leaf.Boxes.Add(box); leaf.Children.Add(item); Node[] split = RTreeMemoryIndex <T> .SplitNode(leaf, minimumSize); leaf.Boxes = split[0].Boxes; leaf.Children = split[0].Children; RTreeMemoryIndex <T> .SetParents(leaf); ll = split[1]; } else { // add the child. leaf.Boxes.Add(box); leaf.Children.Add(item); } // adjust the tree. Node n = leaf; Node nn = ll; while (n.Parent != null) { // keep going until the root is reached. Node p = n.Parent; RTreeMemoryIndex <T> .TightenFor(p, n); // tighten the parent box around n. if (nn != null) { // propagate split if needed. if (p.Boxes.Count == maximumSize) { // parent needs to be split. p.Boxes.Add(nn.GetBox()); p.Children.Add(nn); Node[] split = RTreeMemoryIndex <T> .SplitNode( p, minimumSize); p.Boxes = split[0].Boxes; p.Children = split[0].Children; RTreeMemoryIndex <T> .SetParents(p); nn = split[1]; } else { // add the other 'split' node. p.Boxes.Add(nn.GetBox()); p.Children.Add(nn); nn.Parent = p; nn = null; } } n = p; } if (nn != null) { // create a new root node and var root = new Node(); root.Boxes = new List <BoxF2D>(); root.Boxes.Add(n.GetBox()); root.Boxes.Add(nn.GetBox()); root.Children = new List <Node>(); root.Children.Add(n); n.Parent = root; root.Children.Add(nn); nn.Parent = root; return(root); } return(null); // no new root node needed. }