UFO 1.0.0
An Efficient Probabilistic 3D Mapping Framework That Embraces the Unknown
Loading...
Searching...
No Matches
tree_map.hpp
1
42#ifndef UFO_CONTAINER_TREE_MAP_HPP
43#define UFO_CONTAINER_TREE_MAP_HPP
44
45// UFO
46#include <ufo/container/tree/map/block.hpp>
47#include <ufo/container/tree/map/iterator.hpp>
48#include <ufo/container/tree/map/nearest_iterator.hpp>
49#include <ufo/container/tree/map/query_iterator.hpp>
50#include <ufo/container/tree/map/query_nearest_iterator.hpp>
51#include <ufo/container/tree/predicate/predicate.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#include <type_traits>
62
63namespace ufo
64{
65template <std::size_t Dim, class T>
66class TreeMap : protected Tree<TreeMap<Dim, T>, Dim, TreeMapBlock<T>>
67{
68 protected:
70 static constexpr auto const BF = Base::branchingFactor();
71 using LeafBlock = typename TreeMapBlock<T>::template LeafBlock<Dim, BF>;
72 using InnerBlock = typename TreeMapBlock<T>::template InnerBlock<Dim, BF>;
73
74 static_assert(
75 std::is_same_v<typename LeafBlock::value_type, typename InnerBlock::value_type>);
76 static_assert(std::is_same_v<typename LeafBlock::container_type,
77 typename InnerBlock::container_type>);
78
79 //
80 // Friends
81 //
82
83 // First base friends :)
84 friend Base;
85
86 template <class Geometry, pred::SpatialTag Tag, bool Negated>
87 friend class pred::Spatial;
88
89 public:
90 /**************************************************************************************
91 | |
92 | Tags |
93 | |
94 **************************************************************************************/
95
96 // UFO stuff
97 using Index = typename Base::Index;
98 using Node = typename Base::Node;
99 using Code = typename Base::Code;
100 using Key = typename Base::Key;
101 using Point = typename Base::Point;
102 using Coord = typename Base::Coord;
103 using Bounds = typename Base::Bounds;
104 using Length = typename Base::Length;
105 using coord_type = typename Base::coord_type;
106 using depth_type = typename Base::depth_type;
107 using offset_type = typename Base::offset_type;
108 using length_type = typename Base::length_type;
109 using pos_type = typename Base::pos_type;
110
111 // STL stuff
112 using value_type = typename LeafBlock::value_type;
113 using mapped_type = T;
114 using reference = value_type&;
115 using const_reference = value_type const&;
116 using pointer = value_type*;
117 using const_pointer = value_type const*;
118 using size_type = std::size_t;
119 using difference_type = std::ptrdiff_t;
120
121 // TODO: Add `iterator` postfix
122
123 // Iterators
126
127 template <class Predicate>
129 template <class Predicate>
131
134
135 template <class Geometry>
137 template <class Geometry>
139
142
143 template <class Predicate, class Geometry>
146 template <class Predicate, class Geometry>
149
154
155 template <class Predicate>
156 using Query = IteratorWrapper<query_iterator_pred<Predicate>, query_iterator>;
157 template <class Predicate>
158 using ConstQuery =
159 IteratorWrapper<const_query_iterator_pred<Predicate>, const_query_iterator>;
160
161 template <class Geometry>
162 using Nearest = IteratorWrapper<nearest_iterator_geom<Geometry>, nearest_iterator>;
163 template <class Geometry>
164 using ConstNearest =
165 IteratorWrapper<const_nearest_iterator_geom<Geometry>, const_nearest_iterator>;
166
167 template <class Predicate, class Geometry>
168 using QueryNearest =
169 IteratorWrapper<query_nearest_iterator_pred_geom<Predicate, Geometry>,
171 template <class Predicate, class Geometry>
172 using ConstQueryNearest =
173 IteratorWrapper<const_query_nearest_iterator_pred_geom<Predicate, Geometry>,
175
176 //
177 // Friend iterators
178 //
179
180 template <bool, std::size_t, class>
181 friend class TreeMapIterator;
182
183 template <bool, std::size_t, class, class>
184 friend class TreeMapQueryIterator;
185
186 template <bool, std::size_t, class, class>
187 friend class TreeMapNearestIterator;
188
189 template <bool, std::size_t, class, class, class>
190 friend class TreeMapQueryNearestIterator;
191
192 private:
193 using container_type = typename LeafBlock::container_type;
194
195 public:
196 /**************************************************************************************
197 | |
198 | Constructors |
199 | |
200 **************************************************************************************/
201
202 TreeMap(Length leaf_node_length = Length(0.1),
203 depth_type num_depth_levels = std::min(depth_type(17),
205 : Base(leaf_node_length, num_depth_levels)
206 {
207 }
208
209 TreeMap(length_type leaf_node_length,
210 depth_type num_depth_levels = std::min(depth_type(17),
212 : TreeMap(Length(leaf_node_length), num_depth_levels)
213 {
214 }
215
216 template <class InputIt>
217 TreeMap(InputIt first, InputIt last, length_type leaf_node_length = length_type(0.1),
218 depth_type num_depth_levels = std::min(depth_type(17),
220 : TreeMap(leaf_node_length, num_depth_levels)
221 {
222 insert(first, last);
223 }
224
225 TreeMap(std::initializer_list<value_type> init,
226 length_type leaf_node_length = length_type(0.1),
227 depth_type num_depth_levels = std::min(depth_type(17),
229 : TreeMap(init.begin(), init.end(), leaf_node_length, num_depth_levels)
230 {
231 }
232
233 template <class Range>
234 TreeMap(Range const& range, length_type leaf_node_length = length_type(0.1),
235 depth_type num_depth_levels = std::min(depth_type(17),
237 : TreeMap(std::begin(range), std::end(range), leaf_node_length, num_depth_levels)
238 {
239 }
240
241 TreeMap(TreeMap const&) = default;
242
243 TreeMap(TreeMap&&) = default;
244
245 /**************************************************************************************
246 | |
247 | Destructor |
248 | |
249 **************************************************************************************/
250
251 ~TreeMap() = default;
252
253 /**************************************************************************************
254 | |
255 | Assignment operator |
256 | |
257 **************************************************************************************/
258
259 TreeMap& operator=(TreeMap const&) = default;
260
261 TreeMap& operator=(TreeMap&&) = default;
262
263 /**************************************************************************************
264 | |
265 | Iterators |
266 | |
267 **************************************************************************************/
268
269 [[nodiscard]] iterator begin() { return iterator(this, Base::index()); }
270
271 [[nodiscard]] const_iterator begin() const
272 {
273 return const_iterator(const_cast<TreeMap*>(this), Base::index());
274 }
275
276 [[nodiscard]] const_iterator cbegin() const { return begin(); }
277
278 [[nodiscard]] iterator end() { return iterator(); }
279
280 [[nodiscard]] const_iterator end() const { return const_iterator(); }
281
282 [[nodiscard]] const_iterator cend() const { return end(); }
283
284 /**************************************************************************************
285 | |
286 | Query iterators |
287 | |
288 **************************************************************************************/
289
290 template <class Predicate>
291 [[nodiscard]] query_iterator_pred<Predicate> beginQuery(Predicate const& pred)
292 {
293 return query_iterator_pred<Predicate>(this, Base::index(), pred);
294 }
295
296 template <class Predicate>
297 [[nodiscard]] const_query_iterator_pred<Predicate> beginQuery(
298 Predicate const& pred) const
299 {
300 return const_query_iterator_pred<Predicate>(const_cast<TreeMap*>(this), Base::index(),
301 pred);
302 }
303
304 template <class Predicate>
305 [[nodiscard]] const_query_iterator_pred<Predicate> cbeginQuery(
306 Predicate const& pred) const
307 {
308 return beginQuery(pred);
309 }
310
311 [[nodiscard]] query_iterator endQuery() { return query_iterator(); }
312
313 [[nodiscard]] const_query_iterator endQuery() const { return const_query_iterator(); }
314
315 [[nodiscard]] const_query_iterator cendQuery() const { return endQuery(); }
316
317 /**************************************************************************************
318 | |
319 | Nearest iterators |
320 | |
321 **************************************************************************************/
322
323 template <class Geometry>
324 [[nodiscard]] nearest_iterator_geom<Geometry> beginNearest(Geometry const& query,
325 float epsilon = 0.0f)
326 {
327 return nearest_iterator_geom<Geometry>(this, Base::index(), query, epsilon);
328 }
329
330 template <class Geometry>
331 [[nodiscard]] const_nearest_iterator_geom<Geometry> beginNearest(
332 Geometry const& query, float epsilon = 0.0f) const
333 {
334 return const_nearest_iterator_geom<Geometry>(const_cast<TreeMap*>(this),
335 Base::index(), query, epsilon);
336 }
337
338 template <class Geometry>
339 [[nodiscard]] const_nearest_iterator_geom<Geometry> cbeginNearest(
340 Geometry const& query, float epsilon = 0.0f) const
341 {
342 return beginNearest(query, epsilon);
343 }
344
345 [[nodiscard]] nearest_iterator endNearest() { return nearest_iterator(); }
346
347 [[nodiscard]] const_nearest_iterator endNearest() const
348 {
349 return const_nearest_iterator();
350 }
351
352 [[nodiscard]] const_nearest_iterator cendNearest() const { return endNearest(); }
353
354 /**************************************************************************************
355 | |
356 | Query nearest iterators |
357 | |
358 **************************************************************************************/
359
360 template <class Predicate, class Geometry>
361 [[nodiscard]] query_nearest_iterator_pred_geom<Predicate, Geometry> beginQueryNearest(
362 Predicate const& pred, Geometry const& query, float epsilon = 0.0f)
363 {
365 pred, query, epsilon);
366 }
367
368 template <class Predicate, class Geometry>
370 beginQueryNearest(Predicate const& pred, Geometry const& query,
371 float epsilon = 0.0f) const
372 {
374 const_cast<TreeMap*>(this), Base::index(), pred, query, epsilon);
375 }
376
377 template <class Predicate, class Geometry>
379 cbeginQueryNearest(Predicate const& pred, Geometry const& query,
380 float epsilon = 0.0f) const
381 {
382 return beginQueryNearest(pred, query, epsilon);
383 }
384
385 [[nodiscard]] query_nearest_iterator endQueryNearest()
386 {
387 return query_nearest_iterator();
388 }
389
390 [[nodiscard]] const_query_nearest_iterator endQueryNearest() const
391 {
393 }
394
395 [[nodiscard]] const_query_nearest_iterator cendQueryNearest() const
396 {
397 return endQueryNearest();
398 }
399
400 /**************************************************************************************
401 | |
402 | Capacity |
403 | |
404 **************************************************************************************/
405
411 [[nodiscard]] bool empty() const noexcept { return 0 == size(); }
412
418 [[nodiscard]] size_type size() const noexcept { return size_; }
419
426 [[nodiscard]] Bounds bounds() const { return bounds(Base::index()); }
427
428 /**************************************************************************************
429 | |
430 | Modifiers |
431 | |
432 **************************************************************************************/
433
438 void clear()
439 {
440 Base::clear();
441 size_ = 0;
442 }
443
444 template <class... Args>
445 void emplace(Point point, Args&&... args)
446 {
447 insert(value_type(point, T(std::forward<Args>(args)...)));
448 }
449
450 void insert(value_type const& value)
451 {
452 Index node = Base::create(value.first);
453 insert(node, value);
454 }
455
456 void insert(value_type&& value)
457 {
458 Index node = Base::create(value.first);
459 insert(node, std::move(value));
460 }
461
462 template <class InputIt>
463 void insert(InputIt first, InputIt last)
464 {
465 std::vector<Point> points;
466
467 std::transform(first, last, std::back_inserter(points),
468 [](auto const& v) { return v.first; });
469
470 auto nodes = Base::create(points.begin(), points.end());
471
472 for (std::size_t i{}; first != last; ++i, ++first) {
473 insert(nodes[i], *first);
474 }
475 }
476
477 template <
478 class ExecutionPolicy, class RandomIt,
479 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>, bool> = true>
480 void insert(ExecutionPolicy&& policy, RandomIt first, RandomIt last)
481 {
482 std::vector<Point> points(std::distance(first, last));
483
484 if constexpr (execution::is_stl_v<ExecutionPolicy>) {
485 std::transform(execution::toSTL(policy), first, last, points.begin(),
486 [](auto const& v) { return v.first; });
487 }
488#if defined(UFO_PAR_GCD)
489 else if constexpr (execution::is_gcd_v<ExecutionPolicy>) {
490 // TODO: Implement
491 static_assert(dependent_false_v<ExecutionPolicy>,
492 "insert not implemented for that execution policy");
493 }
494#endif
495#if defined(UFO_PAR_TBB)
496 else if constexpr (execution::is_tbb_v<ExecutionPolicy>) {
497 // TODO: Implement
498 static_assert(dependent_false_v<ExecutionPolicy>,
499 "insert not implemented for that execution policy");
500 }
501#endif
502 else if constexpr (execution::is_omp_v<ExecutionPolicy>) {
503 if constexpr (execution::is_seq_v<ExecutionPolicy>) {
504 for (std::size_t i = 0; points.size() > i; ++i) {
505 points[i] = first[i].first;
506 }
507 } else if constexpr (execution::is_unseq_v<ExecutionPolicy>) {
508#pragma omp simd
509 for (std::size_t i = 0; points.size() > i; ++i) {
510 points[i] = first[i].first;
511 }
512 } else if constexpr (execution::is_par_v<ExecutionPolicy>) {
513#pragma omp parallel for
514 for (std::size_t i = 0; points.size() > i; ++i) {
515 points[i] = first[i].first;
516 }
517 } else if constexpr (execution::is_par_unseq_v<ExecutionPolicy>) {
518#pragma omp parallel for simd
519 for (std::size_t i = 0; points.size() > i; ++i) {
520 points[i] = first[i].first;
521 }
522 }
523 } else {
524 static_assert(dependent_false_v<ExecutionPolicy>,
525 "Not implemented for the execution policy");
526 }
527
528 auto nodes =
529 Base::create(std::forward<ExecutionPolicy>(policy), points.begin(), points.end());
530
531 for (std::size_t i{}; first != last; ++i, ++first) {
532 insert(nodes[i], *first);
533 }
534 }
535
536 void insert(std::initializer_list<value_type> ilist)
537 {
538 insert(ilist.begin(), ilist.end());
539 }
540
541 template <
542 class ExecutionPolicy,
543 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>, bool> = true>
544 void insert(ExecutionPolicy&& policy, std::initializer_list<value_type> ilist)
545 {
546 insert(std::forward<ExecutionPolicy>(policy), ilist.begin(), ilist.end());
547 }
548
549 template <class Range>
550 void insert(Range const& r)
551 {
552 using std::begin;
553 using std::end;
554 insert(begin(r), end(r));
555 }
556
557 template <
558 class ExecutionPolicy, class Range,
559 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>, bool> = true>
560 void insert(ExecutionPolicy&& policy, Range const& r)
561 {
562 using std::begin;
563 using std::end;
564 insert(std::forward<ExecutionPolicy>(policy), begin(r), end(r));
565 }
566
567 size_type erase(value_type const& value)
568 {
569 auto node = Base::index(value.first);
570
571 if (!Base::isPureLeaf(node)) {
572 return 0;
573 }
574
575 auto& v = values(node);
576 size_type num_removed = v.size();
577 v.remove_if([&value](auto const& x) {
578 return x.first == value.first && x.second == value.second;
579 });
580 num_removed -= v.size();
581
582 size_ -= num_removed;
583
584 erasePropagate(node);
585
586 return num_removed;
587 }
588
589 iterator erase(iterator pos)
590 {
591 auto it = pos.iterator();
592 ++pos;
593 erase(it);
594 return pos;
595 }
596
597 iterator erase(const_iterator pos)
598 {
599 auto it = pos.iterator();
600 ++pos;
601 erase(it);
602 return iterator(pos);
603 }
604
605 template <class Predicate>
606 query_iterator_pred<Predicate> erase(query_iterator_pred<Predicate> pos)
607 {
608 auto it = pos.iterator();
609 ++pos;
610 erase(it);
611 return pos;
612 }
613
614 template <class Predicate>
615 query_iterator_pred<Predicate> erase(const_query_iterator_pred<Predicate> pos)
616 {
617 auto it = pos.iterator();
618 ++pos;
619 erase(it);
620 return query_iterator_pred<Predicate>(pos);
621 }
622
623 template <class Geometry>
624 nearest_iterator_geom<Geometry> erase(nearest_iterator_geom<Geometry> pos)
625 {
626 auto it = pos.iterator();
627 ++pos;
628 erase(it);
629 return pos;
630 }
631
632 template <class Geometry>
633 nearest_iterator_geom<Geometry> erase(const_nearest_iterator_geom<Geometry> pos)
634 {
635 auto it = pos.iterator();
636 ++pos;
637 erase(it);
638 return nearest_iterator_geom<Geometry>(pos);
639 }
640
641 template <class Predicate, class Geometry>
642 query_nearest_iterator_pred_geom<Predicate, Geometry> erase(
643 query_nearest_iterator_pred_geom<Predicate, Geometry> pos)
644 {
645 auto it = pos.iterator();
646 ++pos;
647 erase(it);
648 return pos;
649 }
650
651 template <class Predicate, class Geometry>
652 query_nearest_iterator_pred_geom<Predicate, Geometry> erase(
653 const_query_nearest_iterator_pred_geom<Predicate, Geometry> pos)
654 {
655 auto it = pos.iterator();
656 ++pos;
657 erase(it);
658 return query_nearest_iterator_pred_geom<Predicate, Geometry>(pos);
659 }
660
661 iterator erase(iterator first, iterator last)
662 {
663 while (last != first) {
664 auto it = first.iterator();
665 ++first;
666 erase(it);
667 }
668 return first;
669 }
670
671 iterator erase(const_iterator first, const_iterator last)
672 {
673 while (last != first) {
674 auto it = first.iterator();
675 ++first;
676 erase(it);
677 }
678 return iterator(first);
679 }
680
681 template <class Predicate1, class Predicate2>
682 query_iterator_pred<Predicate1> erase(query_iterator_pred<Predicate1> first,
683 query_iterator_pred<Predicate2> last)
684 {
685 while (last != first) {
686 auto it = first.iterator();
687 ++first;
688 erase(it);
689 }
690 return first;
691 }
692
693 template <class Predicate1, class Predicate2>
694 query_iterator_pred<Predicate1> erase(const_query_iterator_pred<Predicate1> first,
695 const_query_iterator_pred<Predicate2> last)
696 {
697 while (last != first) {
698 auto it = first.iterator();
699 ++first;
700 erase(it);
701 }
702 return query_iterator_pred<Predicate1>(first);
703 }
704
705 template <class Predicate>
706 query_iterator_pred<Predicate> erase(Query<Predicate> query)
707 {
708 return erase(query.begin(), query.end());
709 }
710
711 template <class Predicate>
712 query_iterator_pred<Predicate> erase(ConstQuery<Predicate> query)
713 {
714 return erase(query.begin(), query.end());
715 }
716
717 template <class Geometry1, class Geometry2>
718 nearest_iterator_geom<Geometry1> erase(nearest_iterator_geom<Geometry1> first,
719 nearest_iterator_geom<Geometry2> last)
720 {
721 while (last != first) {
722 auto it = first.iterator();
723 ++first;
724 erase(it);
725 }
726 return first;
727 }
728
729 template <class Geometry1, class Geometry2>
730 nearest_iterator_geom<Geometry1> erase(const_nearest_iterator_geom<Geometry1> first,
731 const_nearest_iterator_geom<Geometry2> last)
732 {
733 while (last != first) {
734 auto it = first.iterator();
735 ++first;
736 erase(it);
737 }
738 return nearest_iterator_geom<Geometry1>(first);
739 }
740
741 template <class Predicate1, class Geometry1, class Predicate2, class Geometry2>
742 query_nearest_iterator_pred_geom<Predicate1, Geometry1> erase(
743 query_nearest_iterator_pred_geom<Predicate1, Geometry1> first,
744 query_nearest_iterator_pred_geom<Predicate2, Geometry2> last)
745 {
746 while (last != first) {
747 auto it = first.iterator();
748 ++first;
749 erase(it);
750 }
751 return first;
752 }
753
754 template <class Predicate1, class Geometry1, class Predicate2, class Geometry2>
755 query_nearest_iterator_pred_geom<Predicate1, Geometry1> erase(
756 const_query_nearest_iterator_pred_geom<Predicate1, Geometry1> first,
757 const_query_nearest_iterator_pred_geom<Predicate2, Geometry2> last)
758 {
759 while (last != first) {
760 auto it = first.iterator();
761 ++first;
762 erase(it);
763 }
764 return query_nearest_iterator_pred_geom<Predicate1, Geometry1>(first);
765 }
766
767 template <class Predicate, class Geometry>
768 query_nearest_iterator_pred_geom<Predicate, Geometry> erase(
769 QueryNearest<Predicate, Geometry> query)
770 {
771 return erase(query.begin(), query.end());
772 }
773
774 template <class Predicate, class Geometry>
775 query_nearest_iterator_pred_geom<Predicate, Geometry> erase(
776 ConstQueryNearest<Predicate, Geometry> query)
777 {
778 return erase(query.begin(), query.end());
779 }
780
781 size_type erase(Point point)
782 {
783 auto node = Base::index(point);
784
785 if (!Base::isPureLeaf(node)) {
786 return 0;
787 }
788
789 auto& v = values(node);
790 size_type num_removed = v.size();
791 v.remove_if([point](auto const& x) { return x.first == point; });
792 num_removed -= v.size();
793
794 size_ -= num_removed;
795
796 erasePropagate(node);
797
798 return num_removed;
799 }
800
806 void swap(TreeMap& other)
807 {
808 std::swap(size_, other.size_);
809 std::swap(static_cast<Base&>(*this), static_cast<Base&>(other));
810 }
811
812 /**************************************************************************************
813 | |
814 | Lookup |
815 | |
816 **************************************************************************************/
817
825 [[nodiscard]] size_type count(Point point) const
826 {
827 auto const& v = values(Base::index(point));
828 return std::count_if(v.begin(), v.end(),
829 [point](auto const& x) { return x.first == point; });
830 }
831
839 [[nodiscard]] bool contains(Point point) const
840 {
841 auto const& v = values(Base::index(point));
842 return std::end(v) != std::find_if(v.begin(), v.end(), [point](auto const& x) {
843 return x.first == point;
844 });
845 }
846
847 template <class Predicate>
848 [[nodiscard]] Query<Predicate> query(Predicate const& pred)
849 {
850 return Query<Predicate>(beginQuery(pred), endQuery());
851 }
852
853 template <class Predicate>
854 [[nodiscard]] ConstQuery<Predicate> query(Predicate const& pred) const
855 {
856 return ConstQuery<Predicate>(beginQuery(pred), endQuery());
857 }
858
859 template <class Geometry>
860 [[nodiscard]] Nearest<Geometry> nearest(Geometry const& query, float epsilon = 0.0f)
861 {
862 return Nearest<Geometry>(beginNearest(query, epsilon), endNearest());
863 }
864
865 template <class Geometry>
866 [[nodiscard]] ConstNearest<Geometry> nearest(Geometry const& query,
867 float epsilon = 0.0f) const
868 {
869 return ConstNearest<Geometry>(beginNearest(query, epsilon), endNearest());
870 }
871
872 template <class Predicate, class Geometry>
873 [[nodiscard]] QueryNearest<Predicate, Geometry> queryNearest(Predicate const& pred,
874 Geometry const& query,
875 float epsilon = 0.0f)
876 {
877 return QueryNearest<Predicate, Geometry>(beginQueryNearest(pred, query, epsilon),
878 endQueryNearest());
879 }
880
881 template <class Predicate, class Geometry>
882 [[nodiscard]] ConstQueryNearest<Predicate, Geometry> queryNearest(
883 Predicate const& pred, Geometry const& query, float epsilon = 0.0f) const
884 {
885 return ConstQueryNearest<Predicate, Geometry>(beginQueryNearest(pred, query, epsilon),
886 endQueryNearest());
887 }
888
889 template <class Geometry>
890 [[nodiscard]] float nearestDistance(
891 Geometry const& query, float max_distance = std::numeric_limits<float>::infinity(),
892 float epsilon = 0.0f,
893 NearestSearchAlgorithm search_alg = NearestSearchAlgorithm::DEPTH_FIRST) const
894 {
895 float max_distance_sq = max_distance * max_distance;
896 float dist_sq =
897 Base::nearest(
898 Base::index(), search_alg,
899 [this, &query](Index node) {
900 float dist_sq = std::numeric_limits<float>::infinity();
901 for (auto e : values(node)) {
902 dist_sq = UFO_MIN(dist_sq, distanceSquared(query, e.first));
903 }
904 return dist_sq;
905 },
906 [this, &query](Index node) { return distanceSquared(query, bounds(node)); },
907 max_distance_sq, epsilon * epsilon)
908 .first;
909
910 return max_distance_sq <= dist_sq ? max_distance : std::sqrt(dist_sq);
911 }
912
913 template <class Geometry>
914 [[nodiscard]] std::pair<value_type*, float> nearestPoint(
915 Geometry const& query, float max_distance = std::numeric_limits<float>::infinity(),
916 float epsilon = 0.0f,
917 NearestSearchAlgorithm search_alg = NearestSearchAlgorithm::DEPTH_FIRST)
918 {
919 float max_distance_sq = max_distance * max_distance;
920 auto [dist_sq, node] = Base::nearest(
921 Base::index(), search_alg,
922 [this, &query](Index node) {
923 float dist_sq = std::numeric_limits<float>::infinity();
924 for (auto e : values(node)) {
925 dist_sq = UFO_MIN(dist_sq, distanceSquared(query, e.first));
926 }
927 return dist_sq;
928 },
929 [this, &query](Index node) { return distanceSquared(query, bounds(node)); },
930 max_distance_sq, epsilon * epsilon);
931
932 value_type* value = nullptr;
933
934 for (auto& e : values(node)) {
935 value = distanceSquared(query, e.first) == dist_sq ? &e : nullptr;
936 }
937
938 return {value, max_distance_sq <= dist_sq ? max_distance : std::sqrt(dist_sq)};
939 }
940
941 template <class Geometry>
942 [[nodiscard]] std::pair<value_type const*, float> nearestPoint(
943 Geometry const& query, float max_distance = std::numeric_limits<float>::infinity(),
944 float epsilon = 0.0f,
945 NearestSearchAlgorithm search_alg = NearestSearchAlgorithm::DEPTH_FIRST) const
946 {
947 float max_distance_sq = max_distance * max_distance;
948 auto [dist_sq, node] = Base::nearest(
949 Base::index(), search_alg,
950 [this, &query](Index node) {
951 float dist_sq = std::numeric_limits<float>::infinity();
952 for (auto e : values(node)) {
953 dist_sq = UFO_MIN(dist_sq, distanceSquared(query, e.first));
954 }
955 return dist_sq;
956 },
957 [this, &query](Index node) { return distanceSquared(query, bounds(node)); },
958 max_distance_sq, epsilon * epsilon);
959
960 value_type const* value = nullptr;
961
962 for (auto const& e : values(node)) {
963 value = distanceSquared(query, e.first) == dist_sq ? &e : nullptr;
964 }
965
966 return {value, max_distance_sq <= dist_sq ? max_distance : std::sqrt(dist_sq)};
967 }
968
969 /**************************************************************************************
970 | |
971 | Bounds |
972 | |
973 **************************************************************************************/
974
982 template <class NodeType,
983 std::enable_if_t<Base::template is_node_type_v<NodeType>, bool> = true>
984 [[nodiscard]] Bounds& bounds(NodeType node)
985 {
987 return Base::treeBlock(n).bounds[n.offset];
988 }
989
997 template <class NodeType,
998 std::enable_if_t<Base::template is_node_type_v<NodeType>, bool> = true>
999 [[nodiscard]] Bounds const& bounds(NodeType node) const
1000 {
1002 return Base::treeBlock(n).bounds[n.offset];
1003 }
1004
1005 /**************************************************************************************
1006 | |
1007 | Compare |
1008 | |
1009 **************************************************************************************/
1010
1011 template <std::size_t D, class U>
1012 friend bool operator==(TreeMap<D, U> const& lhs, TreeMap<D, U> const& rhs);
1013
1014 template <std::size_t D, class U>
1015 friend bool operator!=(TreeMap<D, U> const& lhs, TreeMap<D, U> const& rhs);
1016
1017 protected:
1018 /**************************************************************************************
1019 | |
1020 | Functions 'Tree" expect |
1021 | |
1022 **************************************************************************************/
1023
1024 void onInitRoot() {}
1025
1026 void onInitChildren(Index /* node */, pos_type /* children */) {}
1027
1028 void onPruneChildren(Index /* node */, pos_type /* children */) {}
1029
1030 /**************************************************************************************
1031 | |
1032 | Capacity |
1033 | |
1034 **************************************************************************************/
1035
1042 [[nodiscard]] bool empty(Index node) const noexcept
1043 {
1044 return boundsMin(node)[0] > boundsMax(node)[0];
1045 }
1046
1047 /**************************************************************************************
1048 | |
1049 | Modifiers |
1050 | |
1051 **************************************************************************************/
1052
1053 void insert(Index node, value_type const& value)
1054 {
1055 Point p = value.first;
1056 values(node).push_back(value);
1057 ++size_;
1058
1059 insertPropagate(node, p);
1060 }
1061
1062 void insert(Index node, value_type&& value)
1063 {
1064 Point p = value.first;
1065 values(node).push_back(std::move(value));
1066 ++size_;
1067
1068 insertPropagate(node, p);
1069 }
1070
1071 void insertPropagate(Index node, Point p)
1072 {
1073 // Propagate
1074 auto root_depth = Base::depth();
1075 auto depth = Base::depth(node);
1076 for (; root_depth > depth; ++depth) {
1077 Point& min = boundsMin(node);
1078 Point& max = boundsMax(node);
1079 min = ufo::min(min, p);
1080 max = ufo::max(max, p);
1081 node = Base::parent(node);
1082 }
1083
1084 // Root
1085 Point& min = boundsMin(node);
1086 Point& max = boundsMax(node);
1087 min = ufo::min(min, p);
1088 max = ufo::max(max, p);
1089 }
1090
1091 void erase(typename container_type::const_iterator it)
1092 {
1093 auto node = Base::index(it->first);
1094
1095 if (!Base::isPureLeaf(node)) {
1096 return;
1097 }
1098
1099 auto& v = values(node);
1100 v.erase(it);
1101 --size_;
1102
1103 erasePropagate(node);
1104 }
1105
1106 void erasePropagate(Index node)
1107 {
1108 Point min(std::numeric_limits<typename Point::value_type>::max());
1109 Point max(std::numeric_limits<typename Point::value_type>::lowest());
1110 for (auto const& [p, _] : values(node)) {
1111 min = ufo::min(min, p);
1112 max = ufo::max(max, p);
1113 }
1114 boundsMin(node) = min;
1115 boundsMax(node) = max;
1116
1117 if (Base::isRoot(node)) {
1118 return;
1119 }
1120
1121 auto root_depth = Base::depth();
1122 auto child_block = node.pos;
1123 node = Base::parent(node);
1124 auto depth = Base::depth(node);
1125 for (; root_depth > depth; ++depth) {
1126 Point min = boundsMin(Index(child_block, 0));
1127 Point max = boundsMax(Index(child_block, 0));
1128 for (std::size_t i = 1; Base::BF > i; ++i) {
1129 min = ufo::min(min, boundsMin(Index(child_block, i)));
1130 max = ufo::max(max, boundsMax(Index(child_block, i)));
1131 }
1132 boundsMin(node) = min;
1133 boundsMax(node) = max;
1134 child_block = node.pos;
1135 node = Base::parent(node);
1136 }
1137
1138 // Root
1139 min = boundsMin(Index(child_block, 0));
1140 max = boundsMax(Index(child_block, 0));
1141 for (std::size_t i = 1; Base::BF > i; ++i) {
1142 min = ufo::min(min, boundsMin(Index(child_block, i)));
1143 max = ufo::max(max, boundsMax(Index(child_block, i)));
1144 }
1145 boundsMin(node) = min;
1146 boundsMax(node) = max;
1147 }
1148
1149 /**************************************************************************************
1150 | |
1151 | Internal data |
1152 | |
1153 **************************************************************************************/
1154
1155 [[nodiscard]] auto& values(pos_type block) { return Base::treeBlock(block).values; }
1156
1157 [[nodiscard]] auto const& values(pos_type block) const
1158 {
1159 return Base::treeBlock(block).values;
1160 }
1161
1162 [[nodiscard]] auto& values(Index node)
1163 {
1164 return Base::treeBlock(node).values[node.offset];
1165 }
1166
1167 [[nodiscard]] auto const& values(Index node) const
1168 {
1169 return Base::treeBlock(node).values[node.offset];
1170 }
1171
1180 [[nodiscard]] Point& boundsMin(Index node)
1181 {
1182 return Base::treeBlock(node).bounds[node.offset].min;
1183 }
1184
1193 [[nodiscard]] Point boundsMin(Index node) const
1194 {
1195 return Base::treeBlock(node).bounds[node.offset].min;
1196 }
1197
1206 [[nodiscard]] Point& boundsMax(Index node)
1207 {
1208 return Base::treeBlock(node).bounds[node.offset].max;
1209 }
1210
1219 [[nodiscard]] Point boundsMax(Index node) const
1220 {
1221 return Base::treeBlock(node).bounds[node.offset].max;
1222 }
1223
1224 protected:
1225 size_type size_{};
1226};
1227
1228//
1229// Compare
1230//
1231
1232template <std::size_t Dim, class T>
1233bool operator==(TreeMap<Dim, T> const& lhs, TreeMap<Dim, T> const& rhs)
1234{
1235 using Base = typename TreeMap<Dim, T>::Base;
1236
1237 Base const& lhs_b = static_cast<Base const&>(lhs);
1238 Base const& rhs_b = static_cast<Base const&>(rhs);
1239
1240 return std::equal(lhs_b.begin(), lhs_b.end(), rhs_b.begin(), rhs_b.end(),
1241 [&lhs, &rhs](auto const& l, auto const& r) {
1242 auto lc = l.code;
1243 auto rc = r.code;
1244 auto const& lv = lhs.values(l.index);
1245 auto const& rv = rhs.values(r.index);
1246
1247 return lc == rc && std::is_permutation(lv.begin(), lv.end(),
1248 rv.begin(), rv.end());
1249 });
1250}
1251
1252template <std::size_t Dim, class T>
1253bool operator!=(TreeMap<Dim, T> const& lhs, TreeMap<Dim, T> const& rhs)
1254{
1255 return !(lhs == rhs);
1256}
1257
1258template <class T>
1259using BinaryTreeMap = TreeMap<1, T>;
1260
1261template <class T>
1262using QuadtreeMap = TreeMap<2, T>;
1263
1264template <class T>
1265using OctreeMap = TreeMap<3, T>;
1266
1267template <class T>
1268using HextreeMap = TreeMap<4, T>;
1269} // namespace ufo
1270
1271#endif // UFO_CONTAINER_TREE_MAP_HPP
Point & boundsMin(Index node)
Returns the minimum point of the Bounds able to contain all values stored in the node and all of its ...
void clear()
Erases all elements from the container. After this call, size() returns zero.
Definition tree_map.hpp:438
bool empty(Index node) const noexcept
Checks if the node and none of its children have any elements.
size_type count(Point point) const
Returns the number of elements with Point that compares equivalent to the specified argument.
Definition tree_map.hpp:825
Point boundsMin(Index node) const
Returns the minimum point of the Bounds able to contain all values stored in the node and all of its ...
size_type size() const noexcept
Returns the number of elements in the container.
Definition tree_map.hpp:418
Bounds const & bounds(NodeType node) const
Returns the minimum Bounds able to contain all values stored in the node and all of its children.
Definition tree_map.hpp:999
bool contains(Point point) const
Checks if there is an element with Point equivalent to point in the container.
Definition tree_map.hpp:839
bool empty() const noexcept
Checks if the container has no elements.
Definition tree_map.hpp:411
Point & boundsMax(Index node)
Returns the maximum point of the Bounds able to contain all values stored in the node and all of its ...
Point boundsMax(Index node) const
Returns the maximum point of the Bounds able to contain all values stored in the node and all of its ...
Bounds & bounds(NodeType node)
Returns the minimum Bounds able to contain all values stored in the node and all of its children.
Definition tree_map.hpp:984
void swap(TreeMap &other)
Exchanges the contents of the container with those of other.
Definition tree_map.hpp:806
Bounds bounds() const
Returns the minimum Bounds able to contain all values stored in the container.
Definition tree_map.hpp:426
Utilizing curiously recurring template pattern (CRTP)
Definition tree.hpp:104
constexpr pos_type block() const noexcept
Returns the block position of the root node.
Definition tree.hpp:743
bool isPureLeaf(pos_type block) const
Checks if the block is pure leaf (i.e., can never have children).
Definition tree.hpp:1256
depth_type depth() const
Returns the depth of the root node, i.e. numDepthLevels() - 1.
Definition tree.hpp:290
constexpr Index index() const noexcept
Returns the index of the root node.
Definition tree.hpp:803
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 depth_type maxNumDepthLevels() noexcept
Returns the maximum number of depth levels a tree can have.
Definition tree.hpp:278
Node node() const
Returns the root node.
Definition tree.hpp:843
Point min() const
Returns the minimum point of the tree (/ root node).
Definition tree.hpp:514
void clear()
Erases all nodes from the tree.
Definition tree.hpp:234
Point max() const
Returns the maximum point of the tree (/ root node).
Definition tree.hpp:533
All vision-related classes and functions.
Definition cloud.hpp:49
constexpr auto distanceSquared(A const &a, B const &b)
Computes the minimum squared distance between two shapes.
Definition distance.hpp:80
constexpr Vec< Geometry::dimension(), typename Geometry::value_type > max(Geometry const &g)
Returns the maximum coordinate of the minimum spanning axis-aligned bounding box of a geometry.
Definition fun.hpp:72
constexpr Vec< Geometry::dimension(), typename Geometry::value_type > min(Geometry const &g)
Returns the minimum coordinate of the minimum spanning axis-aligned bounding box of a geometry.
Definition fun.hpp:58
Axis-Aligned Bounding Box (AABB) in Dim-dimensional space.
Definition aabb.hpp:70
Represents a closed interval [lower, upper] of a scalar type.
Definition range.hpp:66