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_DETAIL_TREE_MAP_NEAREST_ITERATOR_HPP
43#define UFO_CONTAINER_DETAIL_TREE_MAP_NEAREST_ITERATOR_HPP
44
45// UFO
46#include <ufo/container/tree/index.hpp>
47#include <ufo/geometry/distance.hpp>
48#include <ufo/geometry/dynamic_geometry.hpp>
49
50// STL
51#include <cassert>
52#include <cmath>
53#include <cstddef>
54#include <iterator>
55#include <queue>
56#include <type_traits>
57
58namespace ufo
59{
60// Forward declare
61template <std::size_t Dim, class T>
62class TreeMap;
63
64template <bool Const, std::size_t Dim, class T, class Geometry = DynamicGeometry>
66{
67 private:
68 //
69 // Friends
70 //
71
72 template <bool, std::size_t, class, class>
73 friend class TreeMapNearestIterator;
74
75 friend class TreeMap<Dim, T>;
76
77 private:
78 static constexpr std::size_t const BF = TreeMap<Dim, T>::branchingFactor();
79
80 using RawIterator =
81 std::conditional_t<Const, typename TreeMap<Dim, T>::container_type::const_iterator,
83
84 using Point = typename TreeMap<Dim, T>::Point;
85
86 struct S {
87 float dist_sq;
88 TreeIndex node;
89 RawIterator it;
90
91 S(float dist_sq, TreeIndex node, RawIterator it = {}) noexcept
92 : dist_sq(dist_sq), node(node), it(it)
93 {
94 }
95
96 bool operator>(S const& rhs) const noexcept { return dist_sq > rhs.dist_sq; }
97 };
98
99 using Queue = std::priority_queue<S, std::vector<S>, std::greater<S>>;
100
101 public:
102 //
103 // Tags
104 //
105
106 using iterator_category = std::forward_iterator_tag;
107 using difference_type = std::ptrdiff_t;
108 using value_type = typename std::iterator_traits<RawIterator>::value_type;
109 using reference = typename std::iterator_traits<RawIterator>::reference;
110 using pointer = typename std::iterator_traits<RawIterator>::pointer;
111
112 TreeMapNearestIterator() = default;
113
115
116 // From non-const to const or change of geometry type
117 template <bool Const2, class Geometry2,
118 std::enable_if_t<(Const && !Const2) || (Const == Const2 &&
119 !std::is_same_v<Geometry, Geometry2>),
120 bool> = true>
122 : tm_(other.tm_), query_(other.query_), epsilon_sq_(other.epsilon_sq_)
123 {
124 auto queue = other.queue_;
125 while (!queue.empty()) {
126 queue_.emplace(queue.top().dist_sq, queue.top().node, queue.top().it);
127 queue.pop();
128 }
129 }
130
131 TreeMapNearestIterator& operator++()
132 {
133 queue_.pop();
134 next();
135 return *this;
136 }
137
138 TreeMapNearestIterator operator++(int)
139 {
140 TreeMapNearestIterator tmp(*this);
141 ++*this;
142 return tmp;
143 }
144
145 reference operator*() const { return *queue_.top().it; }
146
147 pointer operator->() const { return &*queue_.top().it; }
148
149 template <bool Const2, class Geometry2>
150 bool operator==(TreeMapNearestIterator<Const2, Dim, T, Geometry2> const& other)
151 {
152 return queue_.empty() == other.queue_.empty() &&
153 (queue_.empty() || queue_.top().it == other.queue_.top().it);
154 }
155
156 template <bool Const2, class Geometry2>
157 bool operator!=(TreeMapNearestIterator<Const2, Dim, T, Geometry2> const& other)
158 {
159 return !(*this == other);
160 }
161
162 private:
163 [[nodiscard]] bool returnable(TreeIndex node) const
164 {
165 return tm_->isPureLeaf(node) && !tm_->empty(node);
166 }
167
168 [[nodiscard]] bool returnable(S const& s) const { return RawIterator{} != s.it; }
169
170 [[nodiscard]] bool traversable(TreeIndex node) const { return tm_->isParent(node); }
171
172 void next()
173 {
174 while (!queue_.empty()) {
175 auto cur = queue_.top();
176 if (returnable(cur)) {
177 return;
178 }
179
180 queue_.pop();
181
182 if (returnable(cur.node)) {
183 auto& v = tm_->values(cur.node);
184 using std::begin;
185 using std::end;
186 for (auto it = begin(v), last = end(v); it != last; ++it) {
187 Point p = it->first;
188 float dist_sq = distanceSquared(query_, p);
189 queue_.emplace(dist_sq, cur.node, it);
190 }
191 continue;
192 }
193
194 TreeIndex node = tm_->child(cur.node, 0);
195 for (; BF > node.offset; ++node.offset) {
196 if (!traversable(node) && !returnable(node)) {
197 continue;
198 }
199
200 float dist_sq = distanceSquared(query_, tm_->bounds(node)) + epsilon_sq_;
201 queue_.emplace(dist_sq, node);
202 }
203 }
204 }
205
206 [[nodiscard]] RawIterator iterator() { return queue_.top().it; }
207
208 private:
209 TreeMapNearestIterator(TreeMap<Dim, T>* tm, TreeIndex node, Geometry const& query,
210 float epsilon = 0.0f)
211 : tm_(tm), query_(query), epsilon_sq_(epsilon * epsilon)
212 {
213 if (traversable(node) || returnable(node)) {
214 float dist_sq = distanceSquared(query_, tm_->bounds(node));
215 queue_.emplace(dist_sq, node);
216 next();
217 }
218 }
219
220 // From const to non-const
221 template <bool Const2, class Geometry2, std::enable_if_t<!Const && Const2, bool> = true>
223 : tm_(other.tm), query_(other.query_), epsilon_sq_(other.epsilon_sq_)
224 {
225 auto queue = other.queue_;
226 while (!queue.empty()) {
227 auto const& cur = queue.top();
228 // Remove const from it
229 queue_.emplace(cur.dist_sq, cur.node, tm_->values(cur.node).erase(cur.it, cur.it));
230 queue.pop();
231 }
232 }
233
234 private:
235 TreeMap<Dim, T>* tm_ = nullptr;
236
237 Geometry query_;
238 float epsilon_sq_;
239
240 Queue queue_;
241};
242} // namespace ufo
243
244#endif // UFO_CONTAINER_DETAIL_TREE_MAP_NEAREST_ITERATOR_HPP
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
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