UFO 1.0.0
An Efficient Probabilistic 3D Mapping Framework That Embraces the Unknown
Loading...
Searching...
No Matches
tree_set.hpp
1
42#ifndef UFO_CONTAINER_TREE_SET_HPP
43#define UFO_CONTAINER_TREE_SET_HPP
44
45// UFO
46#include <ufo/container/tree/predicate/predicate.hpp>
47#include <ufo/container/tree/set/block.hpp>
48#include <ufo/container/tree/set/iterator.hpp>
49#include <ufo/container/tree/set/nearest_iterator.hpp>
50#include <ufo/container/tree/set/query_iterator.hpp>
51#include <ufo/container/tree/set/query_nearest_iterator.hpp>
52#include <ufo/container/tree/tree.hpp>
53#include <ufo/execution/execution.hpp>
54#include <ufo/geometry/dynamic_geometry.hpp>
55
56// STL
57#include <array>
58#include <cstddef>
59#include <limits>
60#include <list>
61
62namespace ufo
63{
64template <std::size_t Dim>
66 : protected Tree<TreeSet<Dim>, Dim, TreeSetBlock<Dim, std::size_t(1) << Dim>>
67{
68 protected:
69 using Block = TreeSetBlock<Dim, std::size_t(1) << Dim>;
70 using Base = Tree<TreeSet, Dim, Block>;
71
72 //
73 // Friends
74 //
75
76 // First base friends :)
77 friend Base;
78
79 friend typename Base::const_iterator;
80
81 template <class Geometry, pred::SpatialTag Tag, bool Negated>
82 friend class pred::Spatial;
83
84 public:
85 /**************************************************************************************
86 | |
87 | Tags |
88 | |
89 **************************************************************************************/
90
91 // UFO stuff
92 using Index = typename Base::Index;
93 using Node = typename Base::Node;
94 using Code = typename Base::Code;
95 using Key = typename Base::Key;
96 using Point = typename Base::Point;
97 using Coord = typename Base::Coord;
98 using Bounds = typename Base::Bounds;
99 using Length = typename Base::Length;
100 using coord_t = typename Base::coord_t;
101 using depth_t = typename Base::depth_t;
102 using offset_t = typename Base::offset_t;
103 using length_t = typename Base::length_t;
104 using pos_t = typename Base::pos_t;
105
106 // STL stuff
107 using value_type = typename Block::value_type;
108 using reference = value_type&;
109 using const_reference = value_type const&;
110 using pointer = value_type*;
111 using const_pointer = value_type const*;
112 using size_type = std::size_t;
113 using difference_type = std::ptrdiff_t;
114
115 // Iterators
116 // NOTE: All iterators are const because it is not possible to change the key
117
118 using const_iterator = TreeSetIterator<true, Dim>;
119 using iterator = const_iterator;
120
121 template <class Predicate>
122 using const_query_iterator_pred = TreeSetQueryIterator<true, Dim, Predicate>;
123 template <class Predicate>
124 using query_iterator_pred = const_query_iterator_pred<Predicate>;
125
126 using const_query_iterator = const_query_iterator_pred<pred::Predicate<TreeSet>>;
127 using query_iterator = const_query_iterator;
128
129 template <class Geometry>
130 using const_nearest_iterator_geom = TreeSetNearestIterator<true, Dim, Geometry>;
131 template <class Geometry>
132 using nearest_iterator_geom = const_nearest_iterator_geom<Geometry>;
133
134 using const_nearest_iterator = const_nearest_iterator_geom<DynamicGeometry>;
135 using nearest_iterator = const_nearest_iterator;
136
137 template <class Predicate, class Geometry>
138 using const_query_nearest_iterator_pred_geom =
139 TreeSetQueryNearestIterator<true, Dim, Predicate, Geometry>;
140 template <class Predicate, class Geometry>
141 using query_nearest_iterator_pred_geom =
142 const_query_nearest_iterator_pred_geom<Predicate, Geometry>;
143
144 using const_query_nearest_iterator =
145 const_query_nearest_iterator_pred_geom<pred::Predicate<TreeSet>, DynamicGeometry>;
146 using query_nearest_iterator = const_query_nearest_iterator;
147
148 template <class Predicate>
149 using ConstQuery =
150 IteratorWrapper<const_query_iterator_pred<Predicate>, const_query_iterator>;
151 template <class Predicate>
152 using Query = ConstQuery<Predicate>;
153
154 template <class Geometry>
155 using ConstNearest =
156 IteratorWrapper<const_nearest_iterator_geom<Geometry>, const_nearest_iterator>;
157 template <class Geometry>
158 using Nearest = ConstNearest<Geometry>;
159
160 template <class Predicate, class Geometry>
161 using ConstQueryNearest =
162 IteratorWrapper<const_query_nearest_iterator_pred_geom<Predicate, Geometry>,
163 const_query_nearest_iterator>;
164 template <class Predicate, class Geometry>
165 using QueryNearest = ConstQueryNearest<Predicate, Geometry>;
166
167 //
168 // Friend iterators
169 //
170
171 template <bool, std::size_t>
172 friend class TreeSetIterator;
173
174 template <bool, std::size_t, class>
175 friend class TreeSetQueryIterator;
176
177 template <bool, std::size_t, class>
178 friend class TreeSetNearestIterator;
179
180 template <bool, std::size_t, class, class>
181 friend class TreeSetQueryNearestIterator;
182
183 private:
184 using container_type = typename Block::container_type;
185
186 public:
187 /**************************************************************************************
188 | |
189 | Constructors |
190 | |
191 **************************************************************************************/
192
193 TreeSet(Length leaf_node_length = Length(0.1),
194 depth_t num_depth_levels = std::min(depth_t(17), Base::maxNumDepthLevels()))
195 : Base(leaf_node_length, num_depth_levels)
196 {
197 }
198
199 TreeSet(length_t leaf_node_length,
200 depth_t num_depth_levels = std::min(depth_t(17), Base::maxNumDepthLevels()))
201 : TreeSet(Length(leaf_node_length), num_depth_levels)
202 {
203 }
204
205 template <class InputIt>
206 TreeSet(InputIt first, InputIt last, length_t leaf_node_length = length_t(0.1),
207 depth_t num_depth_levels = std::min(depth_t(17), Base::maxNumDepthLevels()))
208 : TreeSet(leaf_node_length, num_depth_levels)
209 {
210 insert(first, last);
211 }
212
213 TreeSet(std::initializer_list<value_type> init,
214 length_t leaf_node_length = length_t(0.1),
215 depth_t num_depth_levels = std::min(depth_t(17), Base::maxNumDepthLevels()))
216 : TreeSet(init.begin(), init.end(), leaf_node_length, num_depth_levels)
217 {
218 }
219
220 template <class Range>
221 TreeSet(Range const& range, length_t leaf_node_length = length_t(0.1),
222 depth_t num_depth_levels = std::min(depth_t(17), Base::maxNumDepthLevels()))
223 : TreeSet(std::begin(range), std::end(range), leaf_node_length, num_depth_levels)
224 {
225 }
226
227 /**************************************************************************************
228 | |
229 | Iterators |
230 | |
231 **************************************************************************************/
232
233 [[nodiscard]] iterator begin() { return iterator(this, Base::index()); }
234
235 [[nodiscard]] const_iterator begin() const
236 {
237 return const_iterator(const_cast<TreeSet*>(this), Base::index());
238 }
239
240 [[nodiscard]] const_iterator cbegin() const { return begin(); }
241
242 [[nodiscard]] iterator end() { return iterator(); }
243
244 [[nodiscard]] const_iterator end() const { return const_iterator(); }
245
246 [[nodiscard]] const_iterator cend() const { return end(); }
247
248 /**************************************************************************************
249 | |
250 | Query iterators |
251 | |
252 **************************************************************************************/
253
254 template <class Predicate>
255 [[nodiscard]] query_iterator_pred<Predicate> beginQuery(Predicate const& pred)
256 {
257 return query_iterator_pred<Predicate>(this, Base::index(), pred);
258 }
259
260 template <class Predicate>
261 [[nodiscard]] const_query_iterator_pred<Predicate> beginQuery(
262 Predicate const& pred) const
263 {
264 return const_query_iterator_pred<Predicate>(const_cast<TreeSet*>(this), Base::index(),
265 pred);
266 }
267
268 template <class Predicate>
269 [[nodiscard]] const_query_iterator_pred<Predicate> cbeginQuery(
270 Predicate const& pred) const
271 {
272 return beginQuery(pred);
273 }
274
275 [[nodiscard]] query_iterator endQuery() { return query_iterator(); }
276
277 [[nodiscard]] const_query_iterator endQuery() const { return const_query_iterator(); }
278
279 [[nodiscard]] const_query_iterator cendQuery() const { return endQuery(); }
280
281 /**************************************************************************************
282 | |
283 | Nearest iterators |
284 | |
285 **************************************************************************************/
286
287 template <class Geometry>
288 [[nodiscard]] nearest_iterator_geom<Geometry> beginNearest(Geometry const& query,
289 float epsilon = 0.0f)
290 {
291 return nearest_iterator_geom<Geometry>(this, Base::index(), query, epsilon);
292 }
293
294 template <class Geometry>
295 [[nodiscard]] const_nearest_iterator_geom<Geometry> beginNearest(
296 Geometry const& query, float epsilon = 0.0f) const
297 {
298 return const_nearest_iterator_geom<Geometry>(const_cast<TreeSet*>(this),
299 Base::index(), query, epsilon);
300 }
301
302 template <class Geometry>
303 [[nodiscard]] const_nearest_iterator_geom<Geometry> cbeginNearest(
304 Geometry const& query, float epsilon = 0.0f) const
305 {
306 return beginNearest(query, epsilon);
307 }
308
309 [[nodiscard]] nearest_iterator endNearest() { return nearest_iterator(); }
310
311 [[nodiscard]] const_nearest_iterator endNearest() const
312 {
313 return const_nearest_iterator();
314 }
315
316 [[nodiscard]] const_nearest_iterator cendNearest() const { return endNearest(); }
317
318 /**************************************************************************************
319 | |
320 | Query nearest iterators |
321 | |
322 **************************************************************************************/
323
324 template <class Predicate, class Geometry>
325 [[nodiscard]] query_nearest_iterator_pred_geom<Predicate, Geometry> beginQueryNearest(
326 Predicate const& pred, Geometry const& query, float epsilon = 0.0f)
327 {
328 return query_nearest_iterator_pred_geom<Predicate, Geometry>(this, Base::index(),
329 pred, query, epsilon);
330 }
331
332 template <class Predicate, class Geometry>
333 [[nodiscard]] const_query_nearest_iterator_pred_geom<Predicate, Geometry>
334 beginQueryNearest(Predicate const& pred, Geometry const& query,
335 float epsilon = 0.0f) const
336 {
337 return const_query_nearest_iterator_pred_geom<Predicate, Geometry>(
338 const_cast<TreeSet*>(this), Base::index(), pred, query, epsilon);
339 }
340
341 template <class Predicate, class Geometry>
342 [[nodiscard]] const_query_nearest_iterator_pred_geom<Predicate, Geometry>
343 cbeginQueryNearest(Predicate const& pred, Geometry const& query,
344 float epsilon = 0.0f) const
345 {
346 return beginQueryNearest(pred, query, epsilon);
347 }
348
349 [[nodiscard]] query_nearest_iterator endQueryNearest()
350 {
351 return query_nearest_iterator();
352 }
353
354 [[nodiscard]] const_query_nearest_iterator endQueryNearest() const
355 {
356 return const_query_nearest_iterator();
357 }
358
359 [[nodiscard]] const_query_nearest_iterator cendQueryNearest() const
360 {
361 return endQueryNearest();
362 }
363
364 /**************************************************************************************
365 | |
366 | Capacity |
367 | |
368 **************************************************************************************/
369
375 [[nodiscard]] bool empty() const noexcept { return 0 == size(); }
376
382 [[nodiscard]] size_type size() const noexcept { return size_; }
383
390 [[nodiscard]] Bounds bounds() const { return bounds(Base::index()); }
391
392 /**************************************************************************************
393 | |
394 | Modifiers |
395 | |
396 **************************************************************************************/
397
402 void clear()
403 {
404 Base::clear();
405 size_ = 0;
406 }
407
408 void insert(value_type const& value)
409 {
410 Index node = Base::create(value);
411 insert(node, value);
412 }
413
414 void insert(value_type&& value)
415 {
416 Index node = Base::create(value);
417 insert(node, std::move(value));
418 }
419
420 template <class InputIt>
421 void insert(InputIt first, InputIt last)
422 {
423 // TODO: Implement
424 insert(execution::seq, first, last);
425 }
426
427 template <
428 class ExecutionPolicy, class RandomIt,
429 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>, bool> = true>
430 void insert(ExecutionPolicy&& policy, RandomIt first, RandomIt last)
431 {
432 // FIXME: Optimize
433
434 auto nodes = Base::create(std::forward<ExecutionPolicy>(policy), first, last);
435
436 for (std::size_t i{}; first != last; ++i, ++first) {
437 insert(nodes[i], *first);
438 }
439 }
440
441 void insert(std::initializer_list<value_type> ilist)
442 {
443 insert(ilist.begin(), ilist.end());
444 }
445
446 template <
447 class ExecutionPolicy,
448 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>, bool> = true>
449 void insert(ExecutionPolicy&& policy, std::initializer_list<value_type> ilist)
450 {
451 insert(std::forward<ExecutionPolicy>(policy), ilist.begin(), ilist.end());
452 }
453
454 template <class Range>
455 void insert(Range const& r)
456 {
457 using std::begin;
458 using std::end;
459 insert(begin(r), end(r));
460 }
461
462 template <
463 class ExecutionPolicy, class Range,
464 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>, bool> = true>
465 void insert(ExecutionPolicy&& policy, Range const& r)
466 {
467 using std::begin;
468 using std::end;
469 insert(std::forward<ExecutionPolicy>(policy), begin(r), end(r));
470 }
471
472 size_type erase(value_type const& value)
473 {
474 auto node = Base::index(value);
475
476 if (!Base::isPureLeaf(node)) {
477 return 0;
478 }
479
480 auto& v = values(node);
481 size_type num_removed = v.size();
482 v.remove_if([&value](auto const& x) { return x == value; });
483 num_removed -= v.size();
484
485 size_ -= num_removed;
486
487 erasePropagate(node);
488
489 return num_removed;
490 }
491
492 // iterator erase(iterator pos)
493 // {
494 // auto it = pos.iterator();
495 // ++pos;
496 // erase(it);
497 // return pos;
498 // }
499
500 iterator erase(const_iterator pos)
501 {
502 auto it = pos.iterator();
503 ++pos;
504 erase(it);
505 return iterator(pos);
506 }
507
508 // template <class Predicate>
509 // query_iterator_pred<Predicate> erase(query_iterator_pred<Predicate> pos)
510 // {
511 // auto it = pos.iterator();
512 // ++pos;
513 // erase(it);
514 // return pos;
515 // }
516
517 template <class Predicate>
518 query_iterator_pred<Predicate> erase(const_query_iterator_pred<Predicate> pos)
519 {
520 auto it = pos.iterator();
521 ++pos;
522 erase(it);
523 return query_iterator_pred<Predicate>(pos);
524 }
525
526 // nearest_iterator erase(nearest_iterator pos)
527 // {
528 // auto it = pos.iterator();
529 // ++pos;
530 // erase(it);
531 // return pos;
532 // }
533
534 template <class Geometry>
535 nearest_iterator_geom<Geometry> erase(const_nearest_iterator_geom<Geometry> pos)
536 {
537 auto it = pos.iterator();
538 ++pos;
539 erase(it);
540 return nearest_iterator_geom<Geometry>(pos);
541 }
542
543 // template <class Predicate>
544 // query_nearest_iterator_pred<Predicate> erase(query_nearest_iterator_pred<Predicate>
545 // pos)
546 // {
547 // auto it = pos.iterator();
548 // ++pos;
549 // erase(it);
550 // return pos;
551 // }
552
553 template <class Predicate, class Geometry>
554 query_nearest_iterator_pred_geom<Predicate, Geometry> erase(
555 const_query_nearest_iterator_pred_geom<Predicate, Geometry> pos)
556 {
557 auto it = pos.iterator();
558 ++pos;
559 erase(it);
560 return query_nearest_iterator_pred_geom<Predicate, Geometry>(pos);
561 }
562
563 // iterator erase(iterator first, iterator last)
564 // {
565 // while (last != first) {
566 // auto it = first.iterator();
567 // ++first;
568 // erase(it);
569 // }
570 // return first;
571 // }
572
573 iterator erase(const_iterator first, const_iterator last)
574 {
575 while (last != first) {
576 auto it = first.iterator();
577 ++first;
578 erase(it);
579 }
580 return iterator(first);
581 }
582
583 // template <class Predicate1, class Predicate2>
584 // query_iterator_pred<Predicate1> erase(query_iterator_pred<Predicate1> first,
585 // query_iterator_pred<Predicate2> last)
586 // {
587 // while (last != first) {
588 // auto it = first.iterator();
589 // ++first;
590 // erase(it);
591 // }
592 // return first;
593 // }
594
595 template <class Predicate1, class Predicate2>
596 query_iterator_pred<Predicate1> erase(const_query_iterator_pred<Predicate1> first,
597 const_query_iterator_pred<Predicate2> last)
598 {
599 while (last != first) {
600 auto it = first.iterator();
601 ++first;
602 erase(it);
603 }
604 return query_iterator_pred<Predicate1>(first);
605 }
606
607 // template <class Predicate>
608 // query_iterator_pred<Predicate> erase(Query<Predicate> query)
609 // {
610 // return erase(query.begin(), query.end());
611 // }
612
613 template <class Predicate>
614 query_iterator_pred<Predicate> erase(ConstQuery<Predicate> query)
615 {
616 return erase(query.begin(), query.end());
617 }
618
619 // nearest_iterator erase(nearest_iterator first, nearest_iterator last)
620 // {
621 // while (last != first) {
622 // auto it = first.iterator();
623 // ++first;
624 // erase(it);
625 // }
626 // return first;
627 // }
628
629 template <class Geometry1, class Geometry2>
630 nearest_iterator_geom<Geometry1> erase(const_nearest_iterator_geom<Geometry1> first,
631 const_nearest_iterator_geom<Geometry2> last)
632 {
633 while (last != first) {
634 auto it = first.iterator();
635 ++first;
636 erase(it);
637 }
638 return nearest_iterator_geom<Geometry1>(first);
639 }
640
641 // template <class Predicate1, class Predicate2>
642 // query_nearest_iterator_pred<Predicate1> erase(
643 // query_nearest_iterator_pred<Predicate1> first,
644 // query_nearest_iterator_pred<Predicate2> last)
645 // {
646 // while (last != first) {
647 // auto it = first.iterator();
648 // ++first;
649 // erase(it);
650 // }
651 // return first;
652 // }
653
654 template <class Predicate1, class Geometry1, class Predicate2, class Geometry2>
655 query_nearest_iterator_pred_geom<Predicate1, Geometry1> erase(
656 const_query_nearest_iterator_pred_geom<Predicate1, Geometry1> first,
657 const_query_nearest_iterator_pred_geom<Predicate2, Geometry2> last)
658 {
659 while (last != first) {
660 auto it = first.iterator();
661 ++first;
662 erase(it);
663 }
664 return query_nearest_iterator_pred_geom<Predicate1, Geometry1>(first);
665 }
666
667 // template <class Predicate>
668 // query_nearest_iterator_pred<Predicate> erase(QueryNearest<Predicate> query)
669 // {
670 // return erase(query.begin(), query.end());
671 // }
672
673 template <class Predicate, class Geometry>
674 query_nearest_iterator_pred_geom<Predicate, Geometry> erase(
675 ConstQueryNearest<Predicate, Geometry> query)
676 {
677 return erase(query.begin(), query.end());
678 }
679
685 void swap(TreeSet& other)
686 {
687 std::swap(size_, other.size_);
688 std::swap(static_cast<Base&>(*this), static_cast<Base&>(other));
689 }
690
691 /**************************************************************************************
692 | |
693 | Lookup |
694 | |
695 **************************************************************************************/
696
704 [[nodiscard]] size_type count(Point point) const
705 {
706 auto const& v = values(Base::index(point));
707 return std::count_if(v.begin(), v.end(),
708 [point](auto const& x) { return x == point; });
709 }
710
718 [[nodiscard]] bool contains(Point point) const
719 {
720 auto const& v = values(Base::index(point));
721 return std::end(v) != std::find_if(v.begin(), v.end(),
722 [point](auto const& x) { return x == point; });
723 }
724
725 template <class Predicate>
726 [[nodiscard]] Query<Predicate> query(Predicate const& pred)
727 {
728 return Query<Predicate>(beginQuery(pred), endQuery());
729 }
730
731 template <class Predicate>
732 [[nodiscard]] ConstQuery<Predicate> query(Predicate const& pred) const
733 {
734 return ConstQuery<Predicate>(beginQuery(pred), endQuery());
735 }
736
737 template <class Geometry>
738 [[nodiscard]] Nearest<Geometry> nearest(Geometry const& query, float epsilon = 0.0f)
739 {
740 return Nearest<Geometry>(beginNearest(query, epsilon), endNearest());
741 }
742
743 template <class Geometry>
744 [[nodiscard]] ConstNearest<Geometry> nearest(Geometry const& query,
745 float epsilon = 0.0f) const
746 {
747 return ConstNearest<Geometry>(beginNearest(query, epsilon), endNearest());
748 }
749
750 template <class Predicate, class Geometry>
751 [[nodiscard]] QueryNearest<Predicate, Geometry> queryNearest(Predicate const& pred,
752 Geometry const& query,
753 float epsilon = 0.0f)
754 {
755 return QueryNearest<Predicate, Geometry>(beginQueryNearest(pred, query, epsilon),
756 endQueryNearest());
757 }
758
759 template <class Predicate, class Geometry>
760 [[nodiscard]] ConstQueryNearest<Predicate, Geometry> queryNearest(
761 Predicate const& pred, Geometry const& query, float epsilon = 0.0f) const
762 {
763 return ConstQueryNearest<Predicate, Geometry>(beginQueryNearest(pred, query, epsilon),
764 endQueryNearest());
765 }
766
767 template <class Geometry>
768 [[nodiscard]] float nearestDistance(
769 Geometry const& query, float max_distance = std::numeric_limits<float>::infinity(),
770 float epsilon = 0.0f,
771 NearestSearchAlgorithm search_alg = NearestSearchAlgorithm::DEPTH_FIRST) const
772 {
773 float max_distance_sq = max_distance * max_distance;
774 float dist_sq =
775 Base::nearest(
776 Base::index(), search_alg,
777 [this, &query](Index node) {
778 float dist_sq = std::numeric_limits<float>::infinity();
779 for (auto e : values(node)) {
780 dist_sq = UFO_MIN(dist_sq, distanceSquared(query, e));
781 }
782 return dist_sq;
783 },
784 [this, &query](Index node) { return distanceSquared(query, bounds(node)); },
785 max_distance_sq, epsilon * epsilon)
786 .first;
787
788 return max_distance_sq <= dist_sq ? max_distance : std::sqrt(dist_sq);
789 }
790
791 template <class Geometry>
792 [[nodiscard]] std::pair<value_type, float> nearestPoint(
793 Geometry const& query, float max_distance = std::numeric_limits<float>::infinity(),
794 float epsilon = 0.0f,
795 NearestSearchAlgorithm search_alg = NearestSearchAlgorithm::DEPTH_FIRST) const
796 {
797 float max_distance_sq = max_distance * max_distance;
798 auto [dist_sq, node] = Base::nearest(
799 Base::index(), search_alg,
800 [this, &query](Index node) {
801 float dist_sq = std::numeric_limits<float>::infinity();
802 for (auto e : values(node)) {
803 dist_sq = UFO_MIN(dist_sq, distanceSquared(query, e));
804 }
805 return dist_sq;
806 },
807 [this, &query](Index node) { return distanceSquared(query, bounds(node)); },
808 max_distance_sq, epsilon * epsilon);
809
810 value_type value(std::numeric_limits<typename value_type::value_type>::quiet_NaN());
811
812 for (auto const& e : values(node)) {
813 value = distanceSquared(query, e) == dist_sq ? e : value;
814 }
815
816 return {value, max_distance_sq <= dist_sq ? max_distance : std::sqrt(dist_sq)};
817 }
818
819 /**************************************************************************************
820 | |
821 | Bounds |
822 | |
823 **************************************************************************************/
824
832 template <class NodeType,
833 std::enable_if_t<Base::template is_node_type_v<NodeType>, bool> = true>
834 [[nodiscard]] Bounds& bounds(NodeType node)
835 {
836 TreeIndex n = Base::index(node);
837 return Base::treeBlock(n).bounds[n.offset];
838 }
839
847 template <class NodeType,
848 std::enable_if_t<Base::template is_node_type_v<NodeType>, bool> = true>
849 [[nodiscard]] Bounds const& bounds(NodeType node) const
850 {
851 TreeIndex n = Base::index(node);
852 return Base::treeBlock(n).bounds[n.offset];
853 }
854
855 /**************************************************************************************
856 | |
857 | Compare |
858 | |
859 **************************************************************************************/
860
861 template <std::size_t D>
862 friend bool operator==(TreeSet<D> const& lhs, TreeSet<D> const& rhs);
863
864 template <std::size_t D>
865 friend bool operator!=(TreeSet<D> const& lhs, TreeSet<D> const& rhs);
866
867 protected:
868 /**************************************************************************************
869 | |
870 | Functions 'Tree" expect |
871 | |
872 **************************************************************************************/
873
874 void onInitRoot() {}
875
876 void onInitChildren(Index /* node */, pos_t /* children */) {}
877
878 void onPruneChildren(Index /* node */, pos_t /* children */) {}
879
880 /**************************************************************************************
881 | |
882 | Capacity |
883 | |
884 **************************************************************************************/
885
892 [[nodiscard]] bool empty(Index node) const noexcept
893 {
894 return boundsMin(node)[0] > boundsMax(node)[0];
895 }
896
897 /**************************************************************************************
898 | |
899 | Modifiers |
900 | |
901 **************************************************************************************/
902
903 void insert(Index node, value_type const& value)
904 {
905 values(node).push_back(value);
906 ++size_;
907
908 insertPropagate(node, value);
909 }
910
911 void insert(Index node, value_type&& value)
912 {
913 values(node).push_back(std::move(value));
914 ++size_;
915
916 insertPropagate(node, value);
917 }
918
919 void insertPropagate(Index node, Point p)
920 {
921 // Propagate
922 auto root_depth = Base::depth();
923 auto depth = Base::depth(node);
924 for (; root_depth > depth; ++depth) {
925 Point& min = boundsMin(node);
926 Point& max = boundsMax(node);
927 min = ufo::min(min, p);
928 max = ufo::max(max, p);
929 node = Base::parent(node);
930 }
931
932 // Root
933 Point& min = boundsMin(node);
934 Point& max = boundsMax(node);
935 min = ufo::min(min, p);
936 max = ufo::max(max, p);
937 }
938
939 void erase(typename container_type::const_iterator it)
940 {
941 auto node = Base::index(*it);
942
943 if (!Base::isPureLeaf(node)) {
944 return;
945 }
946
947 auto& v = values(node);
948 v.erase(it);
949 --size_;
950
951 erasePropagate(node);
952 }
953
954 void erasePropagate(Index node)
955 {
956 Point min(std::numeric_limits<typename Point::value_type>::max());
957 Point max(std::numeric_limits<typename Point::value_type>::lowest());
958 for (auto const& p : values(node)) {
959 min = ufo::min(min, p);
960 max = ufo::max(max, p);
961 }
962 boundsMin(node) = min;
963 boundsMax(node) = max;
964
965 if (Base::isRoot(node)) {
966 return;
967 }
968
969 auto root_depth = Base::depth();
970 auto child_block = node.pos;
971 node = Base::parent(node);
972 auto depth = Base::depth(node);
973 for (; root_depth > depth; ++depth) {
974 Point min = boundsMin(Index(child_block, 0));
975 Point max = boundsMax(Index(child_block, 0));
976 for (std::size_t i = 1; Base::BF > i; ++i) {
977 min = ufo::min(min, boundsMin(Index(child_block, i)));
978 max = ufo::max(max, boundsMax(Index(child_block, i)));
979 }
980 boundsMin(node) = min;
981 boundsMax(node) = max;
982 child_block = node.pos;
983 node = Base::parent(node);
984 }
985
986 // Root
987 min = boundsMin(Index(child_block, 0));
988 max = boundsMax(Index(child_block, 0));
989 for (std::size_t i = 1; Base::BF > i; ++i) {
990 min = ufo::min(min, boundsMin(Index(child_block, i)));
991 max = ufo::max(max, boundsMax(Index(child_block, i)));
992 }
993 boundsMin(node) = min;
994 boundsMax(node) = max;
995 }
996
997 /**************************************************************************************
998 | |
999 | Internal data |
1000 | |
1001 **************************************************************************************/
1002
1003 [[nodiscard]] auto& values(pos_t block) { return Base::treeBlock(block).values; }
1004
1005 [[nodiscard]] auto const& values(pos_t block) const
1006 {
1007 return Base::treeBlock(block).values;
1008 }
1009
1010 [[nodiscard]] auto& values(Index node)
1011 {
1012 return Base::treeBlock(node).values[node.offset];
1013 }
1014
1015 [[nodiscard]] auto const& values(Index node) const
1016 {
1017 return Base::treeBlock(node).values[node.offset];
1018 }
1019
1028 [[nodiscard]] Point& boundsMin(Index node)
1029 {
1030 return Base::treeBlock(node).bounds[node.offset].min;
1031 }
1032
1041 [[nodiscard]] Point boundsMin(Index node) const
1042 {
1043 return Base::treeBlock(node).bounds[node.offset].min;
1044 }
1045
1054 [[nodiscard]] Point& boundsMax(Index node)
1055 {
1056 return Base::treeBlock(node).bounds[node.offset].max;
1057 }
1058
1067 [[nodiscard]] Point boundsMax(Index node) const
1068 {
1069 return Base::treeBlock(node).bounds[node.offset].max;
1070 }
1071
1072 protected:
1073 size_type size_{};
1074};
1075
1076//
1077// Compare
1078//
1079
1080template <std::size_t Dim>
1081bool operator==(TreeSet<Dim> const& lhs, TreeSet<Dim> const& rhs)
1082{
1083 using Base = typename TreeSet<Dim>::Base;
1084
1085 Base const& lhs_b = static_cast<Base const&>(lhs);
1086 Base const& rhs_b = static_cast<Base const&>(rhs);
1087
1088 return std::equal(lhs_b.begin(), lhs_b.end(), rhs_b.begin(), rhs_b.end(),
1089 [&lhs, &rhs](auto const& l, auto const& r) {
1090 auto lc = l.code;
1091 auto rc = r.code;
1092 auto const& lv = lhs.values(l.index);
1093 auto const& rv = rhs.values(r.index);
1094
1095 return lc == rc && std::is_permutation(lv.begin(), lv.end(),
1096 rv.begin(), rv.end());
1097 });
1098}
1099
1100template <std::size_t Dim>
1101bool operator!=(TreeSet<Dim> const& lhs, TreeSet<Dim> const& rhs)
1102{
1103 return !(lhs == rhs);
1104}
1105
1106using BinaryTreeSet = TreeSet<1>;
1107
1108using QuadtreeSet = TreeSet<2>;
1109
1110using OctreeSet = TreeSet<3>;
1111
1112using HextreeSet = TreeSet<4>;
1113} // namespace ufo
1114
1115#endif // UFO_CONTAINER_TREE_SET_HPP
Utilizing curiously recurring template pattern (CRTP)
Definition tree.hpp:104
All vision-related classes and functions.
Definition cloud.hpp:49