UFO 1.0.0
An Efficient Probabilistic 3D Mapping Framework That Embraces the Unknown
Loading...
Searching...
No Matches
key.hpp
1
42#ifndef UFO_CONTAINER_TREE_KEY_HPP
43#define UFO_CONTAINER_TREE_KEY_HPP
44
45// UFO
46#include <ufo/morton/morton.hpp>
47#include <ufo/numeric/vec.hpp>
48
49// STL
50#include <cassert>
51#include <cstddef>
52#include <cstdint>
53#include <functional>
54#include <limits>
55#include <ostream>
56
57namespace ufo
58{
59template <std::size_t Dim>
60class TreeKey : public Vec<Dim, std::uint32_t>
61{
62 public:
63 using key_type = std::uint32_t;
64 using Key = Vec<Dim, key_type>;
65 using depth_type = key_type;
66 using size_type = std::size_t;
67
68 public:
69 /**************************************************************************************
70 | |
71 | Constructors |
72 | |
73 **************************************************************************************/
74
75 constexpr TreeKey() noexcept = default;
76 constexpr TreeKey(TreeKey const&) noexcept = default;
77
78 constexpr TreeKey(Key key, depth_type depth) : Key(key), depth_(depth) {}
79
80 constexpr explicit TreeKey(Key key) : TreeKey(key, 0) {}
81
82 /**************************************************************************************
83 | |
84 | Assignment operator |
85 | |
86 **************************************************************************************/
87
88 constexpr TreeKey& operator=(TreeKey const&) noexcept = default;
89
90 /**************************************************************************************
91 | |
92 | Capacity |
93 | |
94 **************************************************************************************/
95
96 [[nodiscard]] static constexpr depth_type maxDepth() noexcept
97 {
98 // All the time you have to leave the space.
99 // Shifting with `maxDepth()` causes problems when
100 // `std::numeric_limits<key_type>::digits <= maxDepth()` because you are trying to
101 // shift more bits than are allowed and has a well-defined behaviour in C++.
102 // Therefore, we have this check; otherwise, would cause "shift count overflow".
103 return std::numeric_limits<key_type>::digits - 1;
104 }
105
106 /**************************************************************************************
107 | |
108 | Operations |
109 | |
110 **************************************************************************************/
111
112 [[nodiscard]] constexpr bool valid() const noexcept { return maxDepth() >= depth_; }
113
114 [[nodiscard]] constexpr depth_type depth() const noexcept { return depth_; }
115
116 [[nodiscard]] constexpr TreeKey toDepth(depth_type depth) const
117 {
118 assert(maxDepth() >= depth);
119
120 TreeKey ret = *this;
121 ret.setDepth(depth);
122 return ret;
123 }
124
130 constexpr void setDepth(depth_type depth) noexcept
131 {
132 assert(maxDepth() >= depth);
133
134 if (depth_ > depth) {
135 *this <<= depth_ - depth;
136 } else {
137 *this >>= depth - depth_;
138 }
139 this->depth_ = depth;
140 }
141
142 // TODO: Add methods from Code
143
144 [[nodiscard]] constexpr key_type offset() const noexcept { return offset(depth_); }
145
146 [[nodiscard]] constexpr key_type offset(depth_type depth) const noexcept
147 {
148 assert(maxDepth() >= depth);
149 assert(depth_ <= depth);
150
151 auto v = (*this >> (depth - depth_)) & key_type(1);
152 key_type ret = v[0];
153 for (std::size_t i = 1; Dim > i; ++i) {
154 ret |= v[i] << i;
155 }
156 return ret;
157 }
158
159 [[nodiscard]] constexpr TreeKey parent() const
160 {
161 assert(maxDepth() > depth_);
162
163 TreeKey ret = *this;
164 ret >>= 1;
165 ++ret.depth_;
166 return ret;
167 }
168
169 void swap(TreeKey& other) noexcept
170 {
171 using std::swap;
172 static_cast<Key&>(*this).swap(static_cast<Key&>(other));
173 swap(depth_, other.depth_);
174 }
175
176 private:
177 depth_type depth_{};
178};
179
180using BinaryKey = TreeKey<1>;
181using QuadKey = TreeKey<2>;
182using OctKey = TreeKey<3>;
183using HexKey = TreeKey<4>;
184
185template <std::size_t Dim>
186std::ostream& operator<<(std::ostream& out, TreeKey<Dim> const& key)
187{
188 return out << static_cast<typename TreeKey<Dim>::Key const&>(key)
189 << " d: " << key.depth();
190}
191
192template <std::size_t Dim>
193void swap(TreeKey<Dim>& lhs, TreeKey<Dim>& rhs) noexcept
194{
195 lhs.swap(rhs);
196}
197
198/**************************************************************************************
199| |
200| Compare |
201| |
202**************************************************************************************/
203
204template <std::size_t Dim>
205[[nodiscard]] constexpr bool operator==(TreeKey<Dim> const& lhs,
206 TreeKey<Dim> const& rhs) noexcept
207{
208 using Key = typename TreeKey<Dim>::Key;
209 return static_cast<Key const&>(lhs) == static_cast<Key const&>(rhs) &&
210 lhs.depth() == rhs.depth();
211}
212
213template <std::size_t Dim>
214[[nodiscard]] constexpr bool operator!=(TreeKey<Dim> const& lhs,
215 TreeKey<Dim> const& rhs) noexcept
216{
217 return !(lhs == rhs);
218}
219
220template <std::size_t Dim>
221[[nodiscard]] constexpr bool operator<(TreeKey<Dim> const& lhs,
222 TreeKey<Dim> const& rhs) noexcept
223{
224 for (std::size_t i{}; Dim > i; ++i) {
225 if (lhs[i] < rhs[i]) {
226 return true;
227 } else if (lhs[i] > rhs[i]) {
228 return false;
229 }
230 }
231 return false;
232}
233
234template <std::size_t Dim>
235[[nodiscard]] constexpr bool operator<=(TreeKey<Dim> const& lhs,
236 TreeKey<Dim> const& rhs) noexcept
237{
238 for (std::size_t i{}; Dim > i; ++i) {
239 if (lhs[i] < rhs[i]) {
240 return true;
241 } else if (lhs[i] > rhs[i]) {
242 return false;
243 }
244 }
245 return true;
246}
247
248template <std::size_t Dim>
249[[nodiscard]] constexpr bool operator>(TreeKey<Dim> const& lhs,
250 TreeKey<Dim> const& rhs) noexcept
251{
252 for (std::size_t i{}; Dim > i; ++i) {
253 if (lhs[i] > rhs[i]) {
254 return true;
255 } else if (lhs[i] < rhs[i]) {
256 return false;
257 }
258 }
259 return false;
260}
261
262template <std::size_t Dim>
263[[nodiscard]] constexpr bool operator>=(TreeKey<Dim> const& lhs,
264 TreeKey<Dim> const& rhs) noexcept
265{
266 for (std::size_t i{}; Dim > i; ++i) {
267 if (lhs[i] > rhs[i]) {
268 return true;
269 } else if (lhs[i] < rhs[i]) {
270 return false;
271 }
272 }
273 return true;
274}
275
276/**************************************************************************************
277| |
278| Binary operators |
279| |
280**************************************************************************************/
281
282template <std::size_t Dim>
283[[nodiscard]] constexpr TreeKey<Dim> operator+(TreeKey<Dim> key, std::uint32_t v) noexcept
284{
285 key += v;
286 return key;
287}
288
289template <std::size_t Dim>
290[[nodiscard]] constexpr TreeKey<Dim> operator+(TreeKey<Dim> key,
291 Vec<Dim, std::uint32_t> const& v) noexcept
292{
293 key += v;
294 return key;
295}
296
297template <std::size_t Dim>
298[[nodiscard]] constexpr TreeKey<Dim> operator+(std::uint32_t v, TreeKey<Dim> key) noexcept
299{
300 key += v;
301 return key;
302}
303
304template <std::size_t Dim>
305[[nodiscard]] constexpr TreeKey<Dim> operator+(Vec<Dim, std::uint32_t> const& v,
306 TreeKey<Dim> key) noexcept
307{
308 key += v;
309 return key;
310}
311
312template <std::size_t Dim>
313[[nodiscard]] constexpr TreeKey<Dim> operator-(TreeKey<Dim> key, std::uint32_t v) noexcept
314{
315 key -= v;
316 return key;
317}
318
319template <std::size_t Dim>
320[[nodiscard]] constexpr TreeKey<Dim> operator-(TreeKey<Dim> key,
321 Vec<Dim, std::uint32_t> const& v) noexcept
322{
323 key -= v;
324 return key;
325}
326
327template <std::size_t Dim>
328[[nodiscard]] constexpr TreeKey<Dim> operator-(std::uint32_t v, TreeKey<Dim> key) noexcept
329{
330 key -= v;
331 return key;
332}
333
334template <std::size_t Dim>
335[[nodiscard]] constexpr TreeKey<Dim> operator-(Vec<Dim, std::uint32_t> const& v,
336 TreeKey<Dim> key) noexcept
337{
338 key -= v;
339 return key;
340}
341} // namespace ufo
342
343namespace std
344{
345template <std::size_t Dim>
346struct hash<ufo::TreeKey<Dim>> {
347 std::size_t operator()(ufo::TreeKey<Dim> const& key) const
348 {
349 using Key = typename ufo::TreeKey<Dim>::Key;
350 return static_cast<std::size_t>(
351 ufo::Morton<Dim>::encode(static_cast<Key const&>(key)));
352 }
353};
354} // namespace std
355
356#endif // UFO_CONTAINER_TREE_KEY_HPP
constexpr void setDepth(depth_type depth) noexcept
Change the depth of the key.
Definition key.hpp:130
STL namespace.
All vision-related classes and functions.
Definition cloud.hpp:49
A fixed-size arithmetic vector of up to 4 dimensions.
Definition vec.hpp:76