UFO 1.0.0
An Efficient Probabilistic 3D Mapping Framework That Embraces the Unknown
Loading...
Searching...
No Matches
map.hpp
1
42#ifndef UFO_MAP_LABELS_MAP_HPP
43#define UFO_MAP_LABELS_MAP_HPP
44
45// UFO
46#include <functional>
47#include <numeric>
48#include <ufo/container/tree/container.hpp>
49#include <ufo/container/tree/tree.hpp>
50#include <ufo/map/block.hpp>
51#include <ufo/map/labels/block.hpp>
52#include <ufo/map/labels/predicate.hpp>
53#include <ufo/map/labels/propagation_criteria.hpp>
54#include <ufo/map/type.hpp>
55#include <ufo/numeric/transform3.hpp>
56#include <ufo/utility/bit_set.hpp>
57#include <ufo/utility/io/buffer.hpp>
58#include <ufo/utility/macros.hpp>
59#include <ufo/utility/type_traits.hpp>
60
61// STL
62#include <array>
63#include <iostream>
64#include <limits>
65#include <string_view>
66#include <type_traits>
67
68#include "ufo/core/label.hpp"
69
70namespace ufo
71{
72template <class Derived, class Tree>
74{
75 private:
76 template <class Derived2, class Tree2>
77 friend class LabelsMap;
78
79 static constexpr auto const BF = Tree::branchingFactor();
80 static constexpr auto const Dim = Tree::dimensions();
81
82 public:
83 /**************************************************************************************
84 | |
85 | Tags |
86 | |
87 **************************************************************************************/
88
89 static constexpr MapType const Type = MapType::LABEL_SET;
90
91 // Container
92 using Index = typename Tree::Index;
93 using Node = typename Tree::Node;
94 using Code = typename Tree::Code;
95 using Key = typename Tree::Key;
96 using Point = typename Tree::Point;
97 using Coord = typename Tree::Coord;
98 using coord_t = typename Tree::coord_t;
99 using depth_t = typename Tree::depth_t;
100 using offset_t = typename Tree::offset_t;
101 using length_t = typename Tree::length_t;
102 using pos_t = typename Tree::pos_t;
103
104 // Labels
105 using labels_t = typename LabelsBlock<BF>::labels_t;
106
107 public:
108 /**************************************************************************************
109 | |
110 | Access |
111 | |
112 **************************************************************************************/
113
114 template <class NodeType,
115 std::enable_if_t<Tree::template is_node_type_v<NodeType>, bool> = true>
116 [[nodiscard]] labels_t labels(NodeType node) const
117 {
118 Index n = derived().index(node);
119 return labelsBlock(n.pos)[n.offset].labels;
120 }
121
122 /**************************************************************************************
123 | |
124 | Modifiers |
125 | |
126 **************************************************************************************/
127
139 template <class NodeType,
140 std::enable_if_t<Tree::template is_node_type_v<NodeType>, bool> = true>
141 void labelsSet(NodeType node, labels_t value, bool propagate = true)
142 {
143 LabelsElement elem(value);
144
145 auto node_f = [this, elem](Index node) { labelsBlock(node.pos)[node.offset] = elem; };
146
147 auto block_f = [this, elem](pos_t pos) { labelsBlock(pos).fill(elem); };
148
149 auto update_f = [this](Index node, pos_t children) {
150 onPropagateChildren(node, children);
151 };
152
153 derived().recursParentFirst(node, node_f, block_f, update_f, propagate);
154 }
155
156 template <class NodeType,
157 std::enable_if_t<Tree::template is_node_type_v<NodeType>, bool> = true>
158 void labelsUpdate(NodeType node, label_t value, bool propagate = true)
159 {
160 labelsUpdate(
161 node,
162 [this, value](Index node) {
163 labelsBlock(node.pos)[node.offset].labels.insert(value);
164 return labelsBlock(node.pos)[node.offset].labels;
165 },
166 propagate);
167 }
168
169 template <
170 class NodeType, class UnaryOp,
171 std::enable_if_t<Tree::template is_node_type_v<NodeType>, bool> = true,
172 std::enable_if_t<std::is_invocable_r_v<labels_t, UnaryOp, Index>, bool> = true>
173 void labelsUpdate(NodeType node, UnaryOp unary_op, bool propagate = true)
174 {
175 auto node_f = [this, unary_op](Index node) {
176 labels_t value = unary_op(node);
177
178 auto& lb = labelsBlock(node.pos)[node.offset];
179 lb.labels = value;
180 };
181
182 auto block_f = [this, node_f](pos_t pos) {
183 for (std::size_t i{}; BF > i; ++i) {
184 node_f(Index(pos, i));
185 }
186 };
187
188 auto update_f = [this](Index node, pos_t children) {
189 onPropagateChildren(node, children);
190 };
191
192 derived().recursLeaves(node, node_f, block_f, update_f, propagate);
193 }
194
195 //
196 // Propagation criteria
197 //
198
199 [[nodiscard]] constexpr LabelsPropagationCriteria labelsPropagationCriteria()
200 const noexcept
201 {
202 return prop_criteria_;
203 }
204
205 void labelsSetPropagationCriteria(LabelsPropagationCriteria prop_criteria,
206 bool propagate = true)
207 {
208 if (LabelsPropagationCriteria() == prop_criteria) {
209 return;
210 }
211
212 prop_criteria_ = prop_criteria;
213
214 // Set all inner nodes to modified
215 // FIXME: Possible to optimize this to only set the ones with children
216 // TODO: Enable below
217 // derived().setModified();
218
219 // if (propagate) {
220 // derived().propagateModified();
221 // }
222 }
223
224 protected:
225 /**************************************************************************************
226 | |
227 | Constructors |
228 | |
229 **************************************************************************************/
230
231 LabelsMap() { onInitRoot(); }
232
233 LabelsMap(LabelsMap const& other) = default;
234
235 LabelsMap(LabelsMap&& other) = default;
236
237 template <class Derived2, class Tree2>
238 LabelsMap(LabelsMap<Derived2, Tree2> const& other)
239 : prop_criteria_(other.prop_criteria_)
240 {
241 }
242
243 template <class Derived2, class Tree2>
244 LabelsMap(LabelsMap<Derived2, Tree2>&& other)
245 : prop_criteria_(std::move(other.prop_criteria_))
246 {
247 }
248
249 /**************************************************************************************
250 | |
251 | Destructor |
252 | |
253 **************************************************************************************/
254
255 ~LabelsMap() = default;
256
257 /**************************************************************************************
258 | |
259 | Assignment operator |
260 | |
261 **************************************************************************************/
262
263 LabelsMap& operator=(LabelsMap const& rhs) = default;
264
265 LabelsMap& operator=(LabelsMap&& rhs) = default;
266
267 template <class Derived2, class Tree2>
268 LabelsMap& operator=(LabelsMap<Derived2, Tree2> const& rhs)
269 {
270 prop_criteria_ = rhs.prop_criteria_;
271 return *this;
272 }
273
274 template <class Derived2, class Tree2>
275 LabelsMap& operator=(LabelsMap<Derived2, Tree2>&& rhs)
276 {
277 prop_criteria_ = std::move(rhs.prop_criteria_);
278 return *this;
279 }
280
281 //
282 // Swap
283 //
284
285 void swap(LabelsMap& other) noexcept
286 {
287 std::swap(prop_criteria_, other.prop_criteria_);
288 }
289
290 /**************************************************************************************
291 | |
292 | Derived |
293 | |
294 **************************************************************************************/
295
296 [[nodiscard]] constexpr Derived& derived() { return *static_cast<Derived*>(this); }
297
298 [[nodiscard]] constexpr Derived const& derived() const
299 {
300 return *static_cast<Derived const*>(this);
301 }
302
303 /**************************************************************************************
304 | |
305 | Block |
306 | |
307 **************************************************************************************/
308
309 [[nodiscard]] LabelsBlock<BF>& labelsBlock(pos_t pos)
310 {
311 return derived().template data<LabelsBlock<BF>>(pos);
312 }
313
314 [[nodiscard]] LabelsBlock<BF> const& labelsBlock(pos_t pos) const
315 {
316 return derived().template data<LabelsBlock<BF>>(pos);
317 }
318
319 /**************************************************************************************
320 | |
321 | Functions Derived expect |
322 | |
323 **************************************************************************************/
324
325 void onInitRoot()
326 {
327 auto& block = labelsBlock(0);
328
329 labels_t value{};
330 block[0].labels = value;
331 }
332
333 void onInitChildren(Index node, pos_t children)
334 {
335 labelsBlock(children).fill(labelsBlock(node.pos)[node.offset]);
336 }
337
338 void onPruneChildren(Index node, pos_t children)
339 {
340 // TODO: implement
341 // auto& v = labelsBlock(node.pos)[node.offset];
342 }
343
344 void onPropagateChildren(Index node, pos_t children)
345 {
346 auto const& children_block = labelsBlock(children);
347 auto& lb = labelsBlock(node.pos)[node.offset];
348
349 switch (prop_criteria_) {
350 case LabelsPropagationCriteria::ALL: {
351 for (std::size_t i{}; BF > i; ++i) {
352 lb.labels.insert(children_block[i].labels.begin(),
353 children_block[i].labels.end());
354 }
355 break;
356 }
357 case LabelsPropagationCriteria::SUMMARY: {
358 label_t value{};
359 for (std::size_t i{}; BF > i; ++i) {
360 value |=
361 std::accumulate(children_block[i].labels.begin(),
362 children_block[i].labels.end(), 0, std::bit_or<label_t>());
363 }
364 lb.labels = {value};
365 break;
366 }
367 case LabelsPropagationCriteria::MAX: {
368 label_t value = std::numeric_limits<label_t>::lowest();
369 for (std::size_t i{}; BF > i; ++i) {
370 value = UFO_MAX(value, children_block[i].labels.empty()
371 ? std::numeric_limits<label_t>::lowest()
372 : *children_block[i].labels.rbegin());
373 }
374 lb.labels = {value};
375 break;
376 }
377 case LabelsPropagationCriteria::MIN: {
378 label_t value = std::numeric_limits<label_t>::max();
379 for (std::size_t i{}; BF > i; ++i) {
380 value = UFO_MIN(value, children_block[i].labels.empty()
381 ? std::numeric_limits<label_t>::max()
382 : *children_block[i].labels.rbegin());
383 }
384 lb.labels = {value};
385 break;
386 }
387 case LabelsPropagationCriteria::NONE: return;
388 }
389 }
390
391 //
392 // Is prunable
393 //
394
395 [[nodiscard]] bool onIsPrunable(pos_t block) const
396 {
397 using std::begin;
398 using std::end;
399 return std::all_of(
400 begin(labelsBlock(block).data) + 1, end(labelsBlock(block).data),
401 [v = labelsBlock(block)[0].labels](auto const& e) { return v == e.labels; });
402 }
403
404 //
405 // Input/output (read/write)
406 //
407
408 [[nodiscard]] static constexpr std::size_t serializedSizeNode() noexcept
409 {
410 return sizeof(labels_t);
411 }
412
413 [[nodiscard]] constexpr std::size_t serializedSize(
414 std::vector<std::pair<pos_t, BitSet<BF>>> const& /* nodes */,
415 std::size_t num_nodes) const
416 {
417 return num_nodes * serializedSizeNode();
418 }
419
420 void onRead(ReadBuffer& in, std::vector<std::pair<pos_t, BitSet<BF>>> const& nodes)
421 {
422 for (auto [block, offset] : nodes) {
423 auto& cb = labelsBlock(block);
424
425 if (offset.all()) {
426 std::array<labels_t, BF> labels;
427 in.read(labels);
428 for (offset_t i{}; BF > i; ++i) {
429 cb[i] = LabelsElement(labels[i]);
430 }
431 } else {
432 for (offset_t i{}; BF > i; ++i) {
433 if (offset[i]) {
434 labels_t value;
435 in.read(value);
436 cb[i] = LabelsElement(value);
437 }
438 }
439 }
440 }
441 }
442
443 void onWrite(WriteBuffer& out, std::vector<std::pair<pos_t, BitSet<BF>>> const& nodes)
444 {
445 for (auto [block, offset] : nodes) {
446 auto const& lb = labelsBlock(block);
447
448 if (offset.all()) {
449 std::array<labels_t, BF> labels;
450 for (offset_t i{}; BF > i; ++i) {
451 labels[i] = lb[i].labels;
452 }
453 out.write(labels);
454 } else {
455 for (offset_t i{}; BF > i; ++i) {
456 if (offset[i]) {
457 out.write(lb[i].labels);
458 }
459 }
460 }
461 }
462 }
463
464 //
465 // Dot file info
466 //
467
468 void onDotFileInfo(std::ostream& out, Index node) const
469 {
470 out << "Labels: ";
471
472 if (labelsBlock(node.pos)[node.offset].labels.empty()) return;
473
474 auto it = labelsBlock(node.pos)[node.offset].labels.begin();
475 out << *it++;
476
477 while (it != labelsBlock(node.pos)[node.offset].labels.end()) {
478 out << ',' << *it++;
479 }
480 }
481
482 private:
483 // Propagation criteria
484 LabelsPropagationCriteria prop_criteria_ = LabelsPropagationCriteria::ALL;
485};
486
487template <std::size_t Dim, std::size_t BF>
488struct map_block<LabelsMap, Dim, BF> {
489 using type = LabelsBlock<BF>;
490};
491} // namespace ufo
492
493#endif // UFO_MAP_LABELS_MAP_HPP
void labelsSet(NodeType node, labels_t value, bool propagate=true)
Definition map.hpp:141
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
static constexpr std::size_t dimensions() noexcept
Returns the number of dimensions of the tree (i.e., 1 = binary tree, 2 = quadtree,...
Definition tree.hpp:211
STL namespace.
All vision-related classes and functions.
Definition cloud.hpp:49