/// <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); }
private static RTreeMemoryIndex <T> .Node[] SplitNode(RTreeMemoryIndex <T> .Node node, int minimumSize) { int num1 = node.Children is List <T>? 1 : 0; RTreeMemoryIndex <T> .Node[] nodeArray = new RTreeMemoryIndex <T> .Node[2] { new RTreeMemoryIndex <T> .Node(), null }; nodeArray[0].Boxes = new List <BoxF2D>(); nodeArray[0].Children = num1 == 0 ? (IList) new List <RTreeMemoryIndex <T> .Node>() : (IList) new List <T>(); nodeArray[1] = new RTreeMemoryIndex <T> .Node(); nodeArray[1].Boxes = new List <BoxF2D>(); nodeArray[1].Children = num1 == 0 ? (IList) new List <RTreeMemoryIndex <T> .Node>() : (IList) new List <T>(); int[] numArray = RTreeMemoryIndex <T> .SelectSeeds(node.Boxes); nodeArray[0].Boxes.Add(node.Boxes[numArray[0]]); nodeArray[1].Boxes.Add(node.Boxes[numArray[1]]); nodeArray[0].Children.Add(node.Children[numArray[0]]); nodeArray[1].Children.Add(node.Children[numArray[1]]); BoxF2D[] nodeBoxes = new BoxF2D[2] { node.Boxes[numArray[0]], node.Boxes[numArray[1]] }; node.Boxes.RemoveAt(numArray[0]); node.Boxes.RemoveAt(numArray[1]); node.Children.RemoveAt(numArray[0]); node.Children.RemoveAt(numArray[1]); while (node.Boxes.Count > 0) { if (nodeArray[0].Boxes.Count + node.Boxes.Count == minimumSize) { int num2 = 0; while (node.Boxes.Count > 0) { nodeBoxes[0] = nodeBoxes[0].Union(node.Boxes[0]); nodeArray[0].Boxes.Add(node.Boxes[0]); nodeArray[0].Children.Add(node.Children[0]); node.Boxes.RemoveAt(0); node.Children.RemoveAt(0); ++num2; } } else if (nodeArray[1].Boxes.Count + node.Boxes.Count == minimumSize) { int num2 = 0; while (node.Boxes.Count > 0) { nodeBoxes[1] = nodeBoxes[1].Union(node.Boxes[0]); nodeArray[1].Boxes.Add(node.Boxes[0]); nodeArray[1].Children.Add(node.Children[0]); node.Boxes.RemoveAt(0); node.Children.RemoveAt(0); ++num2; } } else { int nodeBoxIndex; int index = RTreeMemoryIndex <T> .PickNext(nodeBoxes, (IList <BoxF2D>) node.Boxes, out nodeBoxIndex); nodeBoxes[nodeBoxIndex] = nodeBoxes[nodeBoxIndex].Union(node.Boxes[index]); nodeArray[nodeBoxIndex].Boxes.Add(node.Boxes[index]); nodeArray[nodeBoxIndex].Children.Add(node.Children[index]); node.Boxes.RemoveAt(index); node.Children.RemoveAt(index); } } RTreeMemoryIndex <T> .SetParents(nodeArray[0]); RTreeMemoryIndex <T> .SetParents(nodeArray[1]); return(nodeArray); }
/// <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. }
private static RTreeMemoryIndex <T> .Node Add(RTreeMemoryIndex <T> .Node leaf, BoxF2D box, T item, int minimumSize, int maximumSize) { if (box == null) { throw new ArgumentNullException("box"); } if (leaf == null) { throw new ArgumentNullException("leaf"); } RTreeMemoryIndex <T> .Node node1 = (RTreeMemoryIndex <T> .Node)null; if (leaf.Boxes.Count == maximumSize) { leaf.Boxes.Add(box); leaf.Children.Add((object)item); RTreeMemoryIndex <T> .Node[] nodeArray = RTreeMemoryIndex <T> .SplitNode(leaf, minimumSize); leaf.Boxes = nodeArray[0].Boxes; leaf.Children = nodeArray[0].Children; RTreeMemoryIndex <T> .SetParents(leaf); node1 = nodeArray[1]; } else { leaf.Boxes.Add(box); leaf.Children.Add((object)item); } RTreeMemoryIndex <T> .Node child = leaf; RTreeMemoryIndex <T> .Node node2 = node1; RTreeMemoryIndex <T> .Node parent; for (; child.Parent != null; child = parent) { parent = child.Parent; RTreeMemoryIndex <T> .TightenFor(parent, child); if (node2 != null) { if (parent.Boxes.Count == maximumSize) { parent.Boxes.Add(node2.GetBox()); parent.Children.Add((object)node2); RTreeMemoryIndex <T> .Node[] nodeArray = RTreeMemoryIndex <T> .SplitNode(parent, minimumSize); parent.Boxes = nodeArray[0].Boxes; parent.Children = nodeArray[0].Children; RTreeMemoryIndex <T> .SetParents(parent); node2 = nodeArray[1]; } else { parent.Boxes.Add(node2.GetBox()); parent.Children.Add((object)node2); node2.Parent = parent; node2 = (RTreeMemoryIndex <T> .Node)null; } } } if (node2 == null) { return((RTreeMemoryIndex <T> .Node)null); } RTreeMemoryIndex <T> .Node node3 = new RTreeMemoryIndex <T> .Node(); node3.Boxes = new List <BoxF2D>(); node3.Boxes.Add(child.GetBox()); node3.Boxes.Add(node2.GetBox()); node3.Children = (IList) new List <RTreeMemoryIndex <T> .Node>(); node3.Children.Add((object)child); child.Parent = node3; node3.Children.Add((object)node2); node2.Parent = node3; return(node3); }