private void Relocate(QuadTreeObject <T> item) { // Are we still inside our parent? if (this.QuadRect.Contains(item.Data.Bounds)) { // Good, have we moved inside any of our children? if (this.TopLeftChild != null) { var dest = this.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 var formerOwner = item.Owner; this.Delete(item, false); dest.Insert(item); // Clean up ourselves formerOwner.CleanUpwards(); } } } else { // We don't fit here anymore, move up, if we can this.Parent?.Relocate(item); } }
///<summary> /// Adds an item to the QuadTree ///</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) { var wrappedObject = new QuadTreeObject <T>(item); this.wrappedDictionary.Add(item, wrappedObject); this.QuadTreeRoot.Insert(wrappedObject); }
/// <summary> /// Add an item to the object list. /// </summary> /// <param name="item">The item to add.</param> private void Add(QuadTreeObject <T> item) { if (this.objects == null) { this.objects = new List <QuadTreeObject <T> >(); } item.Owner = this; this.objects.Add(item); }
/// <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 { this.Relocate(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 (this.objects != null) { var removeIndex = this.objects.IndexOf(item); if (removeIndex >= 0) { this.objects[removeIndex] = this.objects[this.objects.Count - 1]; this.objects.RemoveAt(this.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) { this.Remove(item); if (clean) { this.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 (!this.QuadRect.Contains(item.Data.Bounds)) { if (this.Parent == null) { // This object is outside of the QuadTree bounds, we should add it at the root level this.Add(item); } else { return; } } if (this.objects == null || this.TopLeftChild == null && this.objects.Count + 1 <= MaxObjectsPerNode) { // If there's room to add the object, just add it this.Add(item); } else { // No quads, create them and bump objects down where appropriate if (this.TopLeftChild == null) { this.Subdivide(); } // Find out which tree this object should go in and add it there var destTree = this.GetDestinationTree(item); if (destTree == this) { 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 var destTree = this; if (this.TopLeftChild.QuadRect.Contains(item.Data.Bounds)) { destTree = this.TopLeftChild; } else if (this.TopRightChild.QuadRect.Contains(item.Data.Bounds)) { destTree = this.TopRightChild; } else if (this.BottomLeftChild.QuadRect.Contains(item.Data.Bounds)) { destTree = this.BottomLeftChild; } else if (this.BottomRightChild.QuadRect.Contains(item.Data.Bounds)) { destTree = this.BottomRightChild; } return(destTree); }