/// <summary> /// A manager for a quadtree data structure. /// </summary> /// <param name="x">The x position of the top-left corner of the root node bounding box.</param> /// <param name="y">The y position of the top-left corner of the root node bounding box.</param> /// <param name="width">The width of the root node bounding box.</param> /// <param name="height">The height of the root node bounding box.</param> public GenQuadtree(float x, float y, float width, float height) { MaxObjects = 5; MaxLevels = 5; _rootNode = new GenQuadtreeNode(x, y, width, height, this, null, 0); Objects = new List<GenObject>(); _activeObjects = new List<GenObject>(); _updateObjects = false; _objectLocations = new Dictionary<GenObject, GenQuadtreeNode>(); }
/// <summary> /// A single node within a quadtree data structure. /// Used as a container for objects or other nodes. /// </summary> /// <param name="x">The x position of the top-left corner of the node bounding box.</param> /// <param name="y">The y position of the top-left corner of the node bounding box.</param> /// <param name="width">The width of the node bounding box.</param> /// <param name="height">The height of the node bounding box.</param> /// <param name="quadtree">A reference to the quadtree manager of this node.</param> /// <param name="parentNode">The quadtree node that this node is a leaf of. Use null if this is a root node.</param> /// <param name="level">The split level of the node.</param> public GenQuadtreeNode(float x, float y, float width, float height, GenQuadtree quadtree, GenQuadtreeNode parentNode, int level) : base(x, y, width, height) { _quadtree = quadtree; _parentNode = parentNode; _level = level; _objects = new List<GenObject>(); _objectCount = 0; _nodes = new GenQuadtreeNode[4]; }
internal void Add(GenObject gameObject) { if (_nodes[0] == null) { Insert(gameObject); // If the node is full, attempt to add each of its objects into a leaf node. if ((_objects.Count >= _quadtree.MaxObjects) && (_level < _quadtree.MaxLevels)) { int nextLevel = _level + 1; // Create the leaf nodes. _nodes[0] = new GenQuadtreeNode(_minX, _minY, _halfWidth, _halfHeight, _quadtree, this, nextLevel); _nodes[1] = new GenQuadtreeNode(_midpointX, _minY, _halfWidth, _halfHeight, _quadtree, this, nextLevel); _nodes[2] = new GenQuadtreeNode(_minX, _midpointY, _halfWidth, _halfHeight, _quadtree, this, nextLevel); _nodes[3] = new GenQuadtreeNode(_midpointX, _midpointY, _halfWidth, _halfHeight, _quadtree, this, nextLevel); // Iterate through the objects list in reverse, attempting to add each object into a leaf node. // Otherwise, leave the object in this node. for (int i = _objects.Count - 1; i >= 0; i--) { int index = GetIndex(_objects[i].MoveBounds); if (index != -1) { _nodes[index].Add(_objects[i]); _objects.Remove(_objects[i]); } } } } else { // Since leaf nodes have already been created, attempt to add the object into a leaf node. // Otherwise, add the object to this node. int index = GetIndex(gameObject.MoveBounds); if (index != -1) _nodes[index].Add(gameObject); else Insert(gameObject); } _objectCount++; }
/// <summary> /// Decrements the object cound in a given node. /// Clears each leaf node within the given node if the object count is 0. /// Walks up the tree from the first given node, repeating the process for each parent node. /// </summary> /// <param name="node">The node to check for its object count.</param> protected void CheckObjects(GenQuadtreeNode node) { if (node != null) { if (--node._objectCount <= 0) node.ClearLeaves(); CheckObjects(node._parentNode); } }