UFO 1.0.0
An Efficient Probabilistic 3D Mapping Framework That Embraces the Unknown
Loading...
Searching...
No Matches
query_nearest_iterator.hpp
1
42#ifndef UFO_CONTAINER_TREE_QUERY_NEAREST_ITERATOR_HPP
43#define UFO_CONTAINER_TREE_QUERY_NEAREST_ITERATOR_HPP
44
45// UFO
46#include <ufo/container/tree/index.hpp>
47#include <ufo/container/tree/predicate/filter.hpp>
48#include <ufo/container/tree/predicate/predicate.hpp>
49#include <ufo/geometry/dynamic_geometry.hpp>
50
51// STL
52#include <cmath>
53#include <cstddef>
54#include <iterator>
55#include <queue>
56
57namespace ufo
58{
59template <class Tree, class Predicate = pred::Predicate<Tree>,
60 class Geometry = DynamicGeometry>
62{
63 private:
64 //
65 // Friends
66 //
67
68 template <class, class, class>
69 friend class TreeQueryNearestIterator;
70
71 private:
72 static constexpr std::size_t const BF = Tree::branchingFactor();
73
74 using Node = typename Tree::Node;
75 using DistanceNode = typename Tree::DistanceNode;
76 using offset_t = typename Tree::offset_t;
77
79
80 struct S {
81 float dist_sq;
82 Node node;
83 bool returnable;
84
85 S(float dist_sq, Node node, bool returnable) noexcept
86 : dist_sq(dist_sq), node(node), returnable(returnable)
87 {
88 }
89
90 bool operator>(S const& rhs) const noexcept { return dist_sq > rhs.dist_sq; }
91 };
92
93 using Queue = std::priority_queue<S, std::vector<S>, std::greater<S>>;
94
95 public:
96 //
97 // Tags
98 //
99
100 using iterator_category = std::forward_iterator_tag;
101 using difference_type = std::ptrdiff_t;
102 using value_type = DistanceNode;
103 using reference = value_type const&;
104 using pointer = value_type const*;
105
106 constexpr TreeQueryNearestIterator() = default;
107
108 TreeQueryNearestIterator(Tree* t, Node const& node, Predicate const& pred,
109 Geometry const& geometry, float epsilon, bool only_exists,
110 bool early_stopping)
111 : t_(t)
112 , pred_(pred)
113 , query_(geometry)
114 , epsilon_sq_(epsilon * epsilon)
115 , only_exists_(only_exists)
116 , early_stopping_(early_stopping)
117 {
118 Filter::init(pred_, *t_);
119
120 if (only_exists_ && !t_->exists(node)) {
121 return;
122 }
123
124 float dist_sq = distanceSquared(query_, t_->bounds(node));
125 if (returnable(node)) {
126 queue_.emplace(dist_sq, node, true);
127
128 if (!early_stopping_ && traversable(node)) {
129 queue_.emplace(dist_sq + epsilon_sq_, node, false);
130 }
131 } else if (traversable(node)) {
132 queue_.emplace(dist_sq + epsilon_sq_, node, false);
133 }
134
135 nextNode();
136 }
137
139
140 template <class Predicate2, class Geometry2>
143 : t_(other.t_)
144 , pred_(other.pred)
145 , query_(other.query_)
146 , epsilon_sq_(other.epsilon_sq_)
147 , queue_(other.queue_)
148 , ret_(other.ret_)
149 , only_exists_(other.only_exists_)
150 , early_stopping_(other.early_stopping_)
151 {
152 }
153
154 TreeQueryNearestIterator& operator++()
155 {
156 queue_.pop();
157 nextNode();
158 return *this;
159 }
160
161 TreeQueryNearestIterator operator++(int)
162 {
163 TreeQueryNearestIterator tmp(*this);
164 ++*this;
165 return tmp;
166 }
167
168 reference operator*() const { return ret_; }
169
170 pointer operator->() const { return &ret_; }
171
172 template <class Predicate2, class Geometry2>
174 {
175 return ret_ == other.ret_;
176 }
177
178 template <class Predicate2, class Geometry2>
180 {
181 return !(*this == other);
182 }
183
184 private:
185 [[nodiscard]] bool returnable(Node const& node) const
186 {
187 return Filter::returnable(pred_, *t_, node);
188 }
189
190 [[nodiscard]] bool returnable(S const& s) const { return s.returnable; }
191
192 [[nodiscard]] bool traversable(Node const& node) const
193 {
194 return (t_->isParent(node.index) || (!only_exists_ && !t_->isPureLeaf(node.code))) &&
195 Filter::traversable(pred_, *t_, node);
196 }
197
198 [[nodiscard]] bool exists(Node const& node) const
199 {
200 return only_exists_ || t_->code(node.index) == node.code;
201 }
202
203 [[nodiscard]] Node sibling(Node const& node, offset_t sibling_index) const
204 {
205 return Node(t_->sibling(node.code, sibling_index),
206 exists(node) ? t_->sibling(node.index, sibling_index) : node.index);
207 }
208
209 [[nodiscard]] Node child(Node const& node, offset_t child_index) const
210 {
211 return Node(
212 t_->child(node.code, child_index),
213 t_->isParent(node.index) ? t_->child(node.index, child_index) : node.index);
214 }
215
216 [[nodiscard]] Node parent(Node const& node) const
217 {
218 return Node(t_->parent(node.code),
219 exists(node) ? t_->parent(node.index) : node.index);
220 }
221
222 [[nodiscard]] offset_t offset(Node const& node) const { return node.code.offset(); }
223
224 void nextNode()
225 {
226 while (!queue_.empty()) {
227 S cur = queue_.top();
228 if (returnable(cur)) {
229 ret_ = DistanceNode(cur.node, std::sqrt(cur.dist_sq));
230 return;
231 }
232
233 queue_.pop();
234
235 Node node = child(cur.node, 0);
236 for (offset_t i{}; BF > i; ++i) {
237 node = sibling(node, i);
238
239 float dist_sq = distanceSquared(query_, t_->bounds(node));
240 if (returnable(node)) {
241 queue_.emplace(dist_sq, node, true);
242
243 if (!early_stopping_ && traversable(node)) {
244 queue_.emplace(dist_sq + epsilon_sq_, node, false);
245 }
246 } else if (traversable(node)) {
247 queue_.emplace(dist_sq + epsilon_sq_, node, false);
248 }
249 }
250 }
251 }
252
253 private:
254 Tree* t_ = nullptr;
255
256 Predicate pred_;
257
258 Geometry query_;
259 float epsilon_sq_;
260
261 Queue queue_;
262 DistanceNode ret_{};
263
264 bool only_exists_{};
265 bool early_stopping_{};
266};
267} // namespace ufo
268
269#endif // UFO_CONTAINER_TREE_QUERY_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
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