UFO 1.0.0
An Efficient Probabilistic 3D Mapping Framework That Embraces the Unknown
Loading...
Searching...
No Matches
surfel_map.hpp
1
42#ifndef UFO_MAP_SURFEL_MAP_HPP
43#define UFO_MAP_SURFEL_MAP_HPP
44
45// UFO
46#include <ufo/map/surfel/surfel.hpp>
47#include <ufo/util/buffer.hpp>
48#include <ufo/util/enum.hpp>
49
50// STL
51#include <cstdint>
52#include <deque>
53#include <functional>
54#include <stack>
55#include <type_traits>
56#include <utility>
57
58namespace ufo
59{
60template <bool Cached, class Derived, offset_t N, class Index, class Node, class Code,
61 class Key, class Point>
63{
64 private:
65 using SurfelT = std::conditional_t<Cached, SurfelCached, Surfel>;
66
67 public:
68 //
69 // Surfel block
70 //
71
72 // [[nodiscard]] DataBlock<count_t, N>& countBlock(pos_t block) { return surfel_[block];
73 // }
74
75 // [[nodiscard]] DataBlock<count_t, N> const& countBlock(pos_t block) const
76 // {
77 // return surfel_[block];
78 // }
79
80 //
81 // Get surfel
82 //
83
84 [[nodiscard]] Surfel surfel(Index node) const
85 {
86 auto pos = indices_[node.pos][node.offset];
87 return NULL_POS != pos ? surfel_[pos] : Surfel{};
88 }
89
90 [[nodiscard]] Surfel surfel(Node node) const { return surfel(derived().index(node)); }
91
92 [[nodiscard]] Surfel surfel(Code code) const { return surfel(derived().index(code)); }
93
94 [[nodiscard]] Surfel surfel(Key key) const { return surfel(derived().index(key)); }
95
96 [[nodiscard]] Surfel surfel(Point coord, depth_t depth = 0) const
97 {
98 return surfel(derived().index(coord, depth));
99 }
100
101 //
102 // Surfel empty
103 //
104
105 [[nodiscard]] bool surfelEmpty(Index node) const
106 {
107 auto pos = indices_[node.pos][node.offset];
108 return NULL_POS == pos || surfel_[pos].empty();
109 }
110
111 [[nodiscard]] bool surfelEmpty(Node node) const
112 {
113 return surfelEmpty(derived().index(node));
114 }
115
116 [[nodiscard]] bool surfelEmpty(Code code) const
117 {
118 return surfelEmpty(derived().index(code));
119 }
120
121 [[nodiscard]] bool surfelEmpty(Key key) const
122 {
123 return surfelEmpty(derived().index(key));
124 }
125
126 [[nodiscard]] bool surfelEmpty(Point coord, depth_t depth = 0) const
127 {
128 return surfelEmpty(derived().index(coord, depth));
129 }
130
131 //
132 // Surfel mean
133 //
134
135 [[nodiscard]] decltype(std::declval<Surfel>().mean()) surfelMean(Index node) const
136 {
137 return surfel_[indices_[node.pos][node.offset]].mean();
138 }
139
140 [[nodiscard]] decltype(std::declval<Surfel>().mean()) surfelMean(Node node) const
141 {
142 return surfelMean(derived().index(node));
143 }
144
145 [[nodiscard]] decltype(std::declval<Surfel>().mean()) surfelMean(Code code) const
146 {
147 return surfelMean(derived().index(code));
148 }
149
150 [[nodiscard]] decltype(std::declval<Surfel>().mean()) surfelMean(Key key) const
151 {
152 return surfelMean(derived().index(key));
153 }
154
155 [[nodiscard]] decltype(std::declval<Surfel>().mean()) surfelMean(
156 Point coord, depth_t depth = 0) const
157 {
158 return surfelMean(derived().index(coord, depth));
159 }
160
161 //
162 // Surfel normal
163 //
164
165 [[nodiscard]] decltype(std::declval<Surfel>().normal()) surfelNormal(Index node) const
166 {
167 return surfel_[indices_[node.pos][node.offset]].normal();
168 }
169
170 [[nodiscard]] decltype(std::declval<Surfel>().normal()) surfelNormal(Node node) const
171 {
172 return surfelNormal(derived().index(node));
173 }
174
175 [[nodiscard]] decltype(std::declval<Surfel>().normal()) surfelNormal(Code code) const
176 {
177 return surfelNormal(derived().index(code));
178 }
179
180 [[nodiscard]] decltype(std::declval<Surfel>().normal()) surfelNormal(Key key) const
181 {
182 return surfelNormal(derived().index(key));
183 }
184
185 [[nodiscard]] decltype(std::declval<Surfel>().normal()) surfelNormal(
186 Point coord, depth_t depth = 0) const
187 {
188 return surfelNormal(derived().index(coord, depth));
189 }
190
191 //
192 // Surfel planarity
193 //
194
195 [[nodiscard]] decltype(std::declval<Surfel>().planarity()) surfelPlanarity(
196 Index node) const
197 {
198 return surfel_[indices_[node.pos][node.offset]].planarity();
199 }
200
201 [[nodiscard]] decltype(std::declval<Surfel>().planarity()) surfelPlanarity(
202 Node node) const
203 {
204 return surfelPlanarity(derived().index(node));
205 }
206
207 [[nodiscard]] decltype(std::declval<Surfel>().planarity()) surfelPlanarity(
208 Code code) const
209 {
210 return surfelPlanarity(derived().index(code));
211 }
212
213 [[nodiscard]] decltype(std::declval<Surfel>().planarity()) surfelPlanarity(
214 Key key) const
215 {
216 return surfelPlanarity(derived().index(key));
217 }
218
219 [[nodiscard]] decltype(std::declval<Surfel>().planarity()) surfelPlanarity(
220 Point coord, depth_t depth = 0) const
221 {
222 return surfelPlanarity(derived().index(coord, depth));
223 }
224
225 //
226 // Surfel covariance
227 //
228
229 [[nodiscard]] decltype(std::declval<Surfel>().covariance()) surfelCovariance(
230 Index node) const
231 {
232 return surfel_[indices_[node.pos][node.offset]].covariance();
233 }
234
235 [[nodiscard]] decltype(std::declval<Surfel>().covariance()) surfelCovariance(
236 Node node) const
237 {
238 return surfelCovariance(derived().index(node));
239 }
240
241 [[nodiscard]] decltype(std::declval<Surfel>().covariance()) surfelCovariance(
242 Code code) const
243 {
244 return surfelCovariance(derived().index(code));
245 }
246
247 [[nodiscard]] decltype(std::declval<Surfel>().covariance()) surfelCovariance(
248 Key key) const
249 {
250 return surfelCovariance(derived().index(key));
251 }
252
253 [[nodiscard]] decltype(std::declval<Surfel>().covariance()) surfelCovariance(
254 Point coord, depth_t depth = 0) const
255 {
256 return surfelCovariance(derived().index(coord, depth));
257 }
258
259 //
260 // Surfel eigenvalues
261 //
262
263 [[nodiscard]] decltype(std::declval<Surfel>().eigenValues()) surfelEigenValues(
264 Index node) const
265 {
266 return surfel_[indices_[node.pos][node.offset]].eigenValues();
267 }
268
269 [[nodiscard]] decltype(std::declval<Surfel>().eigenValues()) surfelEigenValues(
270 Node node) const
271 {
272 return surfelEigenValues(derived().index(node));
273 }
274
275 [[nodiscard]] decltype(std::declval<Surfel>().eigenValues()) surfelEigenValues(
276 Code code) const
277 {
278 return surfelEigenValues(derived().index(code));
279 }
280
281 [[nodiscard]] decltype(std::declval<Surfel>().eigenValues()) surfelEigenValues(
282 Key key) const
283 {
284 return surfelEigenValues(derived().index(key));
285 }
286
287 [[nodiscard]] decltype(std::declval<Surfel>().eigenValues()) surfelEigenValues(
288 Point coord, depth_t depth = 0) const
289 {
290 return surfelEigenValues(derived().index(coord, depth));
291 }
292
293 //
294 // Surfel eigen vectors
295 //
296
297 [[nodiscard]] decltype(std::declval<Surfel>().eigenVectors()) surfelEigenVectors(
298 Index node) const
299 {
300 return surfel_[indices_[node.pos][node.offset]].eigenVectors();
301 }
302
303 [[nodiscard]] decltype(std::declval<Surfel>().eigenVectors()) surfelEigenVectors(
304 Node node) const
305 {
306 return surfelEigenVectors(derived().index(node));
307 }
308
309 [[nodiscard]] decltype(std::declval<Surfel>().eigenVectors()) surfelEigenVectors(
310 Code code) const
311 {
312 return surfelEigenVectors(derived().index(code));
313 }
314
315 [[nodiscard]] decltype(std::declval<Surfel>().eigenVectors()) surfelEigenVectors(
316 Key key) const
317 {
318 return surfelEigenVectors(derived().index(key));
319 }
320
321 [[nodiscard]] decltype(std::declval<Surfel>().eigenVectors()) surfelEigenVectors(
322 Point coord, depth_t depth = 0) const
323 {
324 return surfelEigenVectors(derived().index(coord, depth));
325 }
326
327 //
328 // Surfel num points
329 //
330
331 [[nodiscard]] decltype(std::declval<Surfel>().numPoints()) surfelNumPoints(
332 Index node) const
333 {
334 return surfel_[indices_[node.pos][node.offset]].numPoints();
335 }
336
337 [[nodiscard]] decltype(std::declval<Surfel>().numPoints()) surfelNumPoints(
338 Node node) const
339 {
340 return surfelNumPoints(derived().index(node));
341 }
342
343 [[nodiscard]] decltype(std::declval<Surfel>().numPoints()) surfelNumPoints(
344 Code code) const
345 {
346 return surfelNumPoints(derived().index(code));
347 }
348
349 [[nodiscard]] decltype(std::declval<Surfel>().numPoints()) surfelNumPoints(
350 Key key) const
351 {
352 return surfelNumPoints(derived().index(key));
353 }
354
355 [[nodiscard]] decltype(std::declval<Surfel>().numPoints()) surfelNumPoints(
356 Point coord, depth_t depth = 0) const
357 {
358 return surfelNumPoints(derived().index(coord, depth));
359 }
360
361 //
362 // Surfel sum
363 //
364
365 [[nodiscard]] decltype(std::declval<Surfel>().sum()) surfelSum(Index node) const
366 {
367 return surfel_[indices_[node.pos][node.offset]].sum();
368 }
369
370 [[nodiscard]] decltype(std::declval<Surfel>().sum()) surfelSum(Node node) const
371 {
372 return surfelSum(derived().index(node));
373 }
374
375 [[nodiscard]] decltype(std::declval<Surfel>().sum()) surfelSum(Code code) const
376 {
377 return surfelSum(derived().index(code));
378 }
379
380 [[nodiscard]] decltype(std::declval<Surfel>().sum()) surfelSum(Key key) const
381 {
382 return surfelSum(derived().index(key));
383 }
384
385 [[nodiscard]] decltype(std::declval<Surfel>().sum()) surfelSum(Point coord,
386 depth_t depth = 0) const
387 {
388 return surfelSum(derived().index(coord, depth));
389 }
390
391 //
392 // Surfel sum squares
393 //
394
395 [[nodiscard]] decltype(std::declval<Surfel>().sumSquares()) surfelSumSquares(
396 Index node) const
397 {
398 return surfel_[indices_[node.pos][node.offset]].sumSquares();
399 }
400
401 [[nodiscard]] decltype(std::declval<Surfel>().sumSquares()) surfelSumSquares(
402 Node node) const
403 {
404 return surfelSumSquares(derived().index(node));
405 }
406
407 [[nodiscard]] decltype(std::declval<Surfel>().sumSquares()) surfelSumSquares(
408 Code code) const
409 {
410 return surfelSumSquares(derived().index(code));
411 }
412
413 [[nodiscard]] decltype(std::declval<Surfel>().sumSquares()) surfelSumSquares(
414 Key key) const
415 {
416 return surfelSumSquares(derived().index(key));
417 }
418
419 [[nodiscard]] decltype(std::declval<Surfel>().sumSquares()) surfelSumSquares(
420 Point coord, depth_t depth = 0) const
421 {
422 return surfelSumSquares(derived().index(coord, depth));
423 }
424
425 //
426 // Surfel set
427 //
428
429 void surfelSet(Index node, Surfel const& surfel)
430 {
431 derived().apply(
432 node, [this, &surfel](Index node) { createOrAssignSurfel(node, surfel); },
433 [this, &surfel](pos_t block) {
434 for (offset_t i{}; N != i; ++i) {
435 createOrAssignSurfel(Index{block, i}, surfel);
436 }
437 });
438 }
439
440 Node surfelSet(Node node, Surfel const& surfel, bool propagate = true)
441 {
442 return derived().apply(
443 node, [this, &surfel](Index node) { createOrAssignSurfel(node, surfel); },
444 [this, &surfel](pos_t block) {
445 for (offset_t i{}; N != i; ++i) {
446 createOrAssignSurfel(Index{block, i}, surfel);
447 }
448 },
449 propagate);
450 }
451
452 Node surfelSet(Code code, Surfel const& surfel, bool propagate = true)
453 {
454 return derived().apply(
455 code, [this, &surfel](Index node) { createOrAssignSurfel(node, surfel); },
456 [this, &surfel](pos_t block) {
457 for (offset_t i{}; N != i; ++i) {
458 createOrAssignSurfel(Index{block, i}, surfel);
459 }
460 },
461 propagate);
462 }
463
464 Node surfelSet(Key key, Surfel const& surfel, bool propagate = true)
465 {
466 return surfelSet(derived().toCode(key), surfel, propagate);
467 }
468
469 Node surfelSet(Point coord, Surfel const& surfel, bool propagate = true,
470 depth_t depth = 0)
471 {
472 return surfelSet(derived().toCode(coord, depth), surfel, propagate);
473 }
474
475 //
476 // Surfel add
477 //
478
479 void surfelAdd(Index node, Surfel const& surfel)
480 {
481 derived().apply(
482 node,
483 [this, &surfel](Index node) {
484 auto pos = createSurfel(node);
485 surfel_[pos] += surfel;
486 },
487 [this, &surfel](pos_t block) {
488 for (offset_t i{}; N != i; ++i) {
489 auto pos = createSurfel(Index(block, i));
490 surfel_[pos] += surfel;
491 }
492 });
493 }
494
495 Node surfelAdd(Node node, Surfel const& surfel, bool propagate = true)
496 {
497 return derived().apply(
498 node,
499 [this, &surfel](Index node) {
500 auto pos = createSurfel(node);
501 surfel_[pos] += surfel;
502 },
503 [this, &surfel](pos_t block) {
504 for (offset_t i{}; N != i; ++i) {
505 auto pos = createSurfel(Index(block, i));
506 surfel_[pos] += surfel;
507 }
508 },
509 propagate);
510 }
511
512 Node surfelAdd(Code code, Surfel const& surfel, bool propagate = true)
513 {
514 return derived().apply(
515 code,
516 [this, &surfel](Index node) {
517 auto pos = createSurfel(node);
518 surfel_[pos] += surfel;
519 },
520 [this, &surfel](pos_t block) {
521 for (offset_t i{}; N != i; ++i) {
522 auto pos = createSurfel(Index(block, i));
523 surfel_[pos] += surfel;
524 }
525 },
526 propagate);
527 }
528
529 Node surfelAdd(Key key, Surfel const& surfel, bool propagate = true)
530 {
531 return surfelAdd(derived().toCode(key), surfel, propagate);
532 }
533
534 Node surfelAdd(Point coord, Surfel const& surfel, bool propagate = true,
535 depth_t depth = 0)
536 {
537 return surfelAdd(derived().toCode(coord, depth), surfel, propagate);
538 }
539
540 void surfelAdd(Point point, bool propagate = true, depth_t depth = 0)
541 {
542 surfelAdd(point, point, propagate, depth);
543 }
544
545 template <class InputIt>
546 void surfelAdd(InputIt first, InputIt last, bool propagate = true, depth_t depth = 0)
547 {
548 struct CodeOrIndexPoint
549 : CodeOrIndex
550 , Point {
551 constexpr CodeOrIndexPoint() = default;
552 CodeOrIndexPoint(Code code, Point point) : CodeOrIndexPoint(code), Point(point) {}
553 };
554
555 std::vector<CodeOrIndexPoint> data;
556 data.reserve(std::distance(first, last));
557
558 for (; first != last; ++first) {
559 data.emplace_back(derived().toCode(*first, depth), *first);
560 }
561
562 std::sort(std::begin(data), std::end(data),
563 [](auto a, auto b) { return a.code > b.code; });
564
565 derived().createIndicesFromCodes(data);
566
567 for (auto it = std::cbegin(data), last = std::cend(data); it != last;) {
568 auto it_end = std::find_if(std::next(it), last,
569 [idx = it->index](auto v) { return idx != v.index; });
570
571 surfelAdd(it->index, it, it_end);
572 }
573
574 if (propagate) {
575 derived().propagateModified();
576 }
577 }
578
579 template <class PointRange>
580 void surfelAdd(PointRange const& points, bool propagate = true, depth_t depth = 0)
581 {
582 surfelAdd(std::cbegin(points), std::cend(points), propagate, depth);
583 }
584
585 void surfelAdd(std::initializer_list<Point> points, bool propagate = true,
586 depth_t depth = 0)
587 {
588 surfelAdd(std::cbegin(points), std::cend(points), propagate, depth);
589 }
590
591 void surfelAdd(Index node, Point point)
592 {
593 derived().apply(
594 node,
595 [this, point](Index node) {
596 auto pos = createSurfel(node);
597 surfel_[pos] += point;
598 },
599 [this, point](pos_t block) {
600 for (offset_t i{}; N != i; ++i) {
601 auto pos = createSurfel(Index{block, i});
602 surfel_[pos] += point;
603 }
604 });
605 }
606
607 template <class InputIt>
608 void surfelAdd(Index node, InputIt first, InputIt last)
609 {
610 derived().apply(
611 node,
612 [this, first, last](Index node) {
613 auto pos = createSurfel(node);
614 surfel_[pos].addPoint(first, last);
615 },
616 [this, first, last](pos_t block) {
617 for (offset_t i{}; N != i; ++i) {
618 auto pos = createSurfel(Index{block, i});
619 surfel_[pos].addPoint(first, last);
620 }
621 });
622 }
623
624 template <class PointRange>
625 void surfelAdd(Index node, PointRange const& points)
626 {
627 surfelAdd(node, std::cbegin(points), std::cend(points));
628 }
629
630 void surfelAdd(Index node, std::initializer_list<Point> points)
631 {
632 surfelAdd(node, std::cbegin(points), std::cend(points));
633 }
634
635 Node surfelAdd(Node node, Point point, bool propagate = true)
636 {
637 return derived().apply(
638 node,
639 [this, point](Index node) {
640 auto pos = createSurfel(node);
641 surfel_[pos] += point;
642 },
643 [this, point](pos_t block) {
644 for (offset_t i{}; N != i; ++i) {
645 auto pos = createSurfel(Index{block, i});
646 surfel_[pos] += point;
647 }
648 },
649 propagate);
650 }
651
652 template <class InputIt>
653 Node surfelAdd(Node node, InputIt first, InputIt last, bool propagate = true)
654 {
655 return derived().apply(
656 node,
657 [this, first, last](Index node) {
658 auto pos = createSurfel(node);
659 surfel_[pos].addPoint(first, last);
660 },
661 [this, first, last](pos_t block) {
662 for (offset_t i{}; N != i; ++i) {
663 auto pos = createSurfel(Index{block, i});
664 surfel_[pos].addPoint(first, last);
665 }
666 },
667 propagate);
668 }
669
670 template <class PointRange>
671 Node surfelAdd(Node node, PointRange const& points, bool propagate = true)
672 {
673 return surfelAdd(node, std::cbegin(points), std::cend(points), propagate);
674 }
675
676 Node surfelAdd(Node node, std::initializer_list<Point> points, bool propagate = true)
677 {
678 return surfelAdd(node, std::cbegin(points), std::cend(points), propagate);
679 }
680
681 Node surfelAdd(Code code, Point point, bool propagate = true)
682 {
683 return derived().apply(
684 code,
685 [this, point](Index node) {
686 auto pos = createSurfel(node);
687 surfel_[pos] += point;
688 },
689 [this, point](pos_t block) {
690 for (offset_t i{}; N != i; ++i) {
691 auto pos = createSurfel(Index{block, i});
692 surfel_[pos] += point;
693 }
694 },
695 propagate);
696 }
697
698 template <class InputIt>
699 Node surfelAdd(Code code, InputIt first, InputIt last, bool propagate = true)
700 {
701 return derived().apply(
702 code,
703 [this, first, last](Index node) {
704 auto pos = createSurfel(node);
705 surfel_[pos].addPoint(first, last);
706 },
707 [this, first, last](pos_t block) {
708 for (offset_t i{}; N != i; ++i) {
709 auto pos = createSurfel(Index{block, i});
710 surfel_[pos].addPoint(first, last);
711 }
712 },
713 propagate);
714 }
715
716 template <class PointRange>
717 Node surfelAdd(Code code, PointRange const& points, bool propagate = true)
718 {
719 return surfelAdd(code, std::cbegin(points), std::cend(points), propagate);
720 }
721
722 Node surfelAdd(Code code, std::initializer_list<Point> points, bool propagate = true)
723 {
724 return surfelAdd(code, std::cbegin(points), std::cend(points), propagate);
725 }
726
727 Node surfelAdd(Key key, Point point, bool propagate = true)
728 {
729 return surfelAdd(derived().toCode(key), point, propagate);
730 }
731
732 template <class InputIt>
733 Node surfelAdd(Key key, InputIt first, InputIt last, bool propagate = true)
734 {
735 return surfelAdd(derived().toCode(key), first, last, propagate);
736 }
737
738 template <class PointRange>
739 Node surfelAdd(Key key, PointRange const& points, bool propagate = true)
740 {
741 return surfelAdd(key, std::cbegin(points), std::cend(points), propagate);
742 }
743
744 Node surfelAdd(Key key, std::initializer_list<Point> points, bool propagate = true)
745 {
746 return surfelAdd(key, std::cbegin(points), std::cend(points), propagate);
747 }
748
749 Node surfelAdd(Point coord, Point point, bool propagate = true, depth_t depth = 0)
750 {
751 return surfelAdd(derived().toCode(coord, depth), point, propagate);
752 }
753
754 template <class InputIt>
755 Node surfelAdd(Point coord, InputIt first, InputIt last, bool propagate = true,
756 depth_t depth = 0)
757 {
758 return surfelAdd(derived().toCode(coord, depth), first, last, propagate);
759 }
760
761 template <class PointRange>
762 Node surfelAdd(Point coord, PointRange const& points, bool propagate = true,
763 depth_t depth = 0)
764 {
765 return surfelAdd(coord, std::cbegin(points), std::cend(points), propagate, depth);
766 }
767
768 Node surfelAdd(Point coord, std::initializer_list<Point> points, bool propagate = true,
769 depth_t depth = 0)
770 {
771 return surfelAdd(coord, std::cbegin(points), std::cend(points), propagate, depth);
772 }
773
774 //
775 // Surfel remove
776 //
777
778 void surfelRemove(Index node, Surfel const& surfel)
779 {
780 derived().apply(
781 node,
782 [this, &surfel](Index node) {
783 auto pos = indices_[node.pos][node.offset];
784 if (NULL_POS != pos) {
785 surfel_[pos] -= surfel;
786 if (surfel_[pos].empty()) {
787 deleteSurfel(node);
788 }
789 }
790 },
791 [this, &surfel](pos_t block) {
792 for (offset_t i{}; N != i; ++i) {
793 auto pos = indices_[block][i];
794 if (NULL_POS != pos) {
795 surfel_[pos] -= surfel;
796 if (surfel_[pos].empty()) {
797 deleteSurfel(Index{block, i});
798 }
799 }
800 }
801 });
802 }
803
804 Node surfelRemove(Node node, Surfel const& surfel, bool propagate = true)
805 {
806 return derived().apply(
807 node,
808 [this, &surfel](Index node) {
809 auto pos = indices_[node.pos][node.offset];
810 if (NULL_POS != pos) {
811 surfel_[pos] -= surfel;
812 if (surfel_[pos].empty()) {
813 deleteSurfel(node);
814 }
815 }
816 },
817 [this, &surfel](pos_t block) {
818 for (offset_t i{}; N != i; ++i) {
819 auto pos = indices_[block][i];
820 if (NULL_POS != pos) {
821 surfel_[pos] -= surfel;
822 if (surfel_[pos].empty()) {
823 deleteSurfel(Index{block, i});
824 }
825 }
826 }
827 },
828 propagate);
829 }
830
831 Node surfelRemove(Code code, Surfel const& surfel, bool propagate = true)
832 {
833 return derived().apply(
834 code,
835 [this, &surfel](Index node) {
836 auto pos = indices_[node.pos][node.offset];
837 if (NULL_POS != pos) {
838 surfel_[pos] -= surfel;
839 if (surfel_[pos].empty()) {
840 deleteSurfel(node);
841 }
842 }
843 },
844 [this, &surfel](pos_t block) {
845 for (offset_t i{}; N != i; ++i) {
846 auto pos = indices_[block][i];
847 if (NULL_POS != pos) {
848 surfel_[pos] -= surfel;
849 if (surfel_[pos].empty()) {
850 deleteSurfel(Index{block, i});
851 }
852 }
853 }
854 },
855 propagate);
856 }
857
858 Node surfelRemove(Key key, Surfel const& surfel, bool propagate = true)
859 {
860 return surfelRemove(derived().toCode(key), surfel, propagate);
861 }
862
863 Node surfelRemove(Point coord, Surfel const& surfel, bool propagate = true,
864 depth_t depth = 0)
865 {
866 return surfelRemove(derived().toCode(coord, depth), surfel, propagate);
867 }
868
869 void surfelRemove(Point point, bool propagate = true, depth_t depth = 0)
870 {
871 surfelRemove(point, point, propagate, depth);
872 }
873
874 template <class InputIt>
875 void surfelRemove(InputIt first, InputIt last, bool propagate = true, depth_t depth = 0)
876 {
877 struct CodeOrIndexPoint
878 : CodeOrIndex
879 , Point {
880 constexpr CodeOrIndexPoint() = default;
881 CodeOrIndexPoint(Code code, Point point) : CodeOrIndexPoint(code), Point(point) {}
882 };
883
884 std::vector<CodeOrIndexPoint> data;
885 data.reserve(std::distance(first, last));
886
887 for (; first != last; ++first) {
888 data.emplace_back(derived().toCode(*first, depth), *first);
889 }
890
891 std::sort(std::begin(data), std::end(data),
892 [](auto a, auto b) { return a.code > b.code; });
893
894 derived().createIndicesFromCodes(data);
895
896 for (auto it = std::cbegin(data), last = std::cend(data); it != last;) {
897 auto it_end = std::find_if(std::next(it), last,
898 [idx = it->index](auto v) { return idx != v.index; });
899
900 surfelRemove(it->index, it, it_end);
901 }
902
903 if (propagate) {
904 derived().propagateModified();
905 }
906 }
907
908 template <class PointRange>
909 void surfelRemove(PointRange const& points, bool propagate = true, depth_t depth = 0)
910 {
911 surfelRemove(std::cbegin(points), std::cend(points), propagate, depth);
912 }
913
914 void surfelRemove(std::initializer_list<Point> points, bool propagate = true,
915 depth_t depth = 0)
916 {
917 surfelRemove(std::cbegin(points), std::cend(points), propagate, depth);
918 }
919
920 void surfelRemove(Index node, Point point)
921 {
922 derived().apply(
923 node,
924 [this, point](Index node) {
925 auto pos = indices_[node.pos][node.offset];
926 if (NULL_POS != pos) {
927 surfel_[pos] -= point;
928 if (surfel_[pos].empty()) {
929 deleteSurfel(node);
930 }
931 }
932 },
933 [this, point](pos_t block) {
934 for (offset_t i{}; N != i; ++i) {
935 auto pos = indices_[block][i];
936 if (NULL_POS != pos) {
937 surfel_[pos] -= point;
938 if (surfel_[pos].empty()) {
939 deleteSurfel(Index{block, i});
940 }
941 }
942 }
943 });
944 }
945
946 template <class InputIt>
947 void surfelRemove(Index node, InputIt first, InputIt last)
948 {
949 derived().apply(
950 node,
951 [this, first, last](Index node) {
952 auto pos = indices_[node.pos][node.offset];
953 if (NULL_POS != pos) {
954 surfel_[pos].removePoint(first, last);
955 if (surfel_[pos].empty()) {
956 deleteSurfel(node);
957 }
958 }
959 },
960 [this, first, last](pos_t block) {
961 for (offset_t i{}; N != i; ++i) {
962 auto pos = indices_[block][i];
963 if (NULL_POS != pos) {
964 surfel_[pos].removePoint(first, last);
965 if (surfel_[pos].empty()) {
966 deleteSurfel(Index{block, i});
967 }
968 }
969 }
970 });
971 }
972
973 template <class PointRange>
974 void surfelRemove(Index node, PointRange const& points)
975 {
976 surfelRemove(node, std::cbegin(points), std::cend(points));
977 }
978
979 void surfelRemove(Index node, std::initializer_list<Point> points)
980 {
981 surfelRemove(node, std::cbegin(points), std::cend(points));
982 }
983
984 Node surfelRemove(Node node, Point point, bool propagate = true)
985 {
986 return derived().apply(
987 node,
988 [this, point](Index node) {
989 auto pos = indices_[node.pos][node.offset];
990 if (NULL_POS != pos) {
991 surfel_[pos] -= point;
992 if (surfel_[pos].empty()) {
993 deleteSurfel(node);
994 }
995 }
996 },
997 [this, point](pos_t block) {
998 for (offset_t i{}; N != i; ++i) {
999 auto pos = indices_[block][i];
1000 if (NULL_POS != pos) {
1001 surfel_[pos] -= point;
1002 if (surfel_[pos].empty()) {
1003 deleteSurfel(Index{block, i});
1004 }
1005 }
1006 }
1007 },
1008 propagate);
1009 }
1010
1011 template <class InputIt>
1012 Node surfelRemove(Node node, InputIt first, InputIt last, bool propagate = true)
1013 {
1014 return derived().apply(
1015 node,
1016 [this, first, last](Index node) {
1017 auto pos = indices_[node.pos][node.offset];
1018 if (NULL_POS != pos) {
1019 surfel_[pos].removePoint(first, last);
1020 if (surfel_[pos].empty()) {
1021 deleteSurfel(node);
1022 }
1023 }
1024 },
1025 [this, first, last](pos_t block) {
1026 for (offset_t i{}; N != i; ++i) {
1027 auto pos = indices_[block][i];
1028 if (NULL_POS != pos) {
1029 surfel_[pos].removePoint(first, last);
1030 if (surfel_[pos].empty()) {
1031 deleteSurfel(Index{block, i});
1032 }
1033 }
1034 }
1035 },
1036 propagate);
1037 }
1038
1039 template <class PointRange>
1040 Node surfelRemove(Node node, PointRange const& points, bool propagate = true)
1041 {
1042 return surfelRemove(node, std::cbegin(points), std::cend(points), propagate);
1043 }
1044
1045 Node surfelRemove(Node node, std::initializer_list<Point> points, bool propagate = true)
1046 {
1047 return surfelRemove(node, std::cbegin(points), std::cend(points), propagate);
1048 }
1049
1050 Node surfelRemove(Code code, Point point, bool propagate = true)
1051 {
1052 return derived().apply(
1053 code,
1054 [this, point](Index node) {
1055 auto pos = indices_[node.pos][node.offset];
1056 if (NULL_POS != pos) {
1057 surfel_[pos] -= point;
1058 if (surfel_[pos].empty()) {
1059 deleteSurfel(node);
1060 }
1061 }
1062 },
1063 [this, point](pos_t block) {
1064 for (offset_t i{}; N != i; ++i) {
1065 auto pos = indices_[block][i];
1066 if (NULL_POS != pos) {
1067 surfel_[pos] -= point;
1068 if (surfel_[pos].empty()) {
1069 deleteSurfel(Index{block, i});
1070 }
1071 }
1072 }
1073 },
1074 propagate);
1075 }
1076
1077 template <class InputIt>
1078 Node surfelRemove(Code code, InputIt first, InputIt last, bool propagate = true)
1079 {
1080 return derived().apply(
1081 code,
1082 [this, first, last](Index node) {
1083 auto pos = indices_[node.pos][node.offset];
1084 if (NULL_POS != pos) {
1085 surfel_[pos].removePoint(first, last);
1086 if (surfel_[pos].empty()) {
1087 deleteSurfel(node);
1088 }
1089 }
1090 },
1091 [this, first, last](pos_t block) {
1092 for (offset_t i{}; N != i; ++i) {
1093 auto pos = indices_[block][i];
1094 if (NULL_POS != pos) {
1095 surfel_[pos].removePoint(first, last);
1096 if (surfel_[pos].empty()) {
1097 deleteSurfel(Index{block, i});
1098 }
1099 }
1100 }
1101 },
1102 propagate);
1103 }
1104
1105 template <class PointRange>
1106 Node surfelRemove(Code code, PointRange const& points, bool propagate = true)
1107 {
1108 return surfelRemove(code, std::cbegin(points), std::cend(points), propagate);
1109 }
1110
1111 Node surfelRemove(Code code, std::initializer_list<Point> points, bool propagate = true)
1112 {
1113 return surfelRemove(code, std::cbegin(points), std::cend(points), propagate);
1114 }
1115
1116 Node surfelRemove(Key key, Point point, bool propagate = true)
1117 {
1118 return surfelRemove(derived().toCode(key), point, propagate);
1119 }
1120
1121 template <class InputIt>
1122 Node surfelRemove(Key key, InputIt first, InputIt last, bool propagate = true)
1123 {
1124 return surfelRemove(derived().toCode(key), first, last, propagate);
1125 }
1126
1127 template <class PointRange>
1128 Node surfelRemove(Key key, PointRange const& points, bool propagate = true)
1129 {
1130 return surfelRemove(key, std::cbegin(points), std::cend(points), propagate);
1131 }
1132
1133 Node surfelRemove(Key key, std::initializer_list<Point> points, bool propagate = true)
1134 {
1135 return surfelRemove(key, std::cbegin(points), std::cend(points), propagate);
1136 }
1137
1138 Node surfelRemove(Point coord, Point point, bool propagate = true, depth_t depth = 0)
1139 {
1140 return surfelRemove(derived().toCode(coord, depth), point, propagate);
1141 }
1142
1143 template <class InputIt>
1144 Node surfelRemove(Point coord, InputIt first, InputIt last, bool propagate = true,
1145 depth_t depth = 0)
1146 {
1147 return surfelRemove(derived().toCode(coord, depth), first, last, propagate);
1148 }
1149
1150 template <class PointRange>
1151 Node surfelRemove(Point coord, PointRange const& points, bool propagate = true,
1152 depth_t depth = 0)
1153 {
1154 return surfelRemove(coord, std::cbegin(points), std::cend(points), propagate, depth);
1155 }
1156
1157 Node surfelRemove(Point coord, std::initializer_list<Point> points,
1158 bool propagate = true, depth_t depth = 0)
1159 {
1160 return surfelRemove(coord, std::cbegin(points), std::cend(points), propagate, depth);
1161 }
1162
1163 //
1164 // Surfel update
1165 //
1166
1167 template <class UnaryOp,
1168 std::enable_if_t<std::is_invocable_v<UnaryOp, Surfel>, bool> = true>
1169 void surfelUpdate(Index node, UnaryOp unary_op)
1170 {
1171 derived().apply(
1172 node,
1173 [this, unary_op](Index node) {
1174 auto pos = indices_[node.pos][node.offset];
1175 if (NULL_POS == pos) {
1176 if (auto s = unary_op(Surfel{}); !s.empty()) {
1177 createOrAssignSurfel(node, s);
1178 }
1179 } else {
1180 if (auto s = unary_op(surfel_[pos]); !s.empty()) {
1181 surfel_[pos] = s;
1182 } else {
1183 deleteSurfel(node);
1184 }
1185 }
1186 },
1187 [this, unary_op](pos_t block) {
1188 for (offset_t i{}; N != i; ++i) {
1189 Index node(block, i);
1190 auto pos = indices_[node.pos][node.offset];
1191 if (NULL_POS == pos) {
1192 if (auto s = unary_op(Surfel{}); !s.empty()) {
1193 createOrAssignSurfel(node, s);
1194 }
1195 } else {
1196 if (auto s = unary_op(surfel_[pos]); !s.empty()) {
1197 surfel_[pos] = s;
1198 } else {
1199 deleteSurfel(node);
1200 }
1201 }
1202 }
1203 });
1204 }
1205
1206 template <class BinaryOp,
1207 std::enable_if_t<std::is_invocable_v<BinaryOp, Index, Surfel>, bool> = true>
1208 void surfelUpdate(Index node, BinaryOp binary_op)
1209 {
1210 derived().apply(
1211 node,
1212 [this, binary_op](Index node) {
1213 auto pos = indices_[node.pos][node.offset];
1214 if (NULL_POS == pos) {
1215 if (auto s = binary_op(node, Surfel{}); !s.empty()) {
1216 createOrAssignSurfel(node, s);
1217 }
1218 } else {
1219 if (auto s = binary_op(node, surfel_[pos]); !s.empty()) {
1220 surfel_[pos] = s;
1221 } else {
1222 deleteSurfel(node);
1223 }
1224 }
1225 },
1226 [this, binary_op](pos_t block) {
1227 for (offset_t i{}; N != i; ++i) {
1228 Index node(block, i);
1229 auto pos = indices_[node.pos][node.offset];
1230 if (NULL_POS == pos) {
1231 if (auto s = binary_op(node, Surfel{}); !s.empty()) {
1232 createOrAssignSurfel(node, s);
1233 }
1234 } else {
1235 if (auto s = binary_op(node, surfel_[pos]); !s.empty()) {
1236 surfel_[pos] = s;
1237 } else {
1238 deleteSurfel(node);
1239 }
1240 }
1241 }
1242 });
1243 }
1244
1245 template <class UnaryOp,
1246 std::enable_if_t<std::is_invocable_v<UnaryOp, Surfel>, bool> = true>
1247 Node surfelUpdate(Node node, UnaryOp unary_op, bool propagate = true)
1248 {
1249 return derived().apply(
1250 node,
1251 [this, unary_op](Index node) {
1252 auto pos = indices_[node.pos][node.offset];
1253 if (NULL_POS == pos) {
1254 if (auto s = unary_op(Surfel{}); !s.empty()) {
1255 createOrAssignSurfel(node, s);
1256 }
1257 } else {
1258 if (auto s = unary_op(surfel_[pos]); !s.empty()) {
1259 surfel_[pos] = s;
1260 } else {
1261 deleteSurfel(node);
1262 }
1263 }
1264 },
1265 [this, unary_op](pos_t block) {
1266 for (offset_t i{}; N != i; ++i) {
1267 Index node(block, i);
1268 auto pos = indices_[node.pos][node.offset];
1269 if (NULL_POS == pos) {
1270 if (auto s = unary_op(Surfel{}); !s.empty()) {
1271 createOrAssignSurfel(node, s);
1272 }
1273 } else {
1274 if (auto s = unary_op(surfel_[pos]); !s.empty()) {
1275 surfel_[pos] = s;
1276 } else {
1277 deleteSurfel(node);
1278 }
1279 }
1280 }
1281 },
1282 propagate);
1283 }
1284
1285 template <class BinaryOp,
1286 std::enable_if_t<std::is_invocable_v<BinaryOp, Index, Surfel>, bool> = true>
1287 Node surfelUpdate(Node node, BinaryOp binary_op, bool propagate = true)
1288 {
1289 return derived().apply(
1290 node,
1291 [this, binary_op](Index node) {
1292 auto pos = indices_[node.pos][node.offset];
1293 if (NULL_POS == pos) {
1294 if (auto s = binary_op(node, Surfel{}); !s.empty()) {
1295 createOrAssignSurfel(node, s);
1296 }
1297 } else {
1298 if (auto s = binary_op(node, surfel_[pos]); !s.empty()) {
1299 surfel_[pos] = s;
1300 } else {
1301 deleteSurfel(node);
1302 }
1303 }
1304 },
1305 [this, binary_op](pos_t block) {
1306 for (offset_t i{}; N != i; ++i) {
1307 Index node(block, i);
1308 auto pos = indices_[node.pos][node.offset];
1309 if (NULL_POS == pos) {
1310 if (auto s = binary_op(node, Surfel{}); !s.empty()) {
1311 createOrAssignSurfel(node, s);
1312 }
1313 } else {
1314 if (auto s = binary_op(node, surfel_[pos]); !s.empty()) {
1315 surfel_[pos] = s;
1316 } else {
1317 deleteSurfel(node);
1318 }
1319 }
1320 }
1321 },
1322 propagate);
1323 }
1324
1325 template <class UnaryOp,
1326 std::enable_if_t<std::is_invocable_v<UnaryOp, Surfel>, bool> = true>
1327 Node surfelUpdate(Code code, UnaryOp unary_op, bool propagate = true)
1328 {
1329 return derived().apply(
1330 code,
1331 [this, unary_op](Index node) {
1332 auto pos = indices_[node.pos][node.offset];
1333 if (NULL_POS == pos) {
1334 if (auto s = unary_op(Surfel{}); !s.empty()) {
1335 createOrAssignSurfel(node, s);
1336 }
1337 } else {
1338 if (auto s = unary_op(surfel_[pos]); !s.empty()) {
1339 surfel_[pos] = s;
1340 } else {
1341 deleteSurfel(node);
1342 }
1343 }
1344 },
1345 [this, unary_op](pos_t block) {
1346 for (offset_t i{}; N != i; ++i) {
1347 Index node(block, i);
1348 auto pos = indices_[node.pos][node.offset];
1349 if (NULL_POS == pos) {
1350 if (auto s = unary_op(Surfel{}); !s.empty()) {
1351 createOrAssignSurfel(node, s);
1352 }
1353 } else {
1354 if (auto s = unary_op(surfel_[pos]); !s.empty()) {
1355 surfel_[pos] = s;
1356 } else {
1357 deleteSurfel(node);
1358 }
1359 }
1360 }
1361 },
1362 propagate);
1363 }
1364
1365 template <class BinaryOp,
1366 std::enable_if_t<std::is_invocable_v<BinaryOp, Index, Surfel>, bool> = true>
1367 Node surfelUpdate(Code code, BinaryOp binary_op, bool propagate = true)
1368 {
1369 return derived().apply(
1370 code,
1371 [this, binary_op](Index node) {
1372 auto pos = indices_[node.pos][node.offset];
1373 if (NULL_POS == pos) {
1374 if (auto s = binary_op(node, Surfel{}); !s.empty()) {
1375 createOrAssignSurfel(node, s);
1376 }
1377 } else {
1378 if (auto s = binary_op(node, surfel_[pos]); !s.empty()) {
1379 surfel_[pos] = s;
1380 } else {
1381 deleteSurfel(node);
1382 }
1383 }
1384 },
1385 [this, binary_op](pos_t block) {
1386 for (offset_t i{}; N != i; ++i) {
1387 Index node(block, i);
1388 auto pos = indices_[node.pos][node.offset];
1389 if (NULL_POS == pos) {
1390 if (auto s = binary_op(node, Surfel{}); !s.empty()) {
1391 createOrAssignSurfel(node, s);
1392 }
1393 } else {
1394 if (auto s = binary_op(node, surfel_[pos]); !s.empty()) {
1395 surfel_[pos] = s;
1396 } else {
1397 deleteSurfel(node);
1398 }
1399 }
1400 }
1401 },
1402 propagate);
1403 }
1404
1405 template <class UnaryOp,
1406 std::enable_if_t<std::is_invocable_v<UnaryOp, Surfel>, bool> = true>
1407 Node surfelUpdate(Key key, UnaryOp unary_op, bool propagate = true)
1408 {
1409 return surfelUpdate(derived().toCode(key), unary_op, propagate);
1410 }
1411
1412 template <class BinaryOp,
1413 std::enable_if_t<std::is_invocable_v<BinaryOp, Index, Surfel>, bool> = true>
1414 Node surfelUpdate(Key key, BinaryOp binary_op, bool propagate = true)
1415 {
1416 return surfelUpdate(derived().toCode(key), binary_op, propagate);
1417 }
1418
1419 template <class UnaryOp,
1420 std::enable_if_t<std::is_invocable_v<UnaryOp, Surfel>, bool> = true>
1421 Node surfelUpdate(Point coord, UnaryOp unary_op, bool propagate = true,
1422 depth_t depth = 0)
1423 {
1424 return surfelUpdate(derived().toCode(coord, depth), unary_op, propagate);
1425 }
1426
1427 template <class BinaryOp,
1428 std::enable_if_t<std::is_invocable_v<BinaryOp, Index, Surfel>, bool> = true>
1429 Node surfelUpdate(Point coord, BinaryOp binary_op, bool propagate = true,
1430 depth_t depth = 0)
1431 {
1432 return surfelUpdate(derived().toCode(coord, depth), binary_op, propagate);
1433 }
1434
1435 //
1436 // Surfel clear
1437 //
1438
1439 void surfelClear(Index node)
1440 {
1441 derived().apply(
1442 node, [this](Index node) { deleteSurfel(node); },
1443 [this](pos_t block) { clearImpl(block); });
1444 }
1445
1446 Node surfelClear(Node node, bool propagate = true)
1447 {
1448 return derived().apply(
1449 node, [this](Index node) { deleteSurfel(node); },
1450 [this](pos_t block) { clearImpl(block); }, propagate);
1451 }
1452
1453 Node surfelClear(Code code, bool propagate = true)
1454 {
1455 return derived().apply(
1456 code, [this](Index node) { deleteSurfel(node); },
1457 [this](pos_t block) { clearImpl(block); }, propagate);
1458 }
1459
1460 Node surfelClear(Key key, bool propagate = true)
1461 {
1462 return surfelClear(derived().toCode(key), propagate);
1463 }
1464
1465 Node surfelClear(Point coord, bool propagate = true, depth_t depth = 0)
1466 {
1467 return surfelClear(derived().toCode(coord, depth), propagate);
1468 }
1469
1470 protected:
1471 //
1472 // Constructors
1473 //
1474
1475 SurfelMap() { indices_.emplace_back(); }
1476
1477 SurfelMap(SurfelMap const& other) = default;
1478
1479 SurfelMap(SurfelMap&& other) = default;
1480
1481 template <class Derived2>
1483 : indices_(other.indices_), surfel_(other.surfel_), free_surfel_(other.free_surfel_)
1484 {
1485 }
1486
1487 template <class Derived2>
1489 : indices_(std::move(other.indices_))
1490 , surfel_(std::move(other.surfel_))
1491 , free_surfel_(std::move(other.free_surfel_))
1492 {
1493 }
1494
1495 template <bool Cached2, class Derived2>
1497 : indices_(other.indices_)
1498 , surfel_(std::cbegin(other.surfel_), std::cend(other.surfel_))
1499 , free_surfel_(other.free_surfel_)
1500 {
1501 }
1502
1503 template <bool Cached2, class Derived2>
1505 : indices_(std::move(other.indices_))
1506 , surfel_(std::cbegin(other.surfel_), std::cend(other.surfel_))
1507 , free_surfel_(std::move(other.free_surfel_))
1508 {
1509 }
1510
1511 //
1512 // Destructor
1513 //
1514
1515 ~SurfelMap() = default;
1516
1517 //
1518 // Assignment operator
1519 //
1520
1521 SurfelMap& operator=(SurfelMap const& rhs) = default;
1522
1523 SurfelMap& operator=(SurfelMap&& rhs) = default;
1524
1525 template <class Derived2>
1526 SurfelMap& operator=(SurfelMap<Cached, Derived2> const& rhs)
1527 {
1528 indices_ = rhs.indices_;
1529 surfel_ = rhs.surfel_;
1530 free_surfel_ = rhs.free_surfel_;
1531 return *this;
1532 }
1533
1534 template <class Derived2>
1535 SurfelMap& operator=(SurfelMap<Cached, Derived2>&& rhs)
1536 {
1537 indices_ = std::move(rhs.indices_);
1538 surfel_ = std::move(rhs.surfel_);
1539 free_surfel_ = std::move(rhs.free_surfel_);
1540 return *this;
1541 }
1542
1543 template <bool Cached2, class Derived2>
1544 SurfelMap& operator=(SurfelMap<Cached2, Derived2> const& rhs)
1545 {
1546 indices_ = rhs.indices_;
1547 surfel_ = decltype(surfel_)(std::cbegin(rhs.surfel_), std::cend(rhs.surfel_));
1548 free_surfel_ = rhs.free_surfel_;
1549 return *this;
1550 }
1551
1552 template <bool Cached2, class Derived2>
1553 SurfelMap& operator=(SurfelMap<Cached2, Derived2>&& rhs)
1554 {
1555 indices_ = std::move(rhs.indices_);
1556 surfel_ = decltype(surfel_)(std::cbegin(rhs.surfel_), std::cend(rhs.surfel_));
1557 free_surfel_ = std::move(rhs.free_surfel_);
1558 return *this;
1559 }
1560
1561 //
1562 // Swap
1563 //
1564
1565 void swap(SurfelMap& other)
1566 {
1567 std::swap(indices_, other.indices_);
1568 std::swap(surfel_, other.surfel_);
1569 std::swap(free_surfel_, other.free_surfel_);
1570 }
1571
1572 //
1573 // Derived
1574 //
1575
1576 [[nodiscard]] constexpr Derived& derived() { return *static_cast<Derived*>(this); }
1577
1578 [[nodiscard]] constexpr Derived const& derived() const
1579 {
1580 return *static_cast<Derived const*>(this);
1581 }
1582
1583 //
1584 // Initialize root
1585 //
1586
1587 void initRoot()
1588 {
1589 auto node = derived().rootIndex();
1590 indices_[node.pos][node.offset] = NULL_POS;
1591 }
1592
1593 //
1594 // Create node block
1595 //
1596
1597 void createBlock(Index node)
1598 {
1599 auto children_block = indices_.size();
1600 indices_.emplace_back();
1601 auto pos = indices_[node.pos][node.offset];
1602 if (NULL_POS == pos) {
1603 indices_.back().fill(NULL_POS);
1604 } else {
1605 for (offset_t i{}; N != i; ++i) {
1606 createOrAssignSurfel(Index{children_block, i}, surfel_[pos]);
1607 }
1608 }
1609 }
1610
1611 //
1612 // Fill
1613 //
1614
1615 void fill(Index node, pos_t children_block)
1616 {
1617 auto pos = indices_[node.pos][node.offset];
1618 if (NULL_POS == pos) {
1619 indices_.back().fill(NULL_POS);
1620 } else {
1621 for (offset_t i{}; N != i; ++i) {
1622 createOrAssignSurfel(Index{children_block, i}, surfel_[pos]);
1623 }
1624 }
1625 }
1626
1627 //
1628 // Resize
1629 //
1630
1631 void resize(std::size_t count)
1632 {
1633 typename decltype(indices_)::value_type idx;
1634 idx.fill(NULL_POS);
1635 indices_.resize(count, idx);
1636 }
1637
1638 //
1639 // Reserve
1640 //
1641
1642 void reserveImpl(std::size_t new_cap) { indices_.reserve(new_cap); }
1643
1644 //
1645 // Clear
1646 //
1647
1648 void clearImpl()
1649 {
1650 indices_.resize(1);
1651 indices_[0].fill(NULL_POS);
1652 surfel_.clear();
1653 free_surfel_ = decltype(free_surfel_)();
1654 }
1655
1656 void clearImpl(pos_t block)
1657 {
1658 for (offset_t i{}; N != i; ++i) {
1659 deleteSurfel(Index{block, i});
1660 }
1661 }
1662
1663 //
1664 // Update block
1665 //
1666
1667 void updateBlock(pos_t block, std::array<bool, N> modified_parent)
1668 {
1669 for (offset_t i{}; N != i; ++i) {
1670 if (modified_parent[i]) {
1671 Index node(block, i);
1672 updateNode(node, derived().children(node));
1673 }
1674 }
1675 }
1676
1677 void updateNode(Index node)
1678 {
1679 Surfel surfel;
1680
1681 auto children = derived().children(node);
1682 for (std::size_t i{}; N != i; ++i) {
1683 auto pos = indices_[children][i];
1684 if (NULL_POS != pos) {
1685 surfel += surfel_[pos];
1686 }
1687 }
1688
1689 if (surfel.empty()) {
1690 deleteSurfel(node);
1691 } else {
1692 createOrAssignSurfel(node, surfel);
1693 }
1694 }
1695
1696 //
1697 // Is prunable
1698 //
1699
1700 [[nodiscard]] bool isPrunable(pos_t block) const
1701 {
1702 return std::all_of(std::cbegin(indices_[block]) + 1, std::cend(indices_[block]),
1703 [a = indices_[block].front()](auto b) {
1704 // FIXME: Do we need to actually look at the surfels?
1705 // The intended use of the surfels would mean that it is
1706 // impossible that two nodes have the exact same surfel. The only
1707 // time it can happen is when neither contains a surfel and hence
1708 // the surfel-index for both is NULL_POS.
1709 return a == b;
1710 });
1711 }
1712
1713 void preparePrune(Index)
1714 {
1715 // FIXME: If the comment above is true then it is impossible to prune while we still
1716 // have surfels in the node; hence, we do not need to do anything here.
1717 }
1718
1719 //
1720 // Memory
1721 //
1722
1723 [[nodiscard]] std::size_t sizeofNodeTimesN(Index node)
1724 {
1725 auto pos = indices_[node.pos][node.offset];
1726 return N * (sizeof(pos) + (NULL_POS != pos ? sizeof(surfel_[pos]) : 0));
1727 }
1728
1729 [[nodiscard]] std::size_t sizeofBlock(pos_t block)
1730 {
1731 std::size_t size{};
1732 for (offset_t i{}; N != i; ++i) {
1733 auto pos = indices_[block][i];
1734 size += sizeof(pos) + (NULL_POS != pos ? sizeof(surfel_[pos]) : 0);
1735 }
1736 return size;
1737 }
1738
1739 [[nodiscard]] static constexpr std::size_t sizeofBlockLowerBound() noexcept
1740 {
1741 return sizeof(typename decltype(indices_)::value_type);
1742 }
1743
1744 [[nodiscard]] static constexpr std::size_t sizeofMap() noexcept
1745 {
1746 return sizeof(indices_) + sizeof(surfel_) + sizeof(free_surfel_);
1747 }
1748
1749 //
1750 // Input/output (read/write)
1751 //
1752
1753 [[nodiscard]] static constexpr MapType mapType() noexcept { return MapType::SURFEL; }
1754
1755 [[nodiscard]] constexpr std::size_t serializedSizeBlock(pos_t block)
1756 {
1757 std::size_t num_surfels{};
1758 for (auto i : indices_[block]) {
1759 num_surfels += NULL_POS != indices_[block][i];
1760 }
1761 return sizeof(BitSet<N>) + num_surfels * sizeof(Surfel);
1762 }
1763
1764 template <class Container>
1765 constexpr std::size_t serializedSize(Container const& c) const
1766 {
1767 std::size_t size{};
1768 for (auto block : c) {
1769 size += serializedSizeBlock(block);
1770 }
1771 return size;
1772 }
1773
1774 template <class Container>
1775 void readNodes(ReadBuffer& in, Container const& c)
1776 {
1777 // TODO: Implement
1778 // for (auto const [pos, offsets] : c) {
1779 // if (offsets.all()) {
1780 // in.read(time_[pos].data(), serializedSizeBlock());
1781 // } else {
1782 // DataBlock<time_t, N> time;
1783 // in.read(time.data(), serializedSizeBlock());
1784 // for (offset_t i{}; N != i; ++i) {
1785 // time_[pos][i] = offsets[i] ? time[i] : time_[pos][i];
1786 // }
1787 // }
1788 // }
1789 }
1790
1791 template <class BlockRange>
1792 void writeBlocks(WriteBuffer& out, BlockRange const& blocks) const
1793 {
1794 // TODO: Implement
1795 // for (auto block : c) {
1796 // BitSet<N> has_surfel;
1797 // for (std::size_t i{}; N != i; ++i) {
1798 // has_surfel[i] = NULL_POS != indices_[block][i];
1799 // }
1800 // out.write(has_surfel, sizeof(BitSet<N>));
1801 // for (std::size_t i{}; N != i; ++i) {
1802 // auto pos = indices_[block][i];
1803 // if (NULL_POS != pos) {
1804 // out.write(static_cast<Surfel const&>(surfel_[pos]), sizeof(Surfel));
1805 // }
1806 // }
1807 // }
1808 }
1809
1810 //
1811 // Create surfel
1812 //
1813
1814 pos_t createSurfel(Index node)
1815 {
1816 auto pos = indices_[node.pos][node.offset];
1817 if (NULL_POS != pos) {
1818 return pos;
1819 }
1820
1821 pos = free_surfel_.empty() ? surfel_.size() : free_surfel_.top();
1822 indices_[node.pos][node.offset] = pos;
1823 if (free_surfel_.empty()) {
1824 surfel_.emplace_back();
1825 } else {
1826 free_surfel_.pop();
1827 }
1828 return pos;
1829 }
1830
1831 pos_t createOrAssignSurfel(Index node, Surfel const& surfel)
1832 {
1833 // TODO: What happens if surfel is empty?
1834
1835 auto pos = indices_[node.pos][node.offset];
1836 if (NULL_POS != pos) {
1837 surfel_[pos] = surfel;
1838 return pos;
1839 }
1840
1841 pos = free_surfel_.empty() ? surfel_.size() : free_surfel_.top();
1842 indices_[node.pos][node.offset] = pos;
1843 if (free_surfel_.empty()) {
1844 surfel_.push_back(surfel);
1845 } else {
1846 free_surfel_.pop();
1847 surfel_[pos] = surfel;
1848 }
1849 return pos;
1850 }
1851
1852 //
1853 // Delete surfel
1854 //
1855
1856 void deleteSurfel(Index node)
1857 {
1858 auto pos = indices_[node.pos][node.offset];
1859 if (NULL_POS == pos) {
1860 return;
1861 }
1862
1863 free_surfel_.push(pos);
1864 indices_[node.pos][node.offset] = NULL_POS;
1865 }
1866
1867 private:
1868 Container<DataBlock<pos_t, N>> indices_;
1869 std::deque<SurfelT> surfel_;
1870 std::stack<pos_t> free_surfel_;
1871
1872 template <class Derived2, std::size_t N2>
1873 friend class SurfelMap;
1874};
1875} // namespace ufo
1876
1877namespace ufo
1878{
1879//
1880// Type traits
1881//
1882
1883template <class Map>
1884struct is_surfel_map
1885 : std::conditional_t<is_map_type_v<Map, MapType::SURFEL>, std::true_type,
1886 std::false_type> {
1887};
1888template <class Map>
1889constexpr inline bool is_surfel_map_v = is_surfel_map<Map>::value;
1890} // namespace ufo
1891#endif // UFO_MAP_SURFEL_MAP_HPP
Represents an incremental surface element (surfel) that tracks the sufficient statistics of a 3D poin...
Definition surfel.hpp:97
constexpr bool empty() const noexcept
Returns true if no points have been added.
Definition surfel.hpp:187
All vision-related classes and functions.
Definition cloud.hpp:49
constexpr T b(Lab< T, Flags > color) noexcept
Returns the un-weighted blue–yellow axis value.
Definition lab.hpp:326
constexpr T a(Lab< T, Flags > color) noexcept
Returns the un-weighted green–red axis value.
Definition lab.hpp:310