root/src/BRAINSFramework/QuadTree/QuadTree.cs

User picture

Author: conkerjo

Revision: 30 («Previous)


File Size: 6.36 KB

(July 01, 2009 23:02 UTC) Almost 3 years ago


  

 
Show/hide line numbers
// *******************************************//
// *********Credits to Kyle Schouviller*******//
// *******for the original implementation*****//
// *******************************************//
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;


namespace Brains.Framework.QuadTree
{
    public class QuadTree<T>
    {

        public static Rectangle GetRectangle(RectangleF rect)
        {
            return new Rectangle((int)rect.Left, (int)rect.Top, (int)rect.Width, (int)rect.Height);
        }
        
        /// <summary>
        /// The head node of the QuadTree
        /// </summary>
        protected QuadTreeNode<T> headNode;

        /// <summary>
        /// Gets the world rectangle
        /// </summary>
        public RectangleF WorldRect
        {
            get { return headNode.Rect; }
        }

        /// <summary>
        /// The maximum number of items in any node before partitioning
        /// </summary>
        protected int maxItems;

        /// <summary>
        /// QuadTree constructor
        /// </summary>
        /// <param name="worldRect">The world rectangle for this QuadTree (a rectangle containing all items at all times)</param>
        /// <param name="maxItems">Maximum number of items in any cell of the QuadTree before partitioning</param>
        public QuadTree(RectangleF worldRect, int maxItems)
        {
            this.headNode = new QuadTreeNode<T>(worldRect, maxItems, Resize);
            this.maxItems = maxItems;
        }

        /// <summary>
        /// QuadTree constructor
        /// </summary>
        /// <param name="size">The size of the QuadTree (i.e. the bottom-right with a top-left of (0,0))</param>
        /// <param name="maxItems">Maximum number of items in any cell of the QuadTree before partitioning</param>
        /// <remarks>This constructor is for ease of use</remarks>
        public QuadTree(Vector2 size, int maxItems)
            : this(new RectangleF(Vector2.Zero, size), maxItems)
        {
            // Nothing extra to initialize
        }
      
        /// <summary>
        /// Inserts an item into the QuadTree
        /// </summary>
        /// <param name="item">The item to insert</param>
        /// <remarks>Checks to see if the world needs resizing and does so if needed</remarks>
        public void Insert(QuadTreePositionItem<T> item)
        {
            // check if the world needs resizing
            if (!headNode.ContainsRect(item.Rect))
            {
                Resize(new RectangleF(
                    Vector2.Min(headNode.Rect.TopLeft, item.Rect.TopLeft) * 2,
                    Vector2.Max(headNode.Rect.BottomRight, item.Rect.BottomRight) * 2));
            }
            item.node = null;
            item.quadTree = this;
            headNode.Insert(item);
        }

        /// <summary>
        /// Inserts an item into the QuadTree
        /// </summary>
        /// <param name="parent">The parent of the new position item</param>
        /// <param name="position">The position of the new position item</param>
        /// <param name="size">The size of the new position item</param>
        /// <returns>A new position item</returns>
        /// <remarks>Checks to see if the world needs resizing and does so if needed</remarks>
        public QuadTreePositionItem<T> Insert(T parent, Vector2 position, Vector2 size)
        {
            QuadTreePositionItem<T> item = new QuadTreePositionItem<T>(parent, position, size);

            // check if the world needs resizing
            if (!headNode.ContainsRect(item.Rect))
            {
                Resize(new RectangleF(
                    Vector2.Min(headNode.Rect.TopLeft, item.Rect.TopLeft) * 2,
                    Vector2.Max(headNode.Rect.BottomRight, item.Rect.BottomRight) * 2));
            }
            item.node = null;
            item.quadTree = this;
            headNode.Insert(item);

            return item;
        }

        /// <summary>
        /// Resizes the Quadtree field
        /// </summary>
        /// <param name="newWorld">The new field</param>
        /// <remarks>This is an expensive operation, so try to initialize the world to a big enough size</remarks>
        public void Resize(RectangleF newWorld)
        {
            // Get all of the items in the tree
            List<QuadTreePositionItem<T>> Components = new List<QuadTreePositionItem<T>>();
            GetAllItems(ref Components);

            // Destroy the head node
            headNode.Destroy();
            headNode = null;

            // Create a new head
            headNode = new QuadTreeNode<T>(newWorld, maxItems, Resize);

            // Reinsert the items
            foreach (QuadTreePositionItem<T> m in Components)
            {
                headNode.Insert(m);
            }
        }

        /// <summary>
        /// Gets a list of items containing a specified point
        /// </summary>
        /// <param name="Point">The point</param>
        /// <param name="ItemsFound">The list to add found items to (list will not be cleared first)</param>
        public void GetItems(Vector2 Point, ref List<QuadTreePositionItem<T>> ItemsList)
        {
            if (ItemsList != null)
            {
                headNode.GetItems(Point, ref ItemsList);
            }
        }

        /// <summary>
        /// Gets a list of items intersecting a specified rectangle
        /// </summary>
        /// <param name="Rect">The rectangle</param>
        /// <param name="ItemsFound">The list to add found items to (list will not be cleared first)</param>
        public void GetItems(RectangleF Rect, ref List<QuadTreePositionItem<T>> ItemsList)
        {
            if (ItemsList != null)
            {
                headNode.GetItems(Rect, ref ItemsList);
            }
        }

        /// <summary>
        /// Get a list of all items in the quadtree
        /// </summary>
        /// <param name="ItemsFound">The list to add found items to (list will not be cleared first)</param>
        public void GetAllItems(ref List<QuadTreePositionItem<T>> ItemsList)
        {
            if (ItemsList != null)
            {
                headNode.GetAllItems(ref ItemsList);
            }
        }
    }


}