#region CPL License /* Nuclex Framework Copyright (C) 2002-2011 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #endregion #if ENABLE_QUADTREES using System; using System.Collections.Generic; using Microsoft.Xna.Framework; namespace Nuclex.Game.Space { // Flaws: // - Unsplittable nodes are not correctly identified. If ten nodes are outside // of the tree's corners, these are counted as unsplittable. Add more items // to the same quadrant, and it will be split. However, the firstSplittableItem // will point past the items in the corner, causing items outside of the tree // to end up in an inner (non-border) node // - Far too complicated to remain efficient /// Tree that breaks down space into quadrants /// Type of the items being indexed by the tree public partial class QuadTree : SpatialIndex2 where ItemType : IBoundingRectangleProvider { #region class Node /// A node in a quad-tree private class Node { /// Initializes the quad-tree node /// Bounding rectangle of the node /// Item capacity for the node public Node(BoundingRectangle boundingRectangle, int capacity) { this.BoundingRectangle = boundingRectangle; this.Center = new Vector2( (boundingRectangle.Min.X + boundingRectangle.Max.X) / 2.0f, (boundingRectangle.Min.Y + boundingRectangle.Max.Y) / 2.0f ); this.Items = new ItemType[capacity]; } /// Bounding rectangle of this node public BoundingRectangle BoundingRectangle; /// The center point of the node public Vector2 Center; /// The top-left child of this node public Node TL; /// The top-right child of this node public Node TR; /// The bottom-left child of this node public Node BL; /// The bottom-right child of this node public Node BR; /// Items contained in this node public ItemType[] Items; /// Number of items stored in the item array public int ItemCount; /// Index of the first item that is suitable for splitting public int FirstSplittableItemIndex; } #endregion // class Node /// Initializes a new quadtree /// /// Limits of the quad-tree. Setting this too small will make it impossible /// for the tree to work. /// public QuadTree(BoundingRectangle bounds) : this(bounds, EqualityComparer.Default) { } /// Initializes a new quadtree /// /// Limits of the quad-tree. Setting this too small will make it impossible /// for the tree to work. /// /// /// Comparer that will be used to recognize items when they're accessed /// public QuadTree(BoundingRectangle bounds, IEqualityComparer comparer) { this.MinItemsPerNode = 32; this.MaxItemsPerNode = 64; this.root = new Node(bounds, this.MaxItemsPerNode); this.comparer = comparer; } /// Maximum number of items per node public int MaxItemsPerNode; /// Minimum number of items per node after collapsing to collapse public int MinItemsPerNode; /// The root node of the quad-tree private Node root; /// Used to compare items to each other private IEqualityComparer comparer; } } // namespace Nuclex.Game.Space #endif // ENABLE_QUADTREES