private static ISpatialIndexNode <IExtents, TItem> findParentNode(ISpatialIndexNode <IExtents, TItem> lookFor, ISpatialIndexNode <IExtents, TItem> searchNode) { foreach (ISpatialIndexNode <IExtents, TItem> node in searchNode.SubNodes) { if (node.Equals(lookFor)) { return(searchNode); } } IExtents itemBounds = lookFor.Bounds; // TODO: I think a breadth-first search would be more efficient here foreach (ISpatialIndexNode <IExtents, TItem> child in searchNode.SubNodes) { if (child.Intersects(itemBounds)) { ISpatialIndexNode <IExtents, TItem> found = findParentNode(lookFor, child); if (found != null) { return(found); } } } return(null); }
public void Insert(IExtents bounds, TItem entry, ISpatialIndexNode <IExtents, TItem> node, INodeSplitStrategy <IExtents, TItem> nodeSplitStrategy, IndexBalanceHeuristic heuristic, out ISpatialIndexNode <IExtents, TItem> newSiblingFromSplit) { if (node == null) { throw new ArgumentNullException("node"); } if (!(node is QuadTreeNode <TItem>)) { throw new ArgumentException("Parameter 'node' must be of type QuadTreeNode<TItem>", "node"); } QuadTreeNode <TItem> quadTreeNode = node as QuadTreeNode <TItem>; insertEntryRecursive(quadTreeNode, entry, nodeSplitStrategy, heuristic, out newSiblingFromSplit); if (newSiblingFromSplit != null) { if (quadTreeNode.ItemCount == 4) { throw new QuadTreeIndexInsertOverflowException(); } quadTreeNode.Add(newSiblingFromSplit); } }
private static ISpatialIndexNode <IExtents, TItem> findLeastExpandedChild( IEnumerable <ISpatialIndexNode <IExtents, TItem> > children, ComputationExtents currentBounds, Double leastExpandedArea, Double leastExpandedChildArea) { ISpatialIndexNode <IExtents, TItem> leastExpandedChild = null; foreach (ISpatialIndexNode <IExtents, TItem> child in children) { ComputationExtents childBounds = child.Bounds != null ? new ComputationExtents(child.Bounds) : new ComputationExtents(); ComputationExtents candidateRegion = childBounds.Union(currentBounds); Double candidateRegionArea = candidateRegion.Area; Double childArea = childBounds.Area; Double expandedArea = candidateRegionArea - childArea; if (expandedArea < leastExpandedArea) { leastExpandedChild = child; leastExpandedChildArea = childArea; leastExpandedArea = expandedArea; } else if (expandedArea == leastExpandedArea && childArea < leastExpandedChildArea) { leastExpandedChild = child; leastExpandedChildArea = childArea; } } return(leastExpandedChild); }
private static ISpatialIndexNode <TBounds, TItem> findLeastExpandedChild( IEnumerable <ISpatialIndexNode <TBounds, TItem> > children, TBounds currentBounds, Double leastExpandedArea, Double leastExpandedChildArea) { ISpatialIndexNode <TBounds, TItem> leastExpandedChild = null; foreach (ISpatialIndexNode <TBounds, TItem> child in children) { TBounds childBounds = child.Bounds; TBounds candidateRegion = (TBounds)childBounds.Union(currentBounds); Double candidateRegionArea = Area(candidateRegion); Double childArea = Area(childBounds); Double expandedArea = candidateRegionArea - childArea; if (expandedArea < leastExpandedArea) { leastExpandedChild = child; leastExpandedChildArea = childArea; leastExpandedArea = expandedArea; } else if (expandedArea == leastExpandedArea && childArea < leastExpandedChildArea) { leastExpandedChild = child; leastExpandedChildArea = childArea; } } return(leastExpandedChild); }
protected override void addSubNode(ISpatialIndexNode <IExtents, TItem> child) { if (child == null) { throw new ArgumentNullException("child"); } RTreeNode <TItem> node = child as RTreeNode <TItem>; if (node == null) { throw new ArgumentException("Parameter must be of type RTreeNode<TItem>."); } ensureChildren(); _children.Add(node); if (Bounds == null) { Bounds = node.Bounds.Clone() as IExtents; } else { Bounds.ExpandToInclude(child.Bounds); } }
private static ISpatialIndexNode <IExtents, TItem> findNodeForItem(TItem item, ISpatialIndexNode <IExtents, TItem> node) { foreach (TItem nodeItem in node.Items) { if (item.Equals(nodeItem)) { return(node); } } IExtents itemBounds = item.Bounds; // TODO: I think a breadth-first search would be more efficient here foreach (ISpatialIndexNode <IExtents, TItem> child in node.SubNodes) { if (child.Intersects(itemBounds)) { ISpatialIndexNode <IExtents, TItem> found = findNodeForItem(item, child); if (found != null) { return(found); } } } return(null); }
public ISpatialIndexNode <IExtents, TItem> SplitNode(ISpatialIndexNode <IExtents, TItem> node, IndexBalanceHeuristic heuristic) { if (node == null) { return(null); } QuadTreeNode <TItem> quadTreeNode = node as QuadTreeNode <TItem>; DynamicQuadTreeBalanceHeuristic quadTreeHeuristic = heuristic as DynamicQuadTreeBalanceHeuristic; throw new NotImplementedException(); }
public ISpatialIndexNode <TBounds, TItem> SplitNode(ISpatialIndexNode <TBounds, TItem> node, IndexBalanceHeuristic heuristic) { if (node == null) { throw new ArgumentNullException("node"); } DynamicRTreeBalanceHeuristic rTreeHueristic = heuristic as DynamicRTreeBalanceHeuristic; return(doSplit(node, rTreeHueristic)); }
/// <summary> /// Removes an item from the index. /// </summary> /// <param name="item">The item to remove.</param> public override Boolean Remove(TItem item) { ISpatialIndexNode <IExtents, TItem> itemNode = findNodeForItem(item, Root); bool removed = itemNode != null && itemNode.Remove(item); if (itemNode.IsPrunable) { ISpatialIndexNode <IExtents, TItem> parent = findParentNode(itemNode, Root); parent.Remove(itemNode); } return(removed); }
public ISpatialIndexNode <IExtents, TItem> SplitNode( ISpatialIndexNode <IExtents, TItem> node, IndexBalanceHeuristic heuristic) { if (node == null) { throw new ArgumentNullException("node"); } RTreeNode <TItem> rTreeNode = node as RTreeNode <TItem>; Debug.Assert(rTreeNode != null); DynamicRTreeBalanceHeuristic rTreeHueristic = heuristic as DynamicRTreeBalanceHeuristic; return(doSplit(rTreeNode, rTreeHueristic)); }
protected override Boolean removeSubNode(ISpatialIndexNode <IExtents, TItem> child) { if (child == null) { throw new ArgumentNullException("child"); } RTreeNode <TItem> node = child as RTreeNode <TItem>; if (node == null) { throw new ArgumentException("Parameter must be of type RTreeNode<TItem>."); } ensureChildren(); return(_children.Remove(node)); }
/// <summary> /// Inserts a node into the tree using <see cref="ItemInsertStrategy"/>. /// </summary> /// <param name="item">The item to insert into the index.</param> public override void Insert(TItem item) { ISpatialIndexNode <IExtents, TItem> newSiblingFromSplit; //printItemCount(); ItemInsertStrategy.Insert(item.Bounds, item, Root, _nodeSplitStrategy, Heuristic, out newSiblingFromSplit); if (newSiblingFromSplit == null) { return; } //Debug.Print("Node was split."); // Add the newly split sibling if (newSiblingFromSplit.IsLeaf) { if (Root.IsLeaf) // handle the first splitting of the root node. { RTreeNode <TItem> oldRoot = Root as RTreeNode <TItem>; Root = CreateNode(0); Root.Add(oldRoot); } Root.Add(newSiblingFromSplit); } else // Came from a root split { ISpatialIndexNode <IExtents, TItem> oldRoot = Root; Root = CreateNode(0); Root.Add(oldRoot); Root.Add(newSiblingFromSplit); } }
protected override bool removeSubNode(ISpatialIndexNode <IExtents, TItem> child) { throw new NotImplementedException(); }
private void insertEntryRecursive(QuadTreeNode <TItem> quadTreeNode, TItem entry, INodeSplitStrategy <IExtents, TItem> nodeSplitStrategy, IndexBalanceHeuristic heuristic, out ISpatialIndexNode <IExtents, TItem> newSiblingFromSplit) { throw new NotImplementedException(); }
public void Insert(TBounds bounds, TItem entry, ISpatialIndexNode <TBounds, TItem> node, INodeSplitStrategy <TBounds, TItem> nodeSplitStrategy, IndexBalanceHeuristic heuristic, out ISpatialIndexNode <TBounds, TItem> newSiblingFromSplit) { newSiblingFromSplit = null; //TODO: handle null node.. // Terminating case if (node.IsLeaf) { node.Add(entry); // Handle node overflow if (node.ItemCount > heuristic.NodeItemMaximumCount) { // Split the node using the given strategy newSiblingFromSplit = nodeSplitStrategy.SplitNode(node, heuristic); //if (++_tempSplitCount % 100 == 0) //{ // Debug.Print("Node split # {0}", _tempSplitCount); //} } } else { // NOTE: Descending the tree recursively here // can make for a very expensive build of a tree, // even for moderate amounts of data. Double leastExpandedArea = Double.MaxValue; Double leastExpandedChildArea = Double.MaxValue; //TBounds currentBounds = new ComputationExtents(bounds); ISpatialIndexNode <TBounds, TItem> leastExpandedChild; leastExpandedChild = findLeastExpandedChild(node.SubNodes, bounds, leastExpandedArea, leastExpandedChildArea); Debug.Assert(leastExpandedChild != null); // Found least expanded child node - insert into it Insert(bounds, entry, leastExpandedChild, nodeSplitStrategy, heuristic, out newSiblingFromSplit); // Adjust this node... node.Bounds.ExpandToInclude(bounds); // Check for overflow and add to current node if it occured if (newSiblingFromSplit != null) { // Add new sibling node to the current node node.Add(newSiblingFromSplit); newSiblingFromSplit = null; // Split the current node, since the child count is too high, // and return the split to the caller if (node.ItemCount > heuristic.NodeItemMaximumCount) { newSiblingFromSplit = nodeSplitStrategy.SplitNode(node, heuristic); } } } }
private ISpatialIndexNode <TBounds, TItem> doSplit(ISpatialIndexNode <TBounds, TItem> node, DynamicRTreeBalanceHeuristic heuristic) { Boolean isLeaf = node.IsLeaf; IEnumerable <IBoundable <TBounds> > boundables = isLeaf ? Caster.Upcast <IBoundable <TBounds>, TItem>(node.Items) : Caster.Upcast <IBoundable <TBounds>, ISpatialIndexNode <TBounds, TItem> >(node.SubNodes); Int32 boundablesCount = isLeaf ? node.ItemCount : node.SubNodeCount; List <IBoundable <TBounds> > entries = new List <IBoundable <TBounds> >(boundablesCount); entries.AddRange(boundables); IList <IBoundable <TBounds> > group1 = new List <IBoundable <TBounds> >(); IList <IBoundable <TBounds> > group2 = new List <IBoundable <TBounds> >(); pickSeeds(entries, group1, group2); Int32 group1Count = 1, group2Count = 1; distribute(entries, group1, group2, heuristic, ref group1Count, ref group2Count); if (entries.Count > 0) { if (group1Count < heuristic.NodeItemMinimumCount) { fillShortGroup(entries, group1, ref group1Count); } else // group2Count < heuristic.NodeItemMinimumCount { fillShortGroup(entries, group2, ref group2Count); } } node.Clear(); ISpatialIndexNode <TBounds, TItem> sibling = NodeFactory.CreateNode(node.Level); IEnumerable <IBoundable <TBounds> > g1Sized = Enumerable.Take(group1, group1Count); IEnumerable <IBoundable <TBounds> > g2Sized = Enumerable.Take(group2, group2Count); if (isLeaf) { //IEnumerable<TItem> g1Cast = Caster.Downcast<TItem, IBoundable<TBounds>>(g1Sized); node.AddRange(g1Sized); //IEnumerable<TItem> g2Cast = Caster.Downcast<TItem, IBoundable<IExtents>>(g2Sized); sibling.AddRange(g2Sized); } else { //IEnumerable<ISpatialIndexNode<IExtents, TItem>> g1Cast // = Caster.Downcast<ISpatialIndexNode<IExtents, TItem>, IBoundable<IExtents>>(g1Sized); node.AddRange(g1Sized); //IEnumerable<ISpatialIndexNode<IExtents, TItem>> g2Cast // = Caster.Downcast<ISpatialIndexNode<IExtents, TItem>, IBoundable<IExtents>>(g2Sized); sibling.AddRange(g2Sized); } return(sibling); }
protected abstract Boolean removeSubNode(ISpatialIndexNode <IExtents, TItem> child);
protected abstract void addSubNode(ISpatialIndexNode <IExtents, TItem> child);
public void RestructureNode(ISpatialIndexNode node) { }
public void RestructureNode(ISpatialIndexNode <TBounds, TItem> node) { }