private void Relocate(QuadTreeObject <T> item) { // Are we still inside our parent? if (QuadRect.Contains(item.Data.QuadBounds)) { // Good, have we moved inside any of our children? if (childTL != null) { QuadTreeNode <T> dest = GetDestinationTree(item); if (item.Owner != dest) { // Delete the item from this quad and add it to our child // Note: Do NOT clean during this call, it can potentially delete our destination quad QuadTreeNode <T> formerOwner = item.Owner; Delete(item, false); dest.Insert(item); // Clean up ourselves formerOwner.CleanUpwards(); } } } else { // We don't fit here anymore, move up, if we can if (parent != null) { parent.Relocate(item); } } }
///<summary> ///Adds an item to the <see cref="T:System.Collections.Generic.ICollection`1" />. ///</summary> /// ///<param name="item">The object to add to the <see cref="T:System.Collections.Generic.ICollection`1" />.</param> ///<exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1" /> is read-only.</exception> public void Add(T item) { lock (objLock) { QuadTreeObject <T> wrappedObject = new QuadTreeObject <T>(item); wrappedDictionary.Add(item, wrappedObject); quadTreeRoot.Insert(wrappedObject); } }
/// <summary> /// Moves the QuadTree object in the tree /// </summary> /// <param name="item">The item that has moved</param> internal void Move(QuadTreeObject <T> item) { if (item.Owner != null) { item.Owner.Relocate(item); } else { Relocate(item); } }
/// <summary> /// Add an item to the object list. /// </summary> /// <param name="item">The item to add.</param> private void Add(QuadTreeObject <T> item) { if (objects == null) { //m_objects = new List<T>(); objects = new List <QuadTreeObject <T> >(); } item.Owner = this; objects.Add(item); }
/// <summary> /// Remove an item from the object list. /// </summary> /// <param name="item">The object to remove.</param> private void Remove(QuadTreeObject <T> item) { if (objects != null) { int removeIndex = objects.IndexOf(item); if (removeIndex >= 0) { objects[removeIndex] = objects[objects.Count - 1]; objects.RemoveAt(objects.Count - 1); } } }
/// <summary> /// Deletes an item from this QuadTree. If the object is removed causes this Quad to have no objects in its children, it's children will be removed as well. /// </summary> /// <param name="item">The item to remove.</param> /// <param name="clean">Whether or not to clean the tree</param> internal void Delete(QuadTreeObject <T> item, bool clean) { if (item.Owner != null) { if (item.Owner == this) { Remove(item); if (clean) { CleanUpwards(); } } else { item.Owner.Delete(item, clean); } } }
/// <summary> /// Insert an item into this QuadTree object. /// </summary> /// <param name="item">The item to insert.</param> internal void Insert(QuadTreeObject <T> item) { // If this quad doesn't contain the items rectangle, do nothing, unless we are the root if (!rect.Contains(item.Data.QuadBounds)) { //System.Diagnostics.Debug.Assert(parent == null, "We are not the root, and this object doesn't fit here. How did we get here?"); if (parent == null) { // This object is outside of the QuadTree bounds, we should add it at the root level Add(item); } else { parent.Insert(item); return; } } if (objects == null || (childTL == null && objects.Count + 1 <= maxObjectsPerNode)) { // If there's room to add the object, just add it Add(item); } else { // No quads, create them and bump objects down where appropriate if (childTL == null) { Subdivide(); } // Find out which tree this object should go in and add it there QuadTreeNode <T> destTree = GetDestinationTree(item); if (destTree == this) { Add(item); } else { destTree.Insert(item); } } }
/// <summary> /// Get the child Quad that would contain an object. /// </summary> /// <param name="item">The object to get a child for.</param> /// <returns></returns> private QuadTreeNode <T> GetDestinationTree(QuadTreeObject <T> item) { // If a child can't contain an object, it will live in this Quad QuadTreeNode <T> destTree = this; if (childTL.QuadRect.Contains(item.Data.QuadBounds)) { destTree = childTL; } else if (childTR.QuadRect.Contains(item.Data.QuadBounds)) { destTree = childTR; } else if (childBL.QuadRect.Contains(item.Data.QuadBounds)) { destTree = childBL; } else if (childBR.QuadRect.Contains(item.Data.QuadBounds)) { destTree = childBR; } return(destTree); }