/// <summary> /// Subdivide this QuadTree and move it's children into the appropriate Quads where applicable. /// </summary> private void Subdivide() { // We've reached capacity, subdivide... Point size = new Point((int)rect.Width / 2, (int)rect.Height / 2); Point mid = new Point((int)rect.X + size.X, (int)rect.Y + size.Y); childTL = new QuadTreeNode <T>(this, new BoundingBox2D(rect.Left, rect.Top, size.X, size.Y)); childTR = new QuadTreeNode <T>(this, new BoundingBox2D(mid.X, rect.Top, size.X, size.Y)); childBL = new QuadTreeNode <T>(this, new BoundingBox2D(rect.Left, mid.Y, size.X, size.Y)); childBR = new QuadTreeNode <T>(this, new BoundingBox2D(mid.X, mid.Y, size.X, size.Y)); // If they're completely contained by the quad, bump objects down for (int i = 0; i < objects.Count; i++) { QuadTreeNode <T> destTree = GetDestinationTree(objects[i]); if (destTree != this) { // Insert to the appropriate tree, remove the object, and back up one in the loop destTree.Insert(objects[i]); Remove(objects[i]); i--; } } }
private void Relocate(QuadTreeObject <T> item) { // Are we still inside our parent? if (QuadRect.Contains(item.Data.BoundingBox2D)) { // 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) { QuadTreeObject <T> wrappedObject = quadTreeObjectPool.New(); wrappedObject.Data = item; wrappedObject.Active = true; wrappedDictionary.Add(item, wrappedObject); quadTreeRoot.Insert(wrappedObject); }
/// <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.BoundingBox2D)) { 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 { return; } } if (objects == null || (childTL == null && objects.Count < 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); } } }