![]() |
Pangolin
Header-only C++20 plane computational geometry library
|
Static shape tree of bounded shapes. More...
#include <shapetree.hpp>
Public Types | |
| using | ShapeType = S |
| using | WeightFunction = WeightFn |
| using | Rect = std::remove_cvref_t<decltype(std::declval<const S&>().bbox())> |
| using | PointType = typename Rect::PointType |
| using | NumberType = typename PointType::NumberType |
| using | WeightType = std::remove_cvref_t<std::invoke_result_t<const WeightFn&, const ShapeType&>> |
| using | value_type = ShapeType |
| using | size_type = std::size_t |
| using | const_iterator = typename std::vector<ShapeType>::const_iterator |
| using | const_reference = const ShapeType& |
Public Member Functions | |
| ShapeTree ()=default | |
| template<class Container> | |
| ShapeTree (const Container &shapes, std::size_t leafSize=defaultLeafSize, WeightFn weight=WeightFn{}) | |
| Builds the tree from a container of shapes. | |
| template<class Container> | |
| ShapeTree (const Container &shapes, WeightFn weight) | |
| Builds the tree from a container of shapes with a weight function. | |
| std::size_t | size () const |
| Returns the number of stored shapes. | |
| bool | empty () const |
| Returns whether the tree is empty. | |
| const std::vector< ShapeType > & | shapes () const |
| Returns the stored shapes in their internal order. | |
| const_iterator | begin () const |
| Returns an iterator to the first stored shape. | |
| const_iterator | end () const |
| Returns an iterator past the last stored shape. | |
| const_iterator | cbegin () const |
| Returns an iterator to the first stored shape. | |
| const_iterator | cend () const |
| Returns an iterator past the last stored shape. | |
| void | insert (const ShapeType &shape) |
| Inserts a shape without rebalancing the existing tree. | |
| void | rebuild (std::size_t leafSize=0) |
| Rebuilds the tree from the stored shapes, restoring its quality. | |
| bool | erase (const ShapeType &shape) |
| Removes one stored shape equal to shape. | |
| template<class Q> | |
| std::size_t | countIntersecting (const Q &q) const |
| Counts the stored shapes intersecting a query shape. | |
| template<class Q> | |
| WeightType | sumIntersecting (const Q &q) const |
| Sums the weights of the stored shapes intersecting a query shape. | |
| template<class Q> | |
| std::vector< ShapeType > | reportIntersecting (const Q &q) const |
| Returns copies of the stored shapes intersecting a query shape. | |
| template<class Q, class Fn> | |
| bool | visitIntersecting (const Q &q, Fn fn) const |
| Calls fn on each stored shape intersecting a query shape. | |
| template<class Q> | |
| bool | emptyIntersecting (const Q &q) const |
| Returns whether no stored shape intersects a query shape. | |
| template<class Q> | |
| std::size_t | countContainedIn (const Q &q) const |
| Counts the stored shapes contained in a query shape. | |
| template<class Q> | |
| WeightType | sumContainedIn (const Q &q) const |
| Sums the weights of the stored shapes contained in a query shape. | |
| template<class Q> | |
| std::vector< ShapeType > | reportContainedIn (const Q &q) const |
| Returns copies of the stored shapes contained in a query shape. | |
| template<class Q, class Fn> | |
| bool | visitContainedIn (const Q &q, Fn fn) const |
| Calls fn on each stored shape contained in a query shape. | |
| template<class Q> | |
| bool | emptyContainedIn (const Q &q) const |
| Returns whether no stored shape is contained in a query shape. | |
| bool | has (const ShapeType &shape) const |
| Returns whether a shape equal to shape is stored in the tree. | |
| template<class Q> | |
| const ShapeType & | nearestNeighbor (const Q &q) const |
| Returns the stored shape nearest to a query shape. | |
| template<class ResultNumber, class Q> | |
| const ShapeType & | nearestNeighbor (const Q &q) const |
| template<class Q> | |
| std::vector< ShapeType > | kNearestNeighbors (const Q &q, int k) const |
| Returns up to k stored shapes nearest to a query shape. | |
| template<class ResultNumber, class Q> | |
| std::vector< ShapeType > | kNearestNeighbors (const Q &q, int k) const |
| template<class Q> | |
| const ShapeType & | nearestNeighborL1 (const Q &q) const |
| Returns the stored shape nearest to a query shape under the L1 (Manhattan) metric. | |
| template<class ResultNumber, class Q> | |
| const ShapeType & | nearestNeighborL1 (const Q &q) const |
| template<class Q> | |
| const ShapeType & | nearestNeighborLInf (const Q &q) const |
| Returns the stored shape nearest to a query shape under the LInf (Chebyshev) metric. | |
| template<class ResultNumber, class Q> | |
| const ShapeType & | nearestNeighborLInf (const Q &q) const |
| std::vector< Rect > | boundingBoxes () const |
| Returns every node's subtree bounding box in pre-order. | |
Friends | |
| Canvas & | operator<< (Canvas &canvas, const ShapeTree &tree) |
| Draws every node's subtree bounding box to a canvas in pre-order. | |
Static shape tree of bounded shapes.
| S | Any shape type exposing bbox() (Point, Segment, Triangle, Rectangle, Convex, Polygon, ...). Infinite shapes such as Line, Ray and Halfplane have no finite bounding box and are not supported. |
| WeightFn | Callable mapping a ShapeType to a weight (any type with operator+ whose value-initialization is the additive identity). Defaults to a no-op returning an empty type, so weights are ignored unless a real function is supplied. |
| using pgl::ShapeTree< S, WeightFn >::const_iterator = typename std::vector<ShapeType>::const_iterator |
| using pgl::ShapeTree< S, WeightFn >::const_reference = const ShapeType& |
| using pgl::ShapeTree< S, WeightFn >::NumberType = typename PointType::NumberType |
| using pgl::ShapeTree< S, WeightFn >::PointType = typename Rect::PointType |
| using pgl::ShapeTree< S, WeightFn >::Rect = std::remove_cvref_t<decltype(std::declval<const S&>().bbox())> |
| using pgl::ShapeTree< S, WeightFn >::ShapeType = S |
| using pgl::ShapeTree< S, WeightFn >::size_type = std::size_t |
| using pgl::ShapeTree< S, WeightFn >::value_type = ShapeType |
| using pgl::ShapeTree< S, WeightFn >::WeightFunction = WeightFn |
| using pgl::ShapeTree< S, WeightFn >::WeightType = std::remove_cvref_t<std::invoke_result_t<const WeightFn&, const ShapeType&>> |
|
default |
|
inlineexplicit |
Builds the tree from a container of shapes.
| Container | Range whose value type is convertible to ShapeType. |
| shapes | Shapes to store. |
| leafSize | Maximum elements kept at a leaf before it is split. |
| weight | Weight function applied to each shape (defaults to a no-op). |
|
inlineexplicit |
Builds the tree from a container of shapes with a weight function.
Uses the default leaf size.
| Container | Range whose value type is convertible to ShapeType. |
| shapes | Shapes to store. |
| weight | Weight function applied to each shape. |
|
inlinenodiscard |
Returns an iterator to the first stored shape.
|
inlinenodiscard |
Returns every node's subtree bounding box in pre-order.
Visits the root, then the left subtree, then the right subtree, collecting each node's cached bounding box. The result is empty for an empty tree.
|
inlinenodiscard |
Returns an iterator to the first stored shape.
|
inlinenodiscard |
Returns an iterator past the last stored shape.
|
inlinenodiscard |
Counts the stored shapes contained in a query shape.
A stored shape matches when it lies inside q (q.contains(element)). Note this is directional: q.contains(element) is not the same as element.contains(q).
| Q | Query shape type. |
| q | Query shape. |
|
inlinenodiscard |
Counts the stored shapes intersecting a query shape.
Subtrees whose bounding box does not meet the query are pruned; surviving candidates are tested with the exact intersects predicate.
| Q | Query shape type. |
| q | Query shape. |
|
inlinenodiscard |
Returns whether the tree is empty.
|
inlinenodiscard |
Returns whether no stored shape is contained in a query shape.
Stops as soon as a contained shape is found.
| Q | Query shape type. |
| q | Query shape. |
|
inlinenodiscard |
Returns whether no stored shape intersects a query shape.
Stops as soon as an intersecting shape is found.
| Q | Query shape type. |
| q | Query shape. |
|
inlinenodiscard |
Returns an iterator past the last stored shape.
|
inline |
Removes one stored shape equal to shape.
Descends to the node owning an element equal to shape (pruning by the cached boxes), removes it, and on the way back up decrements each node's count, subtracts the removed weight, and recomputes bounding boxes from the removal point upward until a box is unchanged. A node left empty is detached from its parent and reclaimed. The element is then swap-removed from storage and the moved element's reference is updated, so shapes() stays compact; detached node slots are likewise swap-removed from the node array, so it does not grow under interleaved insert/erase.
Like insert, this does not rebalance, so the structure degrades over many removals; rebuild restores it. Only the element order in shapes() may change.
| shape | Shape to remove. |
|
inlinenodiscard |
Returns whether a shape equal to shape is stored in the tree.
Tests exact membership with operator==, pruning any subtree whose cached box does not contain the shape's bounding box. This is distinct from the geometric *ContainedIn queries: it matches a stored shape identical to shape, not one geometrically inside a query region.
| shape | Shape to look for. |
|
inline |
Inserts a shape without rebalancing the existing tree.
The element is routed down the tree, keeping every visited node's box, count and weight sum up to date and preserving the invariant that the two child boxes of a node stay disjoint: a child takes the element only if its grown box remains disjoint from its sibling's; when both qualify the one enlarged least is chosen; when neither does the element is kept at the node. A leaf that overflows the leaf size is split with the best split.
Each insertion is O(height) and never reshapes the existing nodes, so the tree quality degrades over many insertions; rebuild from shapes() to restore it.
| shape | Shape to insert. |
|
inlinenodiscard |
|
inlinenodiscard |
Returns up to k stored shapes nearest to a query shape.
The result contains copies of the stored shapes in nondecreasing squared distance from q. If k exceeds the tree size, every stored shape is returned. A non-positive k or an empty tree produces an empty vector.
| ResultNumber | Explicit coordinate type of the squared distance. |
| Q | Query shape type. |
| q | Query shape. |
| k | Maximum number of neighbors to return. |
|
inlinenodiscard |
|
inlinenodiscard |
Returns the stored shape nearest to a query shape.
Finds the stored shape minimizing squaredDistance to q, using a branch-and-bound traversal: each node's cached bounding box gives a lower bound on the distance from q to anything in that subtree (via q.squaredDistance(Rectangle)), so subtrees that cannot hold a closer shape than the best found are pruned, and the nearer child box is descended first to tighten the bound early.
With no explicit result type, the concrete shape pair chooses its natural type: native arithmetic when the metric uses no division, division_result_t when it may produce a fraction, and double when a Disk makes an irrational result possible. An explicitly requested integral ResultNumber may truncate fractional distances; the box lower bound remains conservative in that case.
If a Disk is involved (as ShapeType or as Q), that leg may be irrational and is computed in double, then converted to the common comparison type. Other legs stay exact.
The reference points into the tree's own storage and stays valid until the tree is destroyed or modified (e.g. by insert).
| ResultNumber | Explicit coordinate type of the squared distance. |
| Q | Query shape type. |
| q | Query shape. |
|
inlinenodiscard |
|
inlinenodiscard |
Returns the stored shape nearest to a query shape under the L1 (Manhattan) metric.
Same branch-and-bound traversal as nearestNeighbor, but minimizes distanceL1 instead of squaredDistance.
| ResultNumber | Explicit coordinate type of the distance. |
| Q | Query shape type. |
| q | Query shape. |
|
inlinenodiscard |
|
inlinenodiscard |
Returns the stored shape nearest to a query shape under the LInf (Chebyshev) metric.
Same branch-and-bound traversal as nearestNeighbor, but minimizes distanceLInf instead of squaredDistance.
| ResultNumber | Explicit coordinate type of the distance. |
| Q | Query shape type. |
| q | Query shape. |
|
inline |
Rebuilds the tree from the stored shapes, restoring its quality.
insert never reshapes existing nodes, so the structure degrades over many insertions; this discards the node structure and rebuilds it from scratch (the same way the constructor does) over the current shapes, leaving the stored shapes and their order unchanged.
| leafSize | Maximum elements kept at a leaf before it is split. Pass 0 to keep the current leaf size. |
|
inlinenodiscard |
Returns copies of the stored shapes contained in a query shape.
| Q | Query shape type. |
| q | Query shape. |
|
inlinenodiscard |
Returns copies of the stored shapes intersecting a query shape.
Subtrees whose bounding box does not meet the query are pruned; subtrees fully inside the query are collected without per-element tests.
| Q | Query shape type. |
| q | Query shape. |
|
inlinenodiscard |
Returns the stored shapes in their internal order.
|
inlinenodiscard |
Returns the number of stored shapes.
|
inlinenodiscard |
Sums the weights of the stored shapes contained in a query shape.
| Q | Query shape type. |
| q | Query shape. |
|
inlinenodiscard |
Sums the weights of the stored shapes intersecting a query shape.
Like countIntersecting, but accumulates the weight function instead of counting. Subtrees fully inside the query contribute their cached weight sum without descending.
| Q | Query shape type. |
| q | Query shape. |
|
inline |
Calls fn on each stored shape contained in a query shape.
If fn returns bool, returning true stops the traversal immediately; a void-returning fn always visits every match.
| Q | Query shape type. |
| Fn | Callable invocable with const ShapeType&, returning void or bool (return true to stop). |
| q | Query shape. |
| fn | Function to call on each contained shape. |
|
inline |
Calls fn on each stored shape intersecting a query shape.
Shapes are visited as they are found during traversal. Subtrees disjoint from the query are pruned; subtrees fully inside it are visited without per-element tests.
If fn returns bool, returning true stops the traversal immediately; a void-returning fn always visits every match.
| Q | Query shape type. |
| Fn | Callable invocable with const ShapeType&, returning void or bool (return true to stop). |
| q | Query shape. |
| fn | Function to call on each intersecting shape. |
|
friend |
Draws every node's subtree bounding box to a canvas in pre-order.
Sends each box returned by boundingBoxes to the canvas with its current style.
| canvas | Destination canvas. |
| tree | Tree whose node boxes are drawn. |