template<typename T> asge::spatial::QuadTree
Region quadtree over axis-aligned rectangles, rebuilt from scratch via Reset().
#include <QuadTree.hpp>Nodes and the blocks holding their elements live in a fixed-size arena, so Insert never allocates from the heap. A node's elements sit in contiguous fixed-size blocks (bounds and values in separate arrays) chained together when the node overflows. An element sits in the deepest node whose quadrant fully contains it, so elements straddling a split line stay in the parent. Elements cannot be removed individually.
Static Private Attributes
Private Attributes
Private Member Functions
Allocates a node from the arena, or returns nullptr if the arena is full.
Returns an empty block from the free list or the arena, or nullptr if the arena is full.
Pushes the block on the free list for later reuse.
Appends the element to the node's last block, chaining a new one if full.
False if the arena is full.
Returns 0..3 if the input rect fits one quadrant, -1 otherwise.
Recursively inserts an element into the tree.
False only if the arena has no room for it.
Splits the leaf into 4 children and moves the elements that fit a quadrant down.
Elements that straddle a split line, or whose child could not get a block, stay in the node. If the arena cannot hold 4 children the node is left as a leaf.
template<typename NodePred, typename ElemPred, typename Visitor> bool traverse(QuadNode const *inNode, NodePred inNodePred, ElemPred inElemPred, Visitor &inVisitor) constprivateVisits the elements of the subtree for which inElemPred holds, using an explicit fixed-size stack.
A child is entered only if inNodePred holds for its bounds, so the node predicate must be true whenever the element predicate is true for something inside the node. Nodes are visited in the same order as a recursive walk (parent, then children 0..3). Returns false once the visitor asked to stop.
void nearest(QuadNode const *inNode, math::Float2 const &inPoint, float &ioBestDistance, std::optional< T > &ioBest) const noexceptprivateBranch-and-bound step of Nearest: updates the best element found so far in the subtree.
template<typename Visitor> bool visitPairs(QuadNode const *inNode, std::vector< Entry > &ioScratch, std::size_t inAncBegin, std::size_t inAncEnd, Visitor &inVisitor) constprivateReports the overlapping pairs found in the subtree of inNode.
ioScratch[inAncBegin, inAncEnd) holds the ancestor elements that overlap inNode and is the end of the buffer on entry; children append their own filtered list after it and truncate back once visited. Returns false once the visitor asked to stop.
Public Member Functions
QuadTree(std::size_t inArenaBytes, std::size_t inMaxElements)Reserves an arena of inArenaBytes for nodes and element blocks, and caps the tree at inMaxElements.
BoolResult Reset(float inW, float inH) noexceptDrops every element and node, then starts a new empty tree covering [0,inW]x[0,inH].
Errors with invalid_argument unless both sizes are finite and positive, and with no_buffer_space if the arena cannot even hold the root. After an error the tree is empty and uninitialised, so Insert fails until a Reset succeeds.
BoolResult Reset(math::Rect const &inBounds) noexceptLike Reset(inW, inH), but the new tree covers inBounds, which may start away from the origin.
BoolResult Insert(T inElement, math::Rect const &inBounds) noexceptInserts an element with the given bounds.
Errors if Reset() was never called, the bounds are not fully inside the root, the element budget is exhausted, or the arena has no room left for the element. A failed insert leaves the tree valid and unchanged in content.
std::size_t Size() const noexceptNumber of elements currently stored.
template<typename Visitor> void Query(math::Rect const &inRect, Visitor &&inVisitor) constCalls inVisitor(value) for every element overlapping inRect.
The visitor returns true to continue or false to stop the traversal early. Overlap is strict (AabbOverlap), so rects that only touch are not reported.
template<typename Visitor> void Query(math::Float2 const &inPoint, Visitor &&inVisitor) constCalls inVisitor(value) for every element whose rect strictly contains inPoint.
Same visitor protocol as the Rect overload; a point exactly on an element's edge is not inside it.
template<typename Visitor> void Query(math::Circle const &inCircle, Visitor &&inVisitor) constCalls inVisitor(value) for every element whose rect is closer to the circle's center than its radius.
Same visitor protocol as the Rect overload; an element that only touches the circle is not reported.
std::optional< T > Nearest(math::Float2 const &inPoint) const noexceptReturns the value of the element whose rect is closest to inPoint.
The distance is 0 for a point inside or on an element. When several elements are equally close, which one is returned is unspecified. Empty if the tree is empty or uninitialised.
std::size_t NodeCount() const noexceptNumber of nodes created since the last Reset, root included.
std::uint16_t MaxDepthReached() const noexceptDepth of the deepest node created since the last Reset (the root is 0).
bool ArenaExhausted() const noexceptTrue if an arena allocation failed since the last Reset.
It means the tree degraded: some leaf could not split, or an Insert was refused for lack of memory. Compare ArenaUsed() with ArenaCapacity() to size the arena.
std::size_t ArenaUsed() const noexceptArena bytes consumed so far by nodes and element blocks.
std::size_t ArenaCapacity() const noexceptTotal arena size in bytes.
template<typename Visitor> void ForEachPair(Visitor &&inVisitor) constCalls inVisitor(a, b) once for every unordered pair of overlapping elements.
Never pairs an element with itself and never reports a pair twice; the order of the pairs and of the two values within a pair is unspecified. The visitor returns true to continue or false to stop early. Allocates one scratch buffer per call.