#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