UFO 1.0.0
An Efficient Probabilistic 3D Mapping Framework That Embraces the Unknown
Loading...
Searching...
No Matches
nearest_iterator.hpp
1
42#ifndef UFO_CONTAINER_TREE_NEAREST_ITERATOR_HPP
43#define UFO_CONTAINER_TREE_NEAREST_ITERATOR_HPP
44
45// UFO
46#include <ufo/container/tree/index.hpp>
47#include <ufo/geometry/dynamic_geometry.hpp>
48
49// STL
50#include <cmath>
51#include <cstddef>
52#include <iterator>
53#include <queue>
54
55namespace ufo
56{
57template <class Tree, class Geometry = DynamicGeometry>
59{
60 private:
61 //
62 // Friends
63 //
64
65 template <class, class>
66 friend class TreeNearestIterator;
67
68 private:
69 static constexpr std::size_t const BF = Tree::branchingFactor();
70
71 using Node = typename Tree::Node;
72 using DistanceNode = typename Tree::DistanceNode;
73 using offset_t = typename Tree::offset_t;
74
75 struct S {
76 float dist_sq;
77 Node node;
78 bool returnable;
79
80 S(float dist_sq, Node node, bool returnable) noexcept
81 : dist_sq(dist_sq), node(node), returnable(returnable)
82 {
83 }
84
85 bool operator>(S const& rhs) const noexcept { return dist_sq > rhs.dist_sq; }
86 };
87
88 using Queue = std::priority_queue<S, std::vector<S>, std::greater<S>>;
89
90 public:
91 //
92 // Tags
93 //
94
95 using iterator_category = std::forward_iterator_tag;
96 using difference_type = std::ptrdiff_t;
97 using value_type = DistanceNode;
98 using reference = value_type const&;
99 using pointer = value_type const*;
100
101 constexpr TreeNearestIterator() = default;
102
103 TreeNearestIterator(Tree* t, Node const& node, Geometry const& geometry, float epsilon,
104 bool only_leaves, bool only_exists)
105 : t_(t)
106 , query_(geometry)
107 , epsilon_sq_(epsilon * epsilon)
108 , only_leaves_(only_leaves)
109 , only_exists_(only_exists)
110 {
111 if (only_exists_ && !t_->exists(node)) {
112 return;
113 }
114
115 float dist_sq = distanceSquared(query_, t_->bounds(node));
116 if (returnable(node)) {
117 queue_.emplace(dist_sq, node, true);
118 }
119 if (traversable(node)) {
120 queue_.emplace(dist_sq + epsilon_sq_, node, false);
121 }
122
123 nextNode();
124 }
125
127
128 template <class Geometry2>
130 : t_(other.t_)
131 , query_(other.query_)
132 , epsilon_sq_(other.epsilon_sq_)
133 , queue_(other.queue_)
134 , ret_(other.ret_)
135 , only_leaves_(other.only_leaves_)
136 , only_exists_(other.only_exists_)
137 {
138 }
139
140 TreeNearestIterator& operator++()
141 {
142 queue_.pop();
143 nextNode();
144 return *this;
145 }
146
147 TreeNearestIterator operator++(int)
148 {
149 TreeNearestIterator tmp(*this);
150 ++*this;
151 return tmp;
152 }
153
154 reference operator*() const { return ret_; }
155
156 pointer operator->() const { return &ret_; }
157
158 template <class Geometry2>
159 bool operator==(TreeNearestIterator<Tree, Geometry2> const& other)
160 {
161 return ret_ == other.ret_;
162 }
163
164 template <class Geometry2>
165 bool operator!=(TreeNearestIterator<Tree, Geometry2> const& other)
166 {
167 return !(*this == other);
168 }
169
170 private:
171 [[nodiscard]] bool returnable(Node const& node) const
172 {
173 return !only_leaves_ || t_->isLeaf(node.index);
174 }
175
176 [[nodiscard]] bool returnable(S const& s) const { return s.returnable; }
177
178 [[nodiscard]] bool traversable(Node const& node) const
179 {
180 return t_->isParent(node.index) || (!only_exists_ && !t_->isPureLeaf(node.code));
181 }
182
183 [[nodiscard]] bool exists(Node const& node) const
184 {
185 return only_exists_ || t_->code(node.index) == node.code;
186 }
187
188 [[nodiscard]] Node sibling(Node const& node, offset_t sibling_index) const
189 {
190 return Node(t_->sibling(node.code, sibling_index),
191 exists(node) ? t_->sibling(node.index, sibling_index) : node.index);
192 }
193
194 [[nodiscard]] Node child(Node const& node, offset_t child_index) const
195 {
196 return Node(
197 t_->child(node.code, child_index),
198 t_->isParent(node.index) ? t_->child(node.index, child_index) : node.index);
199 }
200
201 [[nodiscard]] Node parent(Node const& node) const
202 {
203 return Node(t_->parent(node.code),
204 exists(node) ? t_->parent(node.index) : node.index);
205 }
206
207 [[nodiscard]] offset_t offset(Node const& node) const { return node.code.offset(); }
208
209 void nextNode()
210 {
211 while (!queue_.empty()) {
212 S cur = queue_.top();
213 if (returnable(cur)) {
214 ret_ = DistanceNode(cur.node, std::sqrt(cur.dist_sq));
215 return;
216 }
217
218 queue_.pop();
219
220 Node node = child(cur.node, 0);
221 for (offset_t i{}; BF > i; ++i) {
222 node = sibling(node, i);
223
224 float dist_sq = distanceSquared(query_, t_->bounds(node));
225 if (returnable(node)) {
226 queue_.emplace(dist_sq, node, true);
227 }
228 if (traversable(node)) {
229 queue_.emplace(dist_sq + epsilon_sq_, node, false);
230 }
231 }
232 }
233 }
234
235 private:
236 Tree* t_ = nullptr;
237
238 Geometry query_;
239 float epsilon_sq_;
240
241 Queue queue_;
242 DistanceNode ret_;
243
244 bool only_leaves_{};
245 bool only_exists_{};
246};
247} // namespace ufo
248
249#endif // UFO_CONTAINER_TREE_NEAREST_ITERATOR_HPP
constexpr code_type offset() const
Get the offset at the current depth (same as c.offset(c.depth())).
Definition code.hpp:314
Utilizing curiously recurring template pattern (CRTP)
Definition tree.hpp:104
bool isParent(NodeType node) const
Checks if the node is a parent (i.e., has children).
Definition tree.hpp:1308
bool isPureLeaf(pos_type block) const
Checks if the block is pure leaf (i.e., can never have children).
Definition tree.hpp:1256
constexpr auto child(NodeType node, offset_type offset) const
Returns the i:th child of node.
Definition tree.hpp:1450
static constexpr offset_type branchingFactor() noexcept
Returns the branching factor of the tree (i.e., 2 = binary tree, 4 = quadtree, 8 = octree,...
Definition tree.hpp:203
bool isLeaf(NodeType node) const
Checks if the node is a leaf (i.e., has no children).
Definition tree.hpp:1292
Bounds bounds() const
Returns the bounds of the tree (/ root node).
Definition tree.hpp:567
All vision-related classes and functions.
Definition cloud.hpp:49
constexpr auto distanceSquared(A const &a, B const &b)
Computes the minimum squared distance between two shapes.
Definition distance.hpp:80