/// <summary> /// Query the QuadTree for items that are in the given area /// </summary> /// <param name="queryArea"></pasram> /// <returns></returns> public IEnumerable <T> Query(MRectangleF queryArea) { // this quad contains items that are not entirely contained by // it's four sub-quads. Iterate through the items in this quad // to see if they intersect. foreach (T item in this.Contents) { if (queryArea.IntersectsWith(Tree.GetRect(item))) { yield return(item); } } foreach (QuadTreeNode <T> node in m_nodes) { if (node.IsEmpty) { continue; } // Case 1: search area completely contained by sub-quad // if a node completely contains the query area, go down that branch // and skip the remaining nodes (break this loop) if (node.Bounds.Contains(queryArea)) { foreach (T t in node.Query(queryArea)) { yield return(t); } break; } // Case 2: Sub-quad completely contained by search area // if the query area completely contains a sub-quad, // just add all the contents of that quad and it's children // to the result set. You need to continue the loop to test // the other quads if (queryArea.Contains(node.Bounds)) { foreach (T t in node.SubTreeContents) { yield return(t); } continue; } // Case 3: search area intersects with sub-quad // traverse into this quad, continue the loop to search other // quads if (node.Bounds.IntersectsWith(queryArea)) { foreach (T t in node.Query(queryArea)) { yield return(t); } } } }
/// <summary> /// Insert an item to this node /// </summary> /// <param name="item"></param> public void Insert(T item, MRectangleF rect) { // if the item is not contained in this quad, there's a problem if (!m_bounds.Contains(rect)) { throw new ArgumentException("feature is out of the bounds of this quadtree node"); } // if the subnodes are null create them. may not be sucessfull: see below // we may be at the smallest allowed size in which case the subnodes will not be created //if (m_nodes.Count == 0) // CreateSubNodes(); if (m_nodes.Count == 0 && this.Contents.Count >= Tree.NodeCapacity) { CreateSubNodes(); MoveContentsToSubNodes(); } if (this.Contents.Count > Tree.NodeCapacity) { //this node is full, let's try and store T in a subnode, if it's small enough. // for each subnode: // if the node contains the item, add the item to that node and return // this recurses into the node that is just large enough to fit this item foreach (QuadTreeNode <T> node in m_nodes) { if (node.Bounds.Contains(rect)) { node.Insert(item, rect); return; } } } //add, even if we are over capacity. this.Contents.Add(item); }