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