UFO 1.0.0
An Efficient Probabilistic 3D Mapping Framework That Embraces the Unknown
Loading...
Searching...
No Matches
tree.hpp
1
42#ifndef UFO_CONTAINER_TREE_HPP
43#define UFO_CONTAINER_TREE_HPP
44
45// UFO
46#include <ufo/container/tree/block.hpp>
47#include <ufo/container/tree/code.hpp>
48#include <ufo/container/tree/container.hpp>
49#include <ufo/container/tree/coord.hpp>
50#include <ufo/container/tree/data.hpp>
51#include <ufo/container/tree/index.hpp>
52#include <ufo/container/tree/iterator.hpp>
53#include <ufo/container/tree/key.hpp>
54#include <ufo/container/tree/nearest_iterator.hpp>
55#include <ufo/container/tree/node.hpp>
56#include <ufo/container/tree/predicate.hpp>
57#include <ufo/container/tree/query_iterator.hpp>
58#include <ufo/container/tree/query_nearest_iterator.hpp>
59#include <ufo/container/tree/trace_result.hpp>
60#include <ufo/execution/algorithm.hpp>
61#include <ufo/execution/execution.hpp>
62#include <ufo/geometry/aabb.hpp>
63#include <ufo/geometry/ray.hpp>
64#include <ufo/numeric/math.hpp>
65#include <ufo/numeric/vec.hpp>
66#include <ufo/utility/bit_set.hpp>
67#include <ufo/utility/io/buffer.hpp>
68#include <ufo/utility/iterator_wrapper.hpp>
69#include <ufo/utility/macros.hpp>
70#include <ufo/utility/type_traits.hpp>
71
72// STL
73#include <algorithm>
74#include <array>
75#include <atomic>
76#include <bit>
77#include <cassert>
78#include <cmath>
79#include <cstddef>
80#include <deque>
81#include <iterator>
82#include <optional>
83#include <sstream>
84#include <string>
85#include <type_traits>
86#include <utility>
87#include <vector>
88
89namespace ufo
90{
91enum class NearestSearchAlgorithm { DEPTH_FIRST, A_STAR };
92
102template <class Derived, std::size_t Dim, class... Blocks>
103class Tree : public TreeData<Derived, Dim, TreeBlock, Blocks...>
104{
105 protected:
106 //
107 // Friends
108 //
109
110 friend Derived;
111
112 using Data = TreeData<Derived, Dim, TreeBlock, Blocks...>;
113
114 static constexpr TreeIndex::offset_type const BF = Data::BF;
115
116 using LeafBlock = typename TreeBlock::LeafBlock<Dim, BF>;
117 using InnerBlock = typename TreeBlock::InnerBlock<Dim, BF>;
118
119 using modified_type = typename LeafBlock::modified_type;
120
121 static constexpr modified_type const MODIFIED_ALL_SET =
122 static_cast<modified_type>(~(~0u << BF));
123 static constexpr modified_type const MODIFIED_NONE_SET = {};
124
125 public:
126 //
127 // Tags
128 //
129
130 using coord_type = float;
131 using length_type = double;
132 using depth_type = std::uint32_t;
133
134 using Index = TreeIndex;
135 using Node = TreeNode<Dim>;
136 using Code = TreeCode<Dim>;
137 using Key = TreeKey<Dim>;
144
145 using pos_type = typename Index::pos_type;
146 using offset_type = typename Index::offset_type;
147 using code_type = typename Code::code_type;
148 using key_type = typename Key::key_type;
149
150 // Iterators
151
153
154 template <class Predicate>
157
158 template <class Geometry>
161
162 template <class Predicate, class Geometry>
166
167 template <class Predicate>
168 using ConstQuery =
169 IteratorWrapper<const_query_iterator_pred<Predicate>, const_query_iterator>;
170
171 template <class Geometry>
172 using ConstNearest =
173 IteratorWrapper<const_nearest_iterator_geom<Geometry>, const_nearest_iterator>;
174
175 template <class Predicate, class Geometry>
176 using ConstQueryNearest =
177 IteratorWrapper<const_query_nearest_iterator_pred_geom<Predicate, Geometry>,
179
180 template <class T>
182 : std::disjunction<
183 contains_convertible_type<remove_cvref_t<T>, Index, Node, Code, Key, Coord>,
184 std::is_constructible<remove_cvref_t<T>, Coord>> {
185 };
186
187 template <class T>
188 static constexpr inline bool const is_node_type_v = is_node_type<T>::value;
189
190 public:
191 /**************************************************************************************
192 | |
193 | Tree |
194 | |
195 **************************************************************************************/
196
203 [[nodiscard]] static constexpr offset_type branchingFactor() noexcept { return BF; }
204
211 [[nodiscard]] static constexpr std::size_t dimensions() noexcept { return Dim; }
212
218 [[nodiscard]] std::size_t size() const
219 {
220 // Num. blocks * branching factor - (root block only has one usable node, remove rest)
221 return Data::size() * BF - (BF - 1);
222 }
223
229 void reserve(std::size_t num_nodes) { Data::reserve((num_nodes + BF - 1) / BF); }
230
234 void clear()
235 {
236 Data::clear();
237 createRoot();
238 derived().onInitRoot();
239 }
240
241 void clear(Length const& leaf_node_length, depth_type num_depth_levels)
242 {
243 init(leaf_node_length, num_depth_levels);
244 clear();
245 }
246
247 void clear(length_type const& leaf_node_length, depth_type num_depth_levels)
248 {
249 clear(Length(leaf_node_length), num_depth_levels);
250 }
251
252 //
253 // Depth
254 //
255
261 [[nodiscard]] constexpr depth_type numDepthLevels() const noexcept
262 {
263 return num_depth_levels_;
264 }
265
271 [[nodiscard]] static constexpr depth_type minNumDepthLevels() noexcept { return 2; }
272
278 [[nodiscard]] static constexpr depth_type maxNumDepthLevels() noexcept
279 {
280 return Code::maxDepth() + 1;
281 }
282
290 [[nodiscard]] depth_type depth() const { return numDepthLevels() - 1; }
291
300 [[nodiscard]] depth_type depth(pos_type block) const
301 {
302 return static_cast<depth_type>(isPureLeaf(block) ? 0u : treeInnerBlock(block).depth);
303 }
304
313 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
314 [[nodiscard]] constexpr depth_type depth(NodeType node) const
315 {
316 using T = remove_cvref_t<NodeType>;
317 if constexpr (std::is_same_v<T, Index>) {
318 return depth(node.pos);
319 } else if constexpr (std::is_same_v<T, Node>) {
320 return depth(node.code);
321 } else if constexpr (std::is_same_v<T, Code>) {
322 return node.depth();
323 } else if constexpr (std::is_same_v<T, Key>) {
324 return node.depth();
325 } else if constexpr (std::is_same_v<T, Coord>) {
326 return node.depth;
327 } else {
328 return depth(convert(node));
329 }
330 }
331
332 //
333 // Length
334 //
335
342 [[nodiscard]] Length length() const { return length(depth()); }
343
353 [[nodiscard]] Length length(depth_type depth) const
354 {
355 assert(numDepthLevels() > depth);
356 return node_half_length_[depth + 1];
357 }
358
365 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
366 [[nodiscard]] Length length(NodeType node) const
367 {
368 return length(depth(node));
369 }
370
379 [[nodiscard]] Length halfLength() const { return halfLength(depth()); }
380
392 [[nodiscard]] Length halfLength(depth_type depth) const
393 {
394 assert(numDepthLevels() > depth);
395 return node_half_length_[depth];
396 }
397
407 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
408 [[nodiscard]] constexpr Length halfLength(NodeType node) const
409 {
410 return halfLength(depth(node));
411 }
412
422 [[nodiscard]] Length lengthReciprocal() const { return lengthReciprocal(depth()); }
423
436 [[nodiscard]] Length lengthReciprocal(depth_type depth) const
437 {
438 assert(numDepthLevels() > depth + 1);
439 return node_half_length_reciprocal_[depth + 1];
440 }
441
451 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
452 [[nodiscard]] Length lengthReciprocal(NodeType node) const
453 {
454 return lengthReciprocal(depth(node));
455 }
456
466 [[nodiscard]] Length halfLengthReciprocal() const
467 {
468 return halfLengthReciprocal(depth());
469 }
470
483 [[nodiscard]] Length halfLengthReciprocal(depth_type depth) const
484 {
485 assert(numDepthLevels() > depth);
486 return node_half_length_reciprocal_[depth];
487 }
488
499 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
500 [[nodiscard]] Length halfLengthReciprocal(NodeType node) const
501 {
503 }
504
505 //
506 // Min/max/bounds
507 //
508
514 [[nodiscard]] Point min() const { return center() - cast<coord_type>(halfLength()); }
515
522 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
523 [[nodiscard]] Point min(NodeType node) const
524 {
525 return center(node) - cast<coord_type>(halfLength(node));
526 }
527
533 [[nodiscard]] Point max() const
534 {
535 Point c = center();
536 Point p = c + cast<coord_type>(halfLength());
537 // NOTE: Decrease with minimum step so `isInside` is consitent with this.
538 for (std::size_t i{}; p.size() > i; ++i) {
539 p[i] = std::nextafter(p[i], c[i]);
540 }
541 return c;
542 }
543
550 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
551 [[nodiscard]] Point max(NodeType node) const
552 {
553 Point c = center(node);
554 Point p = c + cast<coord_type>(halfLength(node));
555 // NOTE: Decrease with minimum step so `isInside` is consitent with this.
556 for (std::size_t i{}; p.size() > i; ++i) {
557 p[i] = std::nextafter(p[i], c[i]);
558 }
559 return c;
560 }
561
567 [[nodiscard]] Bounds bounds() const
568 {
569 Point c = center();
570 auto hl = cast<coord_type>(halfLength());
571 auto min = c - hl;
572 auto max = c + hl;
573 // NOTE: Decrease max with minimum step so `isInside` is consitent with this.
574 for (std::size_t i{}; max.size() > i; ++i) {
575 max[i] = std::nextafter(max[i], c[i]);
576 }
577 return Bounds(min, max);
578 }
579
586 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
587 [[nodiscard]] Bounds bounds(NodeType node) const
588 {
589 Point c = center(node);
590 auto hl = cast<coord_type>(halfLength(node));
591 auto min = c - hl;
592 auto max = c + hl;
593 // NOTE: Decrease max with minimum step so `isInside` is consitent with this.
594 for (std::size_t i{}; max.size() > i; ++i) {
595 max[i] = std::nextafter(max[i], c[i]);
596 }
597 return Bounds(min, max);
598 }
599
600 //
601 // Inside
602 //
603
610 [[nodiscard]] bool isInside(Point coord) const
611 {
612 // NOTE: This assumes that origin is at zero
613 auto const hl = halfLength();
614 for (std::size_t i{}; coord.size() > i; ++i) {
615 if (-hl[i] > coord[i] || hl[i] <= coord[i]) {
616 return false;
617 }
618 }
619 return true;
620 }
621
622 /**************************************************************************************
623 | |
624 | Access |
625 | |
626 **************************************************************************************/
627
628 //
629 // Center
630 //
631
637 [[nodiscard]] Coord center() const { return Coord(Point(), depth()); }
638
645 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
646 [[nodiscard]] constexpr Coord center(NodeType node) const
647 {
648 using T = remove_cvref_t<NodeType>;
649 if constexpr (std::is_same_v<T, Key>) {
650 assert(valid(node));
651
652 auto node_depth = depth(node);
653
654 if (depth() == node_depth) {
655 return center();
656 }
657
658 // LOOKAT: Check performance, might be a lot faster to have float here and in rest
659 // of method
660 Length l = length(node_depth);
661 std::int_fast64_t hmv =
662 static_cast<std::int_fast64_t>(half_max_value_ >> node_depth);
663
664 Point coord =
665 cast<coord_type>((cast<length_type>(cast<std::int_fast64_t>(node) - hmv) +
666 static_cast<length_type>(0.5)) *
667 l);
668
669 return Coord(coord, node_depth);
670 } else {
671 return center(key(node));
672 }
673 }
674
681 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
682 [[nodiscard]] std::optional<Coord> centerChecked(NodeType node) const
683 {
684 return valid(node) ? std::optional<Coord>(center(node)) : std::nullopt;
685 }
686
687 //
688 // Center axis
689 //
690
697 [[nodiscard]] coord_type centerAxis(std::size_t axis) const
698 {
699 assert(Dim > axis);
700 return center()[axis];
701 }
702
710 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
711 [[nodiscard]] coord_type centerAxis(NodeType node, std::size_t axis) const
712 {
713 assert(Dim > axis);
714 return center(node)[axis];
715 }
716
726 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
727 [[nodiscard]] std::optional<coord_type> centerAxisChecked(NodeType node,
728 std::size_t axis) const
729 {
730 assert(Dim > axis);
731 return valid(node) ? std::optional<coord_type>(centerAxis(node, axis)) : std::nullopt;
732 }
733
734 //
735 // Block
736 //
737
743 [[nodiscard]] constexpr pos_type block() const noexcept
744 {
745 return Data::addInnerType(0);
746 }
747
755 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
756 [[nodiscard]] pos_type block(NodeType node) const
757 {
758 return index(node).pos;
759 }
760
761 //
762 // Offset
763 //
764
770 [[nodiscard]] constexpr offset_type offset() const noexcept { return 0; }
771
779 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
780 [[nodiscard]] offset_type offset(NodeType node) const
781 {
782 using T = remove_cvref_t<NodeType>;
783 if constexpr (std::is_same_v<T, Index>) {
784 return node.offset;
785 } else if constexpr (std::is_same_v<T, Node>) {
786 return offset(code(node));
787 } else if constexpr (contains_type_v<T, Code, Key>) {
788 return node.offset();
789 } else {
790 return offset(key(node));
791 }
792 }
793
794 //
795 // Index
796 //
797
803 [[nodiscard]] constexpr Index index() const noexcept
804 {
805 return Index(block(), offset());
806 }
807
808 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
809 [[nodiscard]] constexpr Index index(NodeType node) const
810 {
811 assert(valid(node));
812
813 using T = remove_cvref_t<NodeType>;
814 if constexpr (std::is_same_v<T, Index>) {
815 return node;
816 } else if constexpr (std::is_same_v<T, Code>) {
817 Index n = index();
818 depth_type const min_depth = depth(node);
819 for (depth_type d = depth(); min_depth < d; --d) {
820 Index c = child(n, node.offset(d - 1));
821 if (!valid(c.pos)) {
822 return n;
823 }
824 n = c;
825 }
826 return n;
827 } else if constexpr (contains_type_v<T, Node, Key, Coord>) {
828 return index(code(node));
829 } else {
830 return index(convert(node));
831 }
832 }
833
834 //
835 // Node
836 //
837
843 [[nodiscard]] Node node() const { return Node(code(), index()); }
844
851 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
852 [[nodiscard]] Node node(NodeType node) const
853 {
854 using T = remove_cvref_t<NodeType>;
855 if constexpr (std::is_same_v<T, Index>) {
856 return Node(code(node), node);
857 } else if constexpr (std::is_same_v<T, Node>) {
858 return Node(node.code, index(node));
859 } else if constexpr (std::is_same_v<T, Code>) {
860 return Node(node, index(node));
861 } else if constexpr (contains_type_v<T, Key, Coord>) {
862 return this->node(code(node));
863 } else {
864 return this->node(convert(node));
865 }
866 }
867
881 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
882 [[nodiscard]] Node operator[](NodeType node) const
883 {
884 return this->node(node);
885 }
886
887 //
888 // Code
889 //
890
891 [[nodiscard]] Code code() const { return Code(std::array<code_type, 3>{}, depth()); }
892
893 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
894 [[nodiscard]] Code code(NodeType node) const
895 {
896 using T = remove_cvref_t<NodeType>;
897 if constexpr (std::is_same_v<T, Index>) {
898 assert(valid(node));
899 depth_type d = depth(node);
900
901 Code ret;
902 ret.setDepth(d);
903
904 do {
905 ret.setOffset(d, node.offset);
906 node = parent(node);
907 ++d;
908 } while (valid(node.pos));
909 return ret;
910 } else if constexpr (std::is_same_v<T, Node>) {
911 return node.code;
912 } else if constexpr (std::is_same_v<T, Code>) {
913 return node;
914 } else if constexpr (std::is_same_v<T, Key>) {
915 return Code(node);
916 } else if constexpr (std::is_same_v<T, Coord>) {
917 return code(key(node));
918 } else {
919 return code(convert(node));
920 }
921 }
922
923 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
924 [[nodiscard]] std::optional<Code> codeChecked(NodeType node) const
925 {
926 return valid(node) ? std::optional<Code>(Code(node)) : std::nullopt;
927 }
928
929 //
930 // Key
931 //
932
933 [[nodiscard]] Key key() const { return Key(Vec<Dim, key_type>(0), depth()); }
934
935 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
936 [[nodiscard]] Key key(NodeType node) const
937 {
938 using T = remove_cvref_t<NodeType>;
939 if constexpr (std::is_same_v<T, Code>) {
940 return Key(node);
941 } else if constexpr (std::is_same_v<T, Key>) {
942 return node;
943 } else if constexpr (std::is_same_v<T, Coord>) {
944 assert(valid(node));
945
946 auto d = depth(node);
947 Point p = node;
948
949 // LOOKAT: Check performance, might be a lot faster to have float here
950 Length lr = lengthReciprocal(0);
951
952 auto k = cast<key_type>(
953 cast<std::make_signed_t<key_type>>(floor(cast<length_type>(p) * lr))) +
954 half_max_value_;
955
956 return Key(k >> d, d);
957 } else if constexpr (contains_type_v<T, Index, Node>) {
958 return key(code(node));
959 } else {
960 return key(convert(node));
961 }
962 }
963
964 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
965 [[nodiscard]] std::optional<Key> keyChecked(NodeType node) const
966 {
967 return valid(node) ? std::optional<Key>(key(node)) : std::nullopt;
968 }
969
970 /**************************************************************************************
971 | |
972 | Modified |
973 | |
974 **************************************************************************************/
975
981 [[nodiscard]] bool modified() const { return modified(index()); }
982
989 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
990 [[nodiscard]] bool modified(NodeType node) const
991 {
992 Index n = index(node);
993 return modified(n.pos, n.offset);
994 }
995
996 void modifiedSet(bool value) { return value ? modifiedSet() : modifiedReset(); }
997
998 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
999 void modifiedSet(NodeType node, bool value)
1000 {
1001 return value ? modifiedSet(node) : modifiedReset(node);
1002 }
1003
1004 void modifiedSet() { modifiedSet(index()); }
1005
1006 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
1007 void modifiedSet(NodeType node)
1008 {
1009 // NOTE: `create` sets ancestors to modified
1010 auto n = create(node);
1011 modifiedSet(n.pos, n.offset);
1012 if (isParent(n)) {
1013 modifiedSetChildren(n);
1014 }
1015 }
1016
1017 void modifiedReset() { modifiedReset(index()); }
1018
1019 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
1020 void modifiedReset(NodeType node)
1021 {
1022 if (!exists(node)) {
1023 return;
1024 }
1025
1026 auto n = index(node);
1027 modifiedReset(n.pos, n.offset);
1028 if (isParent(n)) {
1029 modifiedResetChildren(n);
1030 }
1031 }
1032
1033 /**************************************************************************************
1034 | |
1035 | Touch |
1036 | |
1037 **************************************************************************************/
1038
1039 // TODO: Add proper guards for the templates
1040
1041 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
1042 Index create(NodeType node)
1043 {
1044 assert(valid(node));
1045
1046 using T = remove_cvref_t<NodeType>;
1047 if constexpr (std::is_same_v<T, Index>) {
1048 modifiedSetParents(node);
1049 return node;
1050 } else {
1051 Code code = this->code(node);
1052 auto wanted_depth = depth(code);
1053 auto cur_node = index();
1054 auto cur_depth = depth();
1055 while (wanted_depth < cur_depth) {
1056 cur_node = createChild(cur_node, code.offset(--cur_depth));
1057 }
1058 return cur_node;
1059 }
1060 }
1061
1062 template <class InputIt, class OutputIt>
1063 OutputIt create(InputIt first, InputIt last, OutputIt d_first)
1064 {
1065 using T = remove_cvref_t<typename std::iterator_traits<InputIt>::value_type>;
1066
1067 if constexpr (std::is_same_v<T, Index>) {
1068 return std::transform(first, last, d_first,
1069 [this](Index node) { return create(node); });
1070 } else {
1071 Index node = this->index();
1072 Code node_code = this->code();
1073
1074 return std::transform(first, last, d_first,
1075 [this, &node, &node_code](auto const& x) {
1076 Code d_code = code(x);
1077 depth_type d = Code::depthWhereEqual(node_code, d_code);
1078
1079 node = ancestor(node, d);
1080 node_code = d_code;
1081 for (depth_type d_depth = depth(d_code); d_depth < d; --d) {
1082 node = createChild(node, d_code.offset(d - 1));
1083 }
1084
1085 return node;
1086 });
1087 }
1088 }
1089
1090 template <class InputIt>
1091 std::vector<Index> create(InputIt first, InputIt last)
1092 {
1093 std::vector<Index> nodes;
1094 create(first, last, std::back_inserter(nodes));
1095 return nodes;
1096 }
1097
1098 template <
1099 class Range, class OutputIt,
1100 std::enable_if_t<!is_node_type_v<Range> && !execution::is_execution_policy_v<Range>,
1101 bool> = true>
1102 OutputIt create(Range const& r, OutputIt d_first)
1103 {
1104 using std::begin;
1105 using std::end;
1106 return create(begin(r), end(r), d_first);
1107 }
1108
1109 template <class Range, std::enable_if_t<!is_node_type_v<Range>, bool> = true>
1110 std::vector<Index> create(Range const& r)
1111 {
1112 std::vector<Index> nodes;
1113 create(r, std::back_inserter(nodes));
1114 return nodes;
1115 }
1116
1117 // TODO: Continue from here
1118
1119 template <
1120 class ExecutionPolicy, class RandomIt1, class RandomIt2,
1121 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>, bool> = true>
1122 RandomIt2 create(ExecutionPolicy&& policy, RandomIt1 first, RandomIt1 last,
1123 RandomIt2 d_first)
1124 {
1125 using T = remove_cvref_t<typename std::iterator_traits<RandomIt1>::value_type>;
1126
1127 if constexpr (std::is_same_v<T, Index>) {
1128 return ufo::transform(std::forward<ExecutionPolicy>(policy), first, last, d_first,
1129 [this](Index node) {
1130 modifiedSetParentsThreadSafe(node);
1131 return node;
1132 });
1133 } else {
1134 // NOTE: Possible (although, highly unlikely) problem. If this function is called
1135 // more than max value of `std::size_t`, so `create_call_num` overflows, *AND* a
1136 // thread has persisted but not been used for a multiple of max value of
1137 // `std::size_t` iterations in the `transform` call below; then `node` and
1138 // `node_code` would not be reset to the root node as they should. This means that
1139 // invalid memory is being accessed.
1140 static std::size_t create_call_num{};
1141 ++create_call_num;
1142
1143 return transform(std::forward<ExecutionPolicy>(policy), first, last, d_first,
1144 [this, ccn = create_call_num](auto const& x) {
1145 thread_local Index node = index();
1146 thread_local Code node_code = code();
1147
1148 thread_local std::size_t thread_create_call_num = 1;
1149 if (ccn != thread_create_call_num) {
1150 thread_create_call_num = ccn;
1151 node = index();
1152 node_code = code();
1153 }
1154
1155 Code d_code = code(x);
1156 depth_type d = Code::depthWhereEqual(node_code, d_code);
1157
1158 node = ancestor(node, d);
1159 node_code = d_code;
1160 for (depth_type d_depth = depth(d_code); d_depth < d; --d) {
1161 node = createChildThreadSafe(node, d_code.offset(d - 1));
1162 }
1163
1164 return node;
1165 });
1166 }
1167 }
1168
1169 template <
1170 class ExecutionPolicy, class RandomIt,
1171 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>, bool> = true>
1172 std::vector<Index> create(ExecutionPolicy&& policy, RandomIt first, RandomIt last)
1173 {
1174 __block std::vector<Index> nodes(std::distance(first, last));
1175 create(std::forward<ExecutionPolicy>(policy), first, last, nodes.begin());
1176 return nodes;
1177 }
1178
1179 template <
1180 class ExecutionPolicy, class Range, class RandomIt,
1181 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>, bool> = true,
1182 std::enable_if_t<!is_node_type_v<Range>, bool> = true>
1183 RandomIt create(ExecutionPolicy&& policy, Range const& r, RandomIt d_first)
1184 {
1185 using std::begin;
1186 using std::end;
1187 return create(std::forward<ExecutionPolicy>(policy), begin(r), end(r), d_first);
1188 }
1189
1190 template <
1191 class ExecutionPolicy, class Range,
1192 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>, bool> = true,
1193 std::enable_if_t<!is_node_type_v<Range>, bool> = true>
1194 std::vector<Index> create(ExecutionPolicy&& policy, Range const& r)
1195 {
1196 using std::size;
1197 __block std::vector<Index> nodes(size(r));
1198 create(std::forward<ExecutionPolicy>(policy), r, nodes.begin());
1199 return nodes;
1200 }
1201
1202 /**************************************************************************************
1203 | |
1204 | Erase |
1205 | |
1206 **************************************************************************************/
1207
1208 void eraseChildren() { eraseChildren(index()); }
1209
1210 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
1211 void eraseChildren(NodeType node)
1212 {
1213 using T = remove_cvref_t<NodeType>;
1214 if constexpr (std::is_same_v<T, Index>) {
1215 if (isLeaf(node)) {
1216 return;
1217 }
1218
1219 auto c = children(node);
1220 for (offset_type i{}; BF > i; ++i) {
1221 eraseChildren(Index(c, i));
1222 }
1223
1224 pruneChildren(node, c);
1225 } else if constexpr (contains_type_v<T, Node, Code>) {
1226 if (!exists(node)) {
1227 return;
1228 }
1229
1230 eraseChildren(index(node));
1231 } else if constexpr (contains_type_v<T, Key, Coord>) {
1232 eraseChildren(code(node));
1233 } else {
1234 eraseChildren(convert(node));
1235 }
1236 }
1237
1238 /**************************************************************************************
1239 | |
1240 | Leaf |
1241 | |
1242 **************************************************************************************/
1243
1244 //
1245 // Pure leaf
1246 //
1247
1256 [[nodiscard]] bool isPureLeaf(pos_type block) const
1257 {
1258 assert(valid(block));
1259 return Data::leaf(block);
1260 }
1261
1270 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
1271 [[nodiscard]] bool isPureLeaf(NodeType node) const
1272 {
1273 using T = remove_cvref_t<NodeType>;
1274 if constexpr (std::is_same_v<T, Index>) {
1275 return isPureLeaf(block(node));
1276 } else {
1277 return 0u == depth(node);
1278 }
1279 }
1280
1281 //
1282 // Leaf
1283 //
1284
1291 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
1292 [[nodiscard]] bool isLeaf(NodeType node) const
1293 {
1294 return isPureLeaf(node) || !valid(children(index(node)));
1295 }
1296
1297 //
1298 // Parent
1299 //
1300
1307 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
1308 [[nodiscard]] bool isParent(NodeType node) const
1309 {
1310 return !isLeaf(node);
1311 }
1312
1313 /**************************************************************************************
1314 | |
1315 | Root |
1316 | |
1317 **************************************************************************************/
1318
1319 [[nodiscard]] constexpr bool isRoot(pos_type block) const
1320 {
1321 return this->block() == block;
1322 }
1323
1330 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
1331 [[nodiscard]] constexpr bool isRoot(NodeType node) const
1332 {
1333 using T = remove_cvref_t<NodeType>;
1334 if constexpr (std::is_same_v<T, Index>) {
1335 return index() == node;
1336 } else if constexpr (std::is_same_v<T, Node>) {
1337 return isRoot(node.code);
1338 } else if constexpr (std::is_same_v<T, Code>) {
1339 return code() == node;
1340 } else if constexpr (std::is_same_v<T, Key>) {
1341 return key() == node;
1342 } else if constexpr (std::is_same_v<T, Coord>) {
1343 return isRoot(key(node));
1344 } else {
1345 return isRoot(convert(node));
1346 }
1347 }
1348
1349 /**************************************************************************************
1350 | |
1351 | Valid |
1352 | |
1353 **************************************************************************************/
1354
1361 [[nodiscard]] bool valid(pos_type block) const { return Index::MAX_VALID_POS >= block; }
1362
1369 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
1370 [[nodiscard]] bool valid(NodeType node) const
1371 {
1372 using T = remove_cvref_t<NodeType>;
1373 if constexpr (std::is_same_v<T, Index>) {
1374 return valid(node.pos) && branchingFactor() > node.offset;
1375 } else if constexpr (std::is_same_v<T, Node>) {
1376 return valid(code(node));
1377 } else if constexpr (std::is_same_v<T, Code>) {
1378 return node.valid() && numDepthLevels() > depth(node);
1379 } else if constexpr (std::is_same_v<T, Key>) {
1380 auto const mv = (2 * half_max_value_) >> depth(node);
1381 for (std::size_t i{}; node.size() != i; ++i) {
1382 if (mv < node[i]) {
1383 return false;
1384 }
1385 }
1386
1387 return node.valid() && numDepthLevels() > depth(node);
1388 } else if constexpr (std::is_same_v<T, Coord>) {
1389 return isInside(static_cast<Point>(node)) && numDepthLevels() > depth(node);
1390 } else {
1391 return valid(convert(node));
1392 }
1393 }
1394
1395 /**************************************************************************************
1396 | |
1397 | Exist |
1398 | |
1399 **************************************************************************************/
1400
1401 [[nodiscard]] bool exists(pos_type block) const
1402 {
1403 return Data::exists(block) && Index::INVALID_POS != parent(block).pos;
1404 }
1405
1412 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
1413 [[nodiscard]] bool exists(NodeType node) const
1414 {
1415 using T = remove_cvref_t<NodeType>;
1416 if constexpr (std::is_same_v<T, Index>) {
1417 return exists(node.pos);
1418 } else if constexpr (contains_type_v<T, Node, Code, Key, Coord>) {
1419 return depth(index(node)) == depth(node);
1420 } else {
1421 return exists(convert(node));
1422 }
1423 }
1424
1425 /**************************************************************************************
1426 | |
1427 | Traverse |
1428 | |
1429 **************************************************************************************/
1430
1431 [[nodiscard]] std::array<pos_type, BF> const& children(pos_type block) const
1432 {
1433 assert(!isPureLeaf(block));
1434 return treeInnerBlock(block).children;
1435 }
1436
1437 [[nodiscard]] pos_type children(Index node) const
1438 {
1439 return children(node.pos)[node.offset];
1440 }
1441
1449 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
1450 [[nodiscard]] constexpr auto child(NodeType node, offset_type offset) const
1451 {
1452 assert(!isPureLeaf(node));
1453 assert(BF > offset);
1454
1455 using T = remove_cvref_t<NodeType>;
1456 if constexpr (std::is_same_v<T, Index>) {
1457 return Index(children(node), offset);
1458 } else if constexpr (std::is_same_v<T, Node>) {
1459 return Node(child(node.code, offset), node.index);
1460 } else if constexpr (contains_type_v<T, Code, Key>) {
1461 return node.child(offset);
1462 } else if constexpr (std::is_same_v<T, Coord>) {
1463 auto center = static_cast<Point>(node);
1464 auto half_length = halfLength(node);
1465 auto child_depth = node.depth - depth_type(1);
1466 return Coord(childCenter(center, half_length, offset), child_depth);
1467 } else {
1468 return child(convert(node), offset);
1469 }
1470 }
1471
1479 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
1480 [[nodiscard]] auto childChecked(NodeType node, offset_type offset) const
1481 {
1482 using T = remove_cvref_t<NodeType>;
1483 if constexpr (std::is_same_v<T, Index>) {
1484 return isParent(node) && BF > offset ? std::optional(child(node, offset))
1485 : std::nullopt;
1486 } else if constexpr (contains_type_v<T, Node, Code, Key, Coord>) {
1487 return !isPureLeaf(node) && BF > offset ? std::optional(child(node, offset))
1488 : std::nullopt;
1489 } else {
1490 return childChecked(convert(node), offset);
1491 }
1492 }
1493
1494 //
1495 // Sibling
1496 //
1497
1498 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
1499 [[nodiscard]] auto sibling(NodeType node, offset_type offset) const
1500 {
1501 assert(!isRoot(node));
1502 assert(BF > offset);
1503
1504 using T = remove_cvref_t<NodeType>;
1505 if constexpr (std::is_same_v<T, Index>) {
1506 return Index(node.pos, offset);
1507 } else if constexpr (std::is_same_v<T, Node>) {
1508 return Node(sibling(node.code, offset), node.index);
1509 } else if constexpr (contains_type_v<T, Code, Key>) {
1510 return node.sibling(offset);
1511 } else if constexpr (std::is_same_v<T, Coord>) {
1512 return center(sibling(key(node), offset));
1513 } else {
1514 return sibling(convert(node), offset);
1515 }
1516 }
1517
1518 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
1519 [[nodiscard]] auto siblingChecked(NodeType node, offset_type offset) const
1520 {
1521 return !isRoot(node) && BF > offset ? std::optional(sibling(node, offset))
1522 : std::nullopt;
1523 }
1524
1525 //
1526 // Parent
1527 //
1528
1529 [[nodiscard]] Index parent(pos_type block) const
1530 {
1531 assert(!isRoot(block));
1532 return isPureLeaf(block) ? parent(treeLeafBlock(block))
1533 : parent(treeInnerBlock(block));
1534 }
1535
1536 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
1537 [[nodiscard]] auto parent(NodeType node) const
1538 {
1539 assert(!isRoot(node));
1540
1541 using T = remove_cvref_t<NodeType>;
1542 if constexpr (std::is_same_v<T, Index>) {
1543 return parent(node.pos);
1544 } else if constexpr (std::is_same_v<T, Node>) {
1545 return Node(parent(node.code), node.index);
1546 } else if constexpr (contains_type_v<T, Code, Key>) {
1547 return node.parent();
1548 } else if constexpr (std::is_same_v<T, Coord>) {
1549 return center(parent(key(node)));
1550 } else {
1551 return parent(convert(node));
1552 }
1553 }
1554
1555 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
1556 [[nodiscard]] auto parentChecked(NodeType node) const
1557 {
1558 return !isRoot(node) ? std::optional(parent(node)) : std::nullopt;
1559 }
1560
1561 //
1562 // Ancestor
1563 //
1564
1565 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
1566 [[nodiscard]] auto ancestor(NodeType node, depth_type depth) const
1567 {
1568 assert(!isRoot(node) || this->depth(node) == depth);
1569 assert(this->depth(node) <= depth);
1570 assert(this->depth() >= depth);
1571
1572 depth_type cur_depth = this->depth(node);
1573
1574 if (cur_depth >= depth) {
1575 return node;
1576 }
1577
1578 using T = remove_cvref_t<NodeType>;
1579 if constexpr (std::is_same_v<T, Index>) {
1580 node = 0 == cur_depth ? parent(treeLeafBlock(node.pos))
1581 : parent(treeInnerBlock(node.pos));
1582
1583 for (++cur_depth; cur_depth < depth; ++cur_depth) {
1584 node = parent(treeInnerBlock(node.pos));
1585 }
1586
1587 return node;
1588 } else if constexpr (std::is_same_v<T, Node>) {
1589 return Node(ancestor(node.code, depth), node.index);
1590 } else if constexpr (contains_type_v<T, Code, Key>) {
1591 return node.toDepth(depth);
1592 } else if constexpr (std::is_same_v<T, Coord>) {
1593 return center(ancestor(key(node), depth));
1594 } else {
1595 return ancestor(convert(node), depth);
1596 }
1597 }
1598
1599 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
1600 [[nodiscard]] auto ancestorChecked(NodeType node, depth_type depth) const
1601 {
1602 return (!isRoot(node) || this->depth(node) == depth) && this->depth(node) <= depth &&
1603 this->depth() >= depth
1604 ? std::optional(ancestor(node, depth))
1605 : std::nullopt;
1606 }
1607
1615 template <class UnaryFun,
1616 std::enable_if_t<std::is_invocable_r_v<bool, UnaryFun, Index>, bool> = true>
1617 void traverse(UnaryFun f) const
1618 {
1619 traverse(index(), f);
1620 }
1621
1630 template <class NodeType, class UnaryFun,
1631 std::enable_if_t<is_node_type_v<NodeType>, bool> = true,
1632 std::enable_if_t<std::is_invocable_r_v<bool, UnaryFun, Index>, bool> = true>
1633 void traverse(NodeType node, UnaryFun f) const
1634 {
1635 assert(valid(node));
1636
1637 if (!exists(node)) {
1638 return;
1639 }
1640
1641 Index cur = index(node);
1642 pos_type const start = cur.pos;
1643
1644 while (f(cur) && isParent(cur)) {
1645 cur = child(cur, 0);
1646 }
1647
1648 while (start != cur.pos) {
1649 if (BF - 1 <= cur.offset) {
1650 cur = parent(cur.pos);
1651 } else {
1652 ++cur.offset;
1653 while (f(cur) && isParent(cur)) {
1654 cur = child(cur, 0);
1655 }
1656 }
1657 }
1658 }
1659
1669 template <class UnaryFun, class Predicate,
1670 std::enable_if_t<std::is_invocable_r_v<bool, UnaryFun, Node>, bool> = true,
1671 std::enable_if_t<pred::is_pred_v<Predicate>, bool> = true>
1672 void traverse(UnaryFun f, Predicate const& pred, bool only_exists = true) const
1673 {
1674 traverse(node(), f, pred, only_exists);
1675 }
1676
1686 template <class NodeType, class UnaryFun, class Predicate,
1687 std::enable_if_t<is_node_type_v<NodeType>, bool> = true,
1688 std::enable_if_t<std::is_invocable_v<UnaryFun, Node>, bool> = true,
1689 std::enable_if_t<pred::is_pred_v<Predicate>, bool> = true>
1690 void traverse(NodeType node, UnaryFun f, Predicate pred, bool only_exists = true) const
1691 {
1692 assert(valid(node));
1693
1694 using Filter = pred::Filter<Predicate>;
1695
1696 Filter::init(pred, derived());
1697
1698 if (only_exists) {
1699 auto fun = [this, f, &pred](Node node) {
1700 if (Filter::returnable(pred, derived(), node)) {
1701 f(node);
1702 }
1703 return isParent(node.index) && Filter::traversable(pred, derived(), node);
1704 };
1705
1706 if (!exists(node)) {
1707 return;
1708 }
1709
1710 Node cur = this->node(node);
1711 pos_type const start = cur.index.pos;
1712
1713 while (fun(cur)) {
1714 cur.code = cur.code.firstBorn();
1715 cur.index = child(cur.index, 0);
1716 }
1717
1718 while (start != cur.index.pos) {
1719 if (BF - 1 <= cur.index.offset) {
1720 cur.code = cur.code.parent();
1721 cur.index = parent(cur.index.pos);
1722 } else {
1723 cur.code = cur.code.nextSibling();
1724 ++cur.index.offset;
1725 while (fun(cur)) {
1726 cur.code = cur.code.firstBorn();
1727 cur.index = child(cur.index, 0);
1728 }
1729 }
1730 }
1731 } else {
1732 auto fun = [this, f, &pred](Node node) {
1733 if (Filter::returnable(pred, derived(), node)) {
1734 f(node);
1735 }
1736 return !isPureLeaf(node.index) && Filter::traversable(pred, derived(), node);
1737 };
1738
1739 Node cur = this->node(node);
1740 depth_type const start = cur.code.depth();
1741
1742 while (fun(node)) {
1743 cur.code = cur.code.firstborn();
1744 cur.index = isParent(cur.index) ? child(cur.index, 0) : cur.index;
1745 }
1746
1747 while (start != cur.code.depth()) {
1748 if (BF - 1 <= cur.code.offset()) {
1749 cur.code = cur.code.parent();
1750 cur.index =
1751 cur.code.depth() > depth(cur.index) ? parent(cur.index.pos) : cur.index;
1752 } else {
1753 cur.code = cur.code.nextSibling();
1754 cur.index.offset += cur.code.depth() == depth(cur.index) ? 1 : 0;
1755 while (fun(node)) {
1756 cur.code = cur.code.firstborn();
1757 cur.index = isParent(cur.index) ? child(cur.index, 0) : cur.index;
1758 }
1759 }
1760 }
1761 }
1762 }
1763
1764 /**************************************************************************************
1765 | |
1766 | Iterators |
1767 | |
1768 **************************************************************************************/
1769
1770 //
1771 // Iterator
1772 //
1773
1774 [[nodiscard]] const_iterator begin(bool only_leaves = true,
1775 bool only_exists = true) const
1776 {
1777 return begin(node(), only_leaves, only_exists);
1778 }
1779
1780 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
1781 [[nodiscard]] const_iterator begin(NodeType node, bool only_leaves = true,
1782 bool only_exists = true) const
1783 {
1784 return const_iterator(&derived(), this->node(node), only_leaves, only_exists);
1785 }
1786
1787 [[nodiscard]] const_iterator end() const { return const_iterator(); }
1788
1789 //
1790 // Query iterator
1791 //
1792
1793 template <class Predicate, std::enable_if_t<pred::is_pred_v<Predicate>, bool> = true>
1794 [[nodiscard]] const_query_iterator_pred<Predicate> beginQuery(
1795 Predicate const& pred, bool only_exists = true, bool early_stopping = false) const
1796 {
1797 return beginQuery(node(), pred, only_exists, early_stopping);
1798 }
1799
1800 template <class NodeType, class Predicate,
1801 std::enable_if_t<is_node_type_v<NodeType>, bool> = true,
1802 std::enable_if_t<pred::is_pred_v<Predicate>, bool> = true>
1803 [[nodiscard]] const_query_iterator_pred<Predicate> beginQuery(
1804 NodeType node, Predicate const& pred, bool only_exists = true,
1805 bool early_stopping = false) const
1806 {
1807 return const_query_iterator_pred<remove_cvref_t<Predicate>>(
1808 &derived(), this->node(node), pred, only_exists, early_stopping);
1809 }
1810
1811 [[nodiscard]] const_query_iterator endQuery() const { return const_query_iterator(); }
1812
1813 //
1814 // Nearest iterator
1815 //
1816
1817 template <class Geometry>
1818 [[nodiscard]] const_nearest_iterator_geom<Geometry> beginNearest(
1819 Geometry const& geometry, double epsilon = 0.0, bool only_leaves = true,
1820 bool only_exists = true) const
1821 {
1822 return beginNearest(node(), geometry, epsilon, only_leaves, only_exists);
1823 }
1824
1825 template <class NodeType, class Geometry,
1826 std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
1827 [[nodiscard]] const_nearest_iterator_geom<Geometry> beginNearest(
1828 NodeType node, Geometry const& geometry, double epsilon = 0.0,
1829 bool only_leaves = true, bool only_exists = true) const
1830 {
1831 return const_nearest_iterator_geom<Geometry>(&derived(), this->node(node), geometry,
1832 epsilon, only_leaves, only_exists);
1833 }
1834
1835 [[nodiscard]] const_nearest_iterator endNearest() const
1836 {
1837 return const_nearest_iterator();
1838 }
1839
1840 //
1841 // Query nearest iterator
1842 //
1843
1844 template <class Predicate, class Geometry,
1845 std::enable_if_t<pred::is_pred_v<Predicate>, bool> = true>
1846 [[nodiscard]] const_query_nearest_iterator_pred_geom<Predicate, Geometry>
1847 beginQueryNearest(Predicate const& pred, Geometry const& geometry, double epsilon = 0.0,
1848 bool only_exists = true, bool early_stopping = false) const
1849 {
1850 return beginQueryNearest(node(), pred, geometry, epsilon, only_exists,
1851 early_stopping);
1852 }
1853
1854 template <class NodeType, class Predicate, class Geometry,
1855 std::enable_if_t<is_node_type_v<NodeType>, bool> = true,
1856 std::enable_if_t<pred::is_pred_v<Predicate>, bool> = true>
1857 [[nodiscard]] const_query_nearest_iterator_pred_geom<Predicate, Geometry>
1858 beginQueryNearest(NodeType node, Predicate const& pred, Geometry const& geometry,
1859 double epsilon = 0.0, bool only_exists = true,
1860 bool early_stopping = false) const
1861 {
1862 return const_query_nearest_iterator_pred_geom<Predicate, Geometry>(
1863 &derived(), this->node(node), pred, geometry, epsilon, only_exists,
1864 early_stopping);
1865 }
1866
1867 [[nodiscard]] const_query_nearest_iterator endQueryNearest() const
1868 {
1869 return const_query_nearest_iterator();
1870 }
1871
1872 /**************************************************************************************
1873 | |
1874 | Query |
1875 | |
1876 **************************************************************************************/
1877
1878 //
1879 // Query
1880 //
1881
1882 template <class Predicate, std::enable_if_t<pred::is_pred_v<Predicate>, bool> = true>
1883 [[nodiscard]] ConstQuery<Predicate> query(Predicate const& pred,
1884 bool only_exists = true,
1885 bool early_stopping = false) const
1886 {
1887 return query(node(), pred, only_exists, early_stopping);
1888 }
1889
1890 template <class NodeType, class Predicate,
1891 std::enable_if_t<is_node_type_v<NodeType>, bool> = true,
1892 std::enable_if_t<pred::is_pred_v<Predicate>, bool> = true>
1893 [[nodiscard]] ConstQuery<Predicate> query(NodeType node, Predicate const& pred,
1894 bool only_exists = true,
1895 bool early_stopping = false) const
1896 {
1897 return ConstQuery<Predicate>(beginQuery(node, pred, only_exists, early_stopping),
1898 endQuery());
1899 }
1900
1901 template <class Predicate, std::enable_if_t<pred::is_pred_v<Predicate>, bool> = true>
1902 [[nodiscard]] ConstQuery<Predicate> operator()(Predicate const& pred,
1903 bool only_exists = true,
1904 bool early_stopping = false) const
1905 {
1906 return query(pred, only_exists, early_stopping);
1907 }
1908
1909 template <class NodeType, class Predicate,
1910 std::enable_if_t<is_node_type_v<NodeType>, bool> = true,
1911 std::enable_if_t<pred::is_pred_v<Predicate>, bool> = true>
1912 [[nodiscard]] ConstQuery<Predicate> operator()(NodeType node, Predicate const& pred,
1913 bool only_exists = true,
1914 bool early_stopping = false) const
1915 {
1916 return query(node, pred, only_exists, early_stopping);
1917 }
1918
1919 //
1920 // Nearest
1921 //
1922
1923 template <class Geometry>
1924 [[nodiscard]] ConstNearest<Geometry> nearest(Geometry const& geometry,
1925 double epsilon = 0.0,
1926 bool only_leaves = true,
1927 bool only_exists = true) const
1928 {
1929 return nearest(node(), geometry, epsilon, only_leaves, only_exists);
1930 }
1931
1932 template <class NodeType, class Geometry,
1933 std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
1934 [[nodiscard]] ConstNearest<Geometry> nearest(NodeType node, Geometry const& geometry,
1935 double epsilon = 0.0,
1936 bool only_leaves = true,
1937 bool only_exists = true) const
1938 {
1939 return ConstNearest<Geometry>(
1940 beginNearest(node, geometry, epsilon, only_leaves, only_exists), endNearest());
1941 }
1942
1943 //
1944 // Query nearest
1945 //
1946
1947 template <class Predicate, class Geometry,
1948 std::enable_if_t<pred::is_pred_v<Predicate>, bool> = true>
1949 [[nodiscard]] ConstQueryNearest<Predicate, Geometry> queryNearest(
1950 Predicate const& pred, Geometry const& geometry, double epsilon = 0.0,
1951 bool only_exists = true, bool early_stopping = false) const
1952 {
1953 return queryNearest(node(), pred, geometry, epsilon, only_exists, early_stopping);
1954 }
1955
1956 template <class NodeType, class Predicate, class Geometry,
1957 std::enable_if_t<is_node_type_v<NodeType>, bool> = true,
1958 std::enable_if_t<pred::is_pred_v<Predicate>, bool> = true>
1959 [[nodiscard]] ConstQueryNearest<Predicate, Geometry> queryNearest(
1960 NodeType node, Predicate const& pred, Geometry const& geometry,
1961 double epsilon = 0.0, bool only_exists = true, bool early_stopping = false) const
1962 {
1963 return ConstQueryNearest<Predicate, Geometry>(
1964 beginQueryNearest(node, pred, geometry, epsilon, only_exists, early_stopping),
1965 endQueryNearest());
1966 }
1967
1968 /**************************************************************************************
1969 | |
1970 | Trace |
1971 | |
1972 **************************************************************************************/
1973
1974 // TODO: Add `only_exists`
1975
1976 template <class Predicate, std::enable_if_t<pred::is_pred_v<Predicate>, bool> = true>
1977 [[nodiscard]] TraceResult trace(Ray const& ray, Predicate const& pred,
1978 float min_dist = 0.0f,
1979 float max_dist = std::numeric_limits<float>::max(),
1980 bool only_exists = true) const
1981 {
1982 return trace(node(), ray, pred, min_dist, max_dist, only_exists);
1983 }
1984
1985 template <class NodeType, class Predicate,
1986 std::enable_if_t<is_node_type_v<NodeType>, bool> = true,
1987 std::enable_if_t<pred::is_pred_v<Predicate>, bool> = true>
1988 [[nodiscard]] TraceResult trace(NodeType node, Ray const& ray, Predicate pred,
1989 float min_dist = 0.0f,
1990 float max_dist = std::numeric_limits<float>::max(),
1991 bool only_exists = true) const
1992 {
1993 // TODO: Implement, also look at `only_exists`
1994
1995 using Filter = pred::Filter<Predicate>;
1996
1997 Filter::init(pred, derived());
1998
1999 Node n = node(node);
2000 if (!exists(n)) { // What if !only_exists?
2001 return TraceResult{Node(), -1.0f};
2002 }
2003
2004 auto params = traceInit(n, ray);
2005 return trace(n, params, pred, min_dist, max_dist, only_exists);
2006 }
2007
2008 template <class InputIt, class OutputIt, class Predicate,
2009 std::enable_if_t<pred::is_pred_v<Predicate>, bool> = true>
2010 OutputIt trace(InputIt first, InputIt last, OutputIt d_first, Predicate const& pred,
2011 float min_dist = 0.0f,
2012 float max_dist = std::numeric_limits<float>::max(),
2013 bool only_exists = true) const
2014 {
2015 return trace(node(), first, last, d_first, pred, min_dist, max_dist, only_exists);
2016 }
2017
2018 template <class NodeType, class InputIt, class OutputIt, class Predicate,
2019 std::enable_if_t<is_node_type_v<NodeType>, bool> = true,
2020 std::enable_if_t<pred::is_pred_v<Predicate>, bool> = true>
2021 OutputIt trace(NodeType node, InputIt first, InputIt last, OutputIt d_first,
2022 Predicate const& pred, float min_dist = 0.0f,
2023 float max_dist = std::numeric_limits<float>::max(),
2024 bool only_exists = true) const
2025 {
2026 // TODO: Implement
2027 }
2028
2029 template <class InputIt, class Predicate,
2030 std::enable_if_t<pred::is_pred_v<Predicate>, bool> = true>
2031 [[nodiscard]] std::vector<TraceResult> trace(
2032 InputIt first, InputIt last, Predicate const& pred, float min_dist = 0.0f,
2033 float max_dist = std::numeric_limits<float>::max(), bool only_exists = true) const
2034 {
2035 return trace(node(), first, last, pred, min_dist, max_dist, only_exists);
2036 }
2037
2038 template <class NodeType, class InputIt, class Predicate,
2039 std::enable_if_t<is_node_type_v<NodeType>, bool> = true,
2040 std::enable_if_t<pred::is_pred_v<Predicate>, bool> = true>
2041 [[nodiscard]] std::vector<TraceResult> trace(
2042 NodeType node, InputIt first, InputIt last, Predicate const& pred,
2043 float min_dist = 0.0f, float max_dist = std::numeric_limits<float>::max(),
2044 bool only_exists = true) const
2045 {
2046 std::vector<TraceResult> res;
2047 trace(node, first, last, std::back_inserter(res), pred, min_dist, max_dist,
2048 only_exists);
2049 return res;
2050 }
2051
2052 template <
2053 class ExecutionPolicy, class RandomIt1, class RandomIt2, class Predicate,
2054 std::enable_if_t<pred::is_pred_v<Predicate>, bool> = true,
2055 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>, bool> = true>
2056 RandomIt2 trace(ExecutionPolicy&& policy, RandomIt1 first, RandomIt1 last,
2057 RandomIt2 d_first, Predicate const& pred, float min_dist = 0.0f,
2058 float max_dist = std::numeric_limits<float>::max(),
2059 bool only_exists = true) const
2060 {
2061 return trace(std::forward<ExecutionPolicy>(policy), index(), first, last, d_first,
2062 pred, min_dist, max_dist, only_exists);
2063 }
2064
2065 template <
2066 class ExecutionPolicy, class NodeType, class RandomIt1, class RandomIt2,
2067 class Predicate, std::enable_if_t<is_node_type_v<NodeType>, bool> = true,
2068 std::enable_if_t<pred::is_pred_v<Predicate>, bool> = true,
2069 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>, bool> = true>
2070 RandomIt2 trace(ExecutionPolicy&& policy, NodeType node, RandomIt1 first,
2071 RandomIt1 last, RandomIt2 d_first, Predicate pred,
2072 float min_dist = 0.0f,
2073 float max_dist = std::numeric_limits<float>::max(),
2074 bool only_exists = true) const
2075 {
2076 // TODO: Look at `only_exists`
2077
2078 using Filter = pred::Filter<Predicate>;
2079
2080 Filter::init(pred, derived());
2081
2082 Node n = this->node(node);
2083 if (!exists(n)) {
2084 for (; last != first; ++first, ++d_first) {
2085 *d_first = TraceResult{Node(), -1.0f};
2086 }
2087 return d_first;
2088 }
2089
2090 auto center = this->center(n);
2091 auto half_length = halfLength(n);
2092
2093 return transform(std::forward<ExecutionPolicy>(policy), first, last, d_first,
2094 [&](Ray const& ray) {
2095 auto params = traceInit(ray, center, half_length);
2096 return trace(n, params, pred, min_dist, max_dist, only_exists);
2097 });
2098 }
2099
2100 template <
2101 class ExecutionPolicy, class RandomIt, class Predicate,
2102 std::enable_if_t<pred::is_pred_v<Predicate>, bool> = true,
2103 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>, bool> = true>
2104 [[nodiscard]] std::vector<TraceResult> trace(
2105 ExecutionPolicy&& policy, RandomIt first, RandomIt last, Predicate const& pred,
2106 float min_dist = 0.0f, float max_dist = std::numeric_limits<float>::max(),
2107 bool only_exists = true) const
2108 {
2109 return trace(std::forward<ExecutionPolicy>(policy), index(), first, last, pred,
2110 min_dist, max_dist, only_exists);
2111 }
2112
2113 template <
2114 class ExecutionPolicy, class NodeType, class RandomIt, class Predicate,
2115 std::enable_if_t<is_node_type_v<NodeType>, bool> = true,
2116 std::enable_if_t<pred::is_pred_v<Predicate>, bool> = true,
2117 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>, bool> = true>
2118 [[nodiscard]] std::vector<TraceResult> trace(
2119 ExecutionPolicy&& policy, NodeType node, RandomIt first, RandomIt last,
2120 Predicate const& pred, float min_dist = 0.0f,
2121 float max_dist = std::numeric_limits<float>::max(), bool only_exists = true) const
2122 {
2123 __block std::vector<TraceResult> res(std::distance(first, last));
2124 trace(std::forward<ExecutionPolicy>(policy), node, first, last, res.begin(), pred,
2125 min_dist, max_dist, only_exists);
2126 return res;
2127 }
2128
2129 /**************************************************************************************
2130 | |
2131 | Comparison |
2132 | |
2133 **************************************************************************************/
2134
2135 template <class Derived2, std::size_t Dim2, class... Blocks2>
2136 friend bool operator==(Tree<Derived2, Dim2, Blocks2...> const& lhs,
2137 Tree<Derived2, Dim2, Blocks2...> const& rhs);
2138
2139 template <class Derived2, std::size_t Dim2, class... Blocks2>
2140 friend bool operator!=(Tree<Derived2, Dim2, Blocks2...> const& lhs,
2141 Tree<Derived2, Dim2, Blocks2...> const& rhs);
2142
2143 protected:
2144 /**************************************************************************************
2145 | |
2146 | Constructors |
2147 | |
2148 **************************************************************************************/
2149
2150 Tree(Length leaf_node_length, depth_type num_depth_levels)
2151 {
2152 init(leaf_node_length, num_depth_levels);
2153 createRoot();
2154 }
2155
2156 Tree(length_type leaf_node_length, depth_type num_depth_levels)
2157 : Tree(Length(leaf_node_length), num_depth_levels)
2158 {
2159 }
2160
2161 Tree(Tree const&) = default;
2162
2163 Tree(Tree&&) = default;
2164
2165 /**************************************************************************************
2166 | |
2167 | Destructor |
2168 | |
2169 **************************************************************************************/
2170
2171 ~Tree() = default;
2172
2173 /**************************************************************************************
2174 | |
2175 | Assignment operator |
2176 | |
2177 **************************************************************************************/
2178
2179 Tree& operator=(Tree const&) = default;
2180
2181 Tree& operator=(Tree&&) = default;
2182
2183 /**************************************************************************************
2184 | |
2185 | Init |
2186 | |
2187 **************************************************************************************/
2188
2189 void init(Length leaf_node_length, depth_type num_depth_levels)
2190 {
2191 if (minNumDepthLevels() > num_depth_levels ||
2192 maxNumDepthLevels() < num_depth_levels) {
2193 throw std::invalid_argument("'num_depth_levels' has to be in range [" +
2194 std::to_string(+minNumDepthLevels()) + ".." +
2195 std::to_string(+maxNumDepthLevels()) + "], '" +
2196 std::to_string(+num_depth_levels) + "' was supplied.");
2197 }
2198
2199 if (length_type(0) >= ufo::min(leaf_node_length) || !isfinite(leaf_node_length)) {
2200 std::stringstream ss;
2201 ss << leaf_node_length;
2202 throw std::invalid_argument(
2203 "'leaf_node_length' has to be finite and greater than zero, '" + ss.str() +
2204 "' was supplied.");
2205 }
2206 if (!isnormal(ldexp(leaf_node_length, num_depth_levels - 1))) {
2207 std::stringstream ss;
2208 ss << ldexp(leaf_node_length, num_depth_levels - 1);
2209 throw std::invalid_argument(
2210 "'leaf_node_length * 2^(num_depth_levels - 1)' has to be finite and greater "
2211 "than zero, '" +
2212 ss.str() + "' was supplied.");
2213 }
2214 if (length_type(0) >= ufo::min(length_type(1) / ldexp(leaf_node_length, -1))) {
2215 std::stringstream ss;
2216 ss << (length_type(1) / ldexp(leaf_node_length, -1));
2217 throw std::invalid_argument(
2218 "The reciprocal of half 'leaf_node_length' (i.e., 1 / (leaf_node_length / "
2219 "2)) has to be a greater than zero, '" +
2220 ss.str() + "' was supplied.");
2221 }
2222
2223 num_depth_levels_ = num_depth_levels;
2224 half_max_value_ = key_type(1) << (num_depth_levels - 2);
2225
2226 // For increased precision
2227 for (int i{}; node_half_length_.size() > i; ++i) {
2228 node_half_length_[i] = ldexp(leaf_node_length, i - 1);
2229 node_half_length_reciprocal_[i] = length_type(1) / node_half_length_[i];
2230 }
2231 }
2232
2233 /**************************************************************************************
2234 | |
2235 | Derived |
2236 | |
2237 **************************************************************************************/
2238
2244 [[nodiscard]] constexpr Derived& derived() { return *static_cast<Derived*>(this); }
2245
2251 [[nodiscard]] constexpr Derived const& derived() const
2252 {
2253 return *static_cast<Derived const*>(this);
2254 }
2255
2256 /**************************************************************************************
2257 | |
2258 | Create root |
2259 | |
2260 **************************************************************************************/
2261
2262 void createRoot()
2263 {
2264 pos_type p = Data::innerCreate();
2265 InnerBlock& block = treeInnerBlock(p);
2266 block.children.fill(Index::NULL_POS);
2267 block.parent_block = Index::NULL_POS;
2268 block.parent_offset = {};
2269 block.depth = numDepthLevels() - 1;
2270 block.modified = MODIFIED_NONE_SET;
2271 }
2272
2273 /**************************************************************************************
2274 | |
2275 | Access |
2276 | |
2277 **************************************************************************************/
2278
2279 [[nodiscard]] LeafBlock& treeLeafBlock(pos_type block)
2280 {
2281 assert(isPureLeaf(block));
2282 return Data::template leafBlock<LeafBlock>(block);
2283 }
2284
2285 [[nodiscard]] LeafBlock const& treeLeafBlock(pos_type block) const
2286 {
2287 assert(isPureLeaf(block));
2288 return Data::template leafBlock<LeafBlock>(block);
2289 }
2290
2291 [[nodiscard]] LeafBlock const& treeLeafBlockConst(pos_type block) const
2292 {
2293 assert(isPureLeaf(block));
2294 return treeLeafBlock(block);
2295 }
2296
2297 [[nodiscard]] InnerBlock& treeInnerBlock(pos_type block)
2298 {
2299 assert(!isPureLeaf(block));
2300 return Data::template innerBlock<InnerBlock>(block);
2301 }
2302
2303 [[nodiscard]] InnerBlock const& treeInnerBlock(pos_type block) const
2304 {
2305 assert(!isPureLeaf(block));
2306 return Data::template innerBlock<InnerBlock>(block);
2307 }
2308
2309 [[nodiscard]] InnerBlock const& treeInnerBlockConst(pos_type block) const
2310 {
2311 assert(!isPureLeaf(block));
2312 return treeInnerBlock(block);
2313 }
2314
2315 /**************************************************************************************
2316 | |
2317 | Recurs |
2318 | |
2319 **************************************************************************************/
2320
2321 template <class UpdateFun,
2322 std::enable_if_t<std::is_invocable_r_v<bool, UpdateFun, Index, pos_type>,
2323 bool> = true>
2324 void recursUp(Index node, UpdateFun update_f)
2325 {
2326 assert(exists(node));
2327
2328 offset_type children = node.pos;
2329 node = parent(node);
2330 // BENCH: Is it faster to use `depth` than `valid` here?
2331 while (valid(node.pos) && update_f(node, children)) {
2332 children = node.pos;
2333 node = parent(treeInnerBlockConst(node.pos));
2334 }
2335 }
2336
2337 template <class UpdateFun,
2338 std::enable_if_t<std::is_invocable_r_v<bool, UpdateFun, Index, pos_type>,
2339 bool> = true>
2340 void recursDown(pos_type block, UpdateFun update_f)
2341 {
2342 assert(exists(block));
2343
2344 if (isPureLeaf(block)) {
2345 return;
2346 }
2347
2348 InnerBlock const& b = treeInnerBlockConst(block);
2349 for (offset_type i{}; BF > i; ++i) {
2350 if (pos_type c = children(b, i); valid(c) && update_f(Index(block, i), c)) {
2351 recursDown(c, update_f);
2352 }
2353 }
2354 }
2355
2356 template <class UpdateFun,
2357 std::enable_if_t<std::is_invocable_r_v<bool, UpdateFun, Index, pos_type>,
2358 bool> = true>
2359 void recursDown(Index node, UpdateFun update_f)
2360 {
2361 assert(exists(node));
2362
2363 if (isPureLeaf(node)) {
2364 return;
2365 }
2366
2367 if (pos_type c = children(node); valid(c) && update_f(node, c)) {
2368 recursDown(c, update_f);
2369 }
2370 }
2371
2372 template <
2373 class NodeFun, class BlockFun, class UpdateFun,
2374 std::enable_if_t<std::is_invocable_r_v<void, NodeFun, Index>, bool> = true,
2375 std::enable_if_t<std::is_invocable_r_v<void, BlockFun, pos_type>, bool> = true,
2376 std::enable_if_t<std::is_invocable_r_v<bool, UpdateFun, Index, pos_type>, bool> =
2377 true>
2378 void recursLeaves(pos_type block, NodeFun node_f, BlockFun block_f, UpdateFun update_f)
2379 {
2380 assert(exists(block));
2381
2382 if (isPureLeaf(block)) {
2383 modifiedSet(treeLeafBlock(block));
2384 block_f(block);
2385 return;
2386 }
2387
2388 InnerBlock& b = treeInnerBlock(block);
2389 modifiedSet(b);
2390
2391 if (allLeaf(b)) {
2392 block_f(block);
2393 return;
2394 }
2395
2396 for (offset_type i{}; BF > i; ++i) {
2397 Index n(block, i);
2398 if (pos_type c = children(b, i); valid(c)) {
2399 recursLeaves(c, node_f, block_f, update_f);
2400 update_f(n, c);
2401 } else {
2402 node_f(n);
2403 }
2404 }
2405 }
2406
2407 template <
2408 class NodeType, class NodeFun, class BlockFun, class UpdateFun,
2409 std::enable_if_t<is_node_type_v<NodeType>, bool> = true,
2410 std::enable_if_t<std::is_invocable_r_v<void, NodeFun, Index>, bool> = true,
2411 std::enable_if_t<std::is_invocable_r_v<void, BlockFun, pos_type>, bool> = true,
2412 std::enable_if_t<std::is_invocable_r_v<bool, UpdateFun, Index, pos_type>, bool> =
2413 true>
2414 void recursLeaves(NodeType node, NodeFun node_f, BlockFun block_f, UpdateFun update_f,
2415 bool propagate)
2416 {
2417 Index n = createThreadSafe(node);
2418
2419 if (isPureLeaf(n)) {
2420 modifiedSet(treeLeafBlock(n.pos), n.offset);
2421 node_f(n);
2422 } else {
2423 InnerBlock& block = treeInnerBlock(n.pos);
2424 modifiedSet(block, n.offset);
2425
2426 if (pos_type c = children(block, n.offset); valid(c)) {
2427 recursLeaves(c, node_f, block_f, update_f);
2428 update_f(n, c);
2429 } else {
2430 node_f(n);
2431 }
2432 }
2433
2434 if (propagate) {
2435 recursUp(n, update_f);
2436 }
2437 }
2438
2439 template <
2440 class BlockFun,
2441 std::enable_if_t<std::is_invocable_r_v<void, BlockFun, pos_type>, bool> = true>
2442 void recursParentFirst(pos_type block, BlockFun block_f)
2443 {
2444 assert(exists(block));
2445
2446 block_f(block);
2447
2448 if (isPureLeaf(block)) {
2449 modifiedSet(treeLeafBlock(block));
2450 return;
2451 }
2452
2453 InnerBlock& b = treeInnerBlock(block);
2454 modifiedSet(b);
2455
2456 for (offset_type i{}; BF > i; ++i) {
2457 if (pos_type c = children(b, i); valid(c)) {
2458 recursParentFirst(c, block_f);
2459 }
2460 }
2461 }
2462
2463 template <
2464 class NodeType, class NodeFun, class BlockFun, class UpdateFun,
2465 std::enable_if_t<is_node_type_v<NodeType>, bool> = true,
2466 std::enable_if_t<std::is_invocable_r_v<void, NodeFun, Index>, bool> = true,
2467 std::enable_if_t<std::is_invocable_r_v<void, BlockFun, pos_type>, bool> = true,
2468 std::enable_if_t<std::is_invocable_r_v<bool, UpdateFun, Index, pos_type>, bool> =
2469 true>
2470 void recursParentFirst(NodeType node, NodeFun node_f, BlockFun block_f,
2471 UpdateFun update_f, bool propagate)
2472 {
2473 Index n = createThreadSafe(node);
2474
2475 node_f(n);
2476
2477 if (isPureLeaf(n)) {
2478 modifiedSet(treeLeafBlock(n.pos), n.offset);
2479 } else {
2480 InnerBlock& block = treeInnerBlock(n.pos);
2481 modifiedSet(block, n.offset);
2482
2483 if (pos_type c = children(block, n.offset); valid(c)) {
2484 recursParentFirst(c, block_f);
2485 }
2486 }
2487
2488 if (propagate) {
2489 recursUp(n, update_f);
2490 }
2491 }
2492
2493 /**************************************************************************************
2494 | |
2495 | Leaf |
2496 | |
2497 **************************************************************************************/
2498
2499 [[nodiscard]] bool allLeaf([[maybe_unused]] LeafBlock const& block) const
2500 {
2501 return true;
2502 }
2503
2504 [[nodiscard]] bool allLeaf(InnerBlock const& block) const
2505 {
2506 return std::all_of(block.children.begin(), block.children.end(),
2507 [](pos_type e) { return Index::MAX_VALID_POS < e; });
2508 }
2509
2516 [[nodiscard]] bool allLeaf(pos_type block) const
2517 {
2518 return isPureLeaf(block) || allLeaf(treeInnerBlock(block));
2519 }
2520
2521 [[nodiscard]] bool anyLeaf([[maybe_unused]] LeafBlock const& block) const
2522 {
2523 return true;
2524 }
2525
2526 [[nodiscard]] bool anyLeaf(InnerBlock const& block) const
2527 {
2528 return std::any_of(block.children.begin(), block.children.end(),
2529 [](pos_type e) { return Index::MAX_VALID_POS < e; });
2530 }
2531
2538 [[nodiscard]] bool anyLeaf(pos_type block) const
2539 {
2540 return isPureLeaf(block) || anyLeaf(treeInnerBlock(block));
2541 }
2542
2549 [[nodiscard]] bool noneLeaf(pos_type block) const { return !anyLeaf(block); }
2550
2557 [[nodiscard]] bool allParent(pos_type block) const { return noneLeaf(block); }
2558
2565 [[nodiscard]] bool anyParent(pos_type block) const { return !allLeaf(block); }
2566
2573 [[nodiscard]] bool noneParent(pos_type block) const { return allLeaf(block); }
2574
2575 /**************************************************************************************
2576 | |
2577 | Center |
2578 | |
2579 **************************************************************************************/
2580
2581 //
2582 // Child center
2583 //
2584
2593 [[nodiscard]] static constexpr Point childCenter(Point center, Length half_length,
2594 offset_type child)
2595 {
2596 assert(BF > child);
2597 half_length /= length_type(2);
2598 for (std::size_t i{}; Point::size() > i; ++i) {
2599 center[i] += (child & offset_type(1u << i)) ? half_length[i] : -half_length[i];
2600 }
2601 return center;
2602 }
2603
2604 //
2605 // Parent center
2606 //
2607
2616 [[nodiscard]] static constexpr Point parentCenter(Point center, Length half_length,
2617 offset_type index)
2618 {
2619 assert(BF > index);
2620 for (std::size_t i{}; Point::size() > i; ++i) {
2621 center[i] += (index & offset_type(1u << i)) ? -half_length[i] : half_length[i];
2622 }
2623 return center;
2624 }
2625
2626 /**************************************************************************************
2627 | |
2628 | Create |
2629 | |
2630 **************************************************************************************/
2631
2632 void initLeafChildren(Index node, InnerBlock const& block, pos_type children)
2633 {
2634 LeafBlock& cb = treeLeafBlock(children);
2635 cb.parent_block = node.pos;
2636 cb.parent_offset = static_cast<std::uint8_t>(node.offset);
2637 modified(cb) = modified(block, node.offset) ? MODIFIED_ALL_SET : MODIFIED_NONE_SET;
2638
2639 derived().onInitLeafChildren(node, children);
2640 }
2641
2642 void initInnerChildren(Index node, InnerBlock const& block, pos_type children)
2643 {
2644 InnerBlock& cb = treeInnerBlock(children);
2645 cb.children.fill(Index::NULL_POS);
2646 cb.parent_block = node.pos;
2647 cb.parent_offset = static_cast<std::uint8_t>(node.offset);
2648 cb.depth = static_cast<std::uint8_t>(block.depth - 1);
2649 modified(cb) = modified(block, node.offset) ? MODIFIED_ALL_SET : MODIFIED_NONE_SET;
2650
2651 derived().onInitInnerChildren(node, children);
2652 }
2653
2654 pos_type createChildren(Index node)
2655 {
2656 assert(!isPureLeaf(node));
2657
2658 InnerBlock& block = treeInnerBlock(node.pos);
2659
2660 pos_type c = children(block, node.offset);
2661 assert(Index::PROCESSING_POS != c);
2662
2663 if (Index::NULL_POS == c) {
2664 if (1 == block.depth) {
2665 c = Data::leafCreate();
2666 initLeafChildren(node, block, c);
2667 } else {
2668 c = Data::innerCreate();
2669 initInnerChildren(node, block, c);
2670 }
2671 }
2672
2673 modifiedSet(block, node.offset);
2674
2675 block.children[node.offset] = c;
2676
2677 return c;
2678 }
2679
2680 pos_type createChildrenThreadSafe(Index node)
2681 {
2682 assert(!isPureLeaf(node));
2683
2684 InnerBlock& block = treeInnerBlock(node.pos);
2685
2686 auto cr = std::atomic_ref(block.children[node.offset]);
2687
2688 pos_type c = Index::NULL_POS;
2689 if (cr.compare_exchange_strong(c, Index::PROCESSING_POS, std::memory_order_relaxed)) {
2690 if (1 == block.depth) {
2691 c = Data::leafCreateThreadSafe();
2692 initLeafChildren(node, block, c);
2693 } else {
2694 c = Data::innerCreateThreadSafe();
2695 initInnerChildren(node, block, c);
2696 }
2697
2698 modifiedSetThreadSafe(block, node.offset);
2699
2700 cr.store(c, std::memory_order_release);
2701 cr.notify_all();
2702 } else if (valid(c)) {
2703 modifiedSetThreadSafe(block, node.offset);
2704 } else {
2705 cr.wait(Index::PROCESSING_POS, std::memory_order_relaxed);
2706 c = cr.load(std::memory_order_acquire);
2707 }
2708
2709 return c;
2710
2711 // pos_type c = cr.load(std::memory_order_relaxed);
2712
2713 // if (valid(c)) {
2714 // modifiedSetThreadSafe(block, node.offset);
2715 // } else if (Index::NULL_POS == c &&
2716 // cr.compare_exchange_strong(c, Index::PROCESSING_POS)) {
2717 // if (1 == block.depth) {
2718 // c = Data::leafCreateThreadSafe();
2719 // initLeafChildren(node, block, c);
2720 // } else {
2721 // c = Data::innerCreateThreadSafe();
2722 // initInnerChildren(node, block, c);
2723 // }
2724
2725 // modifiedSetThreadSafe(block, node.offset);
2726
2727 // cr.store(c, std::memory_order_release);
2728 // cr.notify_all();
2729 // } else {
2730 // cr.wait(Index::PROCESSING_POS, std::memory_order_relaxed);
2731 // c = cr.load(std::memory_order_acquire);
2732
2733 // // NOTE: We know that someone else will set modified
2734 // }
2735
2736 // return c;
2737 }
2738
2739 Index createChild(Index node, offset_type child_offset)
2740 {
2741 assert(!isPureLeaf(node));
2742 assert(BF > child_offset);
2743
2744 return Index(createChildren(node), child_offset);
2745 }
2746
2747 Index createChildThreadSafe(Index node, offset_type child_offset)
2748 {
2749 assert(!isPureLeaf(node));
2750 assert(BF > child_offset);
2751
2752 return Index(createChildrenThreadSafe(node), child_offset);
2753 }
2754
2755 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
2756 Index createThreadSafe(NodeType node)
2757 {
2758 assert(valid(node));
2759
2760 using T = remove_cvref_t<NodeType>;
2761 if constexpr (std::is_same_v<T, Index>) {
2762 assert(exists(node));
2763 modifiedSetParentsThreadSafe(node);
2764 return node;
2765 } else {
2766 Code code = this->code(node);
2767 auto wanted_depth = depth(code);
2768 auto cur_node = index();
2769 auto cur_depth = depth();
2770 while (wanted_depth < cur_depth) {
2771 cur_node = createChildThreadSafe(cur_node, code.offset(--cur_depth));
2772 }
2773 return cur_node;
2774 }
2775 }
2776
2777 /**************************************************************************************
2778 | |
2779 | Erase |
2780 | |
2781 **************************************************************************************/
2782
2783 void pruneChildren(Index node) { pruneChildren(node, children(node)); }
2784
2785 void pruneChildren(Index node, pos_type children)
2786 {
2787 assert(isParent(node) && this->children(node) == children);
2788
2789 InnerBlock& block = treeInnerBlock(node.pos);
2790 block.children[node.offset] = Index::NULL_POS;
2791
2792 // NOTE: Important that derived is pruned first in case they use parent
2793
2794 if (isPureLeaf(children)) {
2795 derived().onPruneLeafChildren(node, children);
2796 treeLeafBlock(children).parent_block = Index::INVALID_POS;
2797 Data::leafErase(children);
2798 } else {
2799 derived().onPruneInnerChildren(node, children);
2800 treeInnerBlock(children).parent_block = Index::INVALID_POS;
2801 Data::innerErase(children);
2802 }
2803 }
2804
2805 /**************************************************************************************
2806 | |
2807 | Nearest |
2808 | |
2809 **************************************************************************************/
2810
2811 // LOOKAT: Benchmark against only returning the distance
2812
2813 // TODO: Implement below correctly
2814
2815 template <bool OnlyDistance = false, bool FastAsSonic = false, class ValueFun,
2816 class InnerFun>
2817 [[nodiscard]] std::conditional_t<OnlyDistance, float, std::pair<float, Index>> nearest(
2818 Index node, NearestSearchAlgorithm search_alg, ValueFun value_f, InnerFun inner_f,
2819 float max_dist, float epsilon) const
2820 {
2821 // FIXME: Look at
2822 // assert(std::isfinite(max_dist));
2823 // assert(std::isfinite(epsilon));
2824
2825 std::conditional_t<OnlyDistance, float, std::pair<float, Index>> closest{};
2826 if constexpr (OnlyDistance) {
2827 closest = max_dist;
2828 } else {
2829 closest.first = max_dist;
2830 }
2831
2832 if (isParent(node) && max_dist >= inner_f(node)) {
2833 auto cb = children(node);
2834 auto cd = depth(cb);
2835
2836 // if (0.0f < epsilon) {
2837 // switch (search_alg) {
2838 // case NearestSearchAlgorithm::DEPTH_FIRST:
2839 closest = nearestDepthFirst<OnlyDistance, FastAsSonic>(cb, cd, max_dist, epsilon,
2840 value_f, inner_f);
2841 // case NearestSearchAlgorithm::A_STAR:
2842 // closest = nearestAStar(cb, cd, max_dist, epsilon, value_f, inner_f);
2843 // }
2844 // } else {
2845 // switch (search_alg) {
2846 // case NearestSearchAlgorithm::DEPTH_FIRST:
2847 // closest = nearestDepthFirst(cb, cd, max_dist, value_f, inner_f);
2848 // case NearestSearchAlgorithm::A_STAR:
2849 // closest = nearestAStar(cb, cd, max_dist, value_f, inner_f);
2850 // }
2851 // }
2852 }
2853
2854 if constexpr (!FastAsSonic) {
2855 max_dist = value_f(node);
2856 }
2857 assert(!std::isnan(max_dist));
2858 if constexpr (OnlyDistance) {
2859 return UFO_MIN(closest, max_dist);
2860 } else {
2861 return closest.first < max_dist ? closest : std::pair{max_dist, node};
2862 }
2863 }
2864
2865 template <class Predicate, class ValueFun, class InnerFun,
2866 std::enable_if_t<pred::is_pred_v<Predicate>, bool> = true>
2867 [[nodiscard]] std::pair<float, Index> nearest(Index node, Predicate pred,
2868 NearestSearchAlgorithm search_alg,
2869 ValueFun value_f, InnerFun inner_f,
2870 float max_dist, float epsilon) const
2871 {
2872 using Filter = pred::Filter<Predicate>;
2873
2874 Filter::init(pred, derived());
2875
2876 auto wrapped_value_f = [value_f, &pred](Index node) -> float {
2877 return Filter::returnable(pred) ? value_f(node)
2878 : std::numeric_limits<float>::infinity();
2879 };
2880
2881 auto wrapped_inner_f = [inner_f, &pred](Index node) -> float {
2882 return Filter::traversable(pred) ? inner_f(node)
2883 : std::numeric_limits<float>::infinity();
2884 };
2885
2886 return nearest(node, search_alg, wrapped_value_f, wrapped_inner_f, max_dist, epsilon);
2887 }
2888
2889 template <bool OnlyDistance, bool FastAsSonic, class ValueFun, class InnerFun>
2890 [[nodiscard]] std::conditional_t<OnlyDistance, float, std::pair<float, Index>>
2891 nearestDepthFirst(pos_type block, depth_type depth, float c_dist, float epsilon,
2892 ValueFun value_f, InnerFun inner_f) const
2893 {
2894 struct StackElement {
2895 using Container = std::array<std::pair<float, pos_type>, BF>;
2896 using Iterator = typename Container::iterator;
2897
2898 Container container;
2899 Iterator it;
2900
2901 [[nodiscard]] constexpr float& distance() { return it->first; }
2902
2903 [[nodiscard]] constexpr float const& distance() const { return it->first; }
2904
2905 [[nodiscard]] constexpr pos_type& block() { return it->second; }
2906
2907 [[nodiscard]] constexpr pos_type const& block() const { return it->second; }
2908
2909 constexpr void start() { it = container.begin(); }
2910
2911 [[nodiscard]] constexpr bool empty() { return container.end() == it; }
2912
2913 [[nodiscard]] constexpr bool empty() const { return container.end() == it; }
2914
2915 StackElement& operator++()
2916 {
2917 ++it;
2918 return *this;
2919 }
2920
2921 constexpr void sort()
2922 {
2923 if constexpr (2 == BF) {
2924 UFO_SORT_ASCENDING_PAIR_FIRST_2(container);
2925 } else if constexpr (4 == BF) {
2926 UFO_SORT_ASCENDING_PAIR_FIRST_4(container);
2927 } else if constexpr (8 == BF) {
2928 UFO_SORT_ASCENDING_PAIR_FIRST_8(container);
2929 } else if constexpr (16 == BF) {
2930 UFO_SORT_ASCENDING_PAIR_FIRST_16(container);
2931 } else {
2932 std::sort(container.begin(), container.end(),
2933 [](auto a, auto b) { return a.first < b.first; });
2934 }
2935 }
2936 };
2937
2938 using Stack = std::array<StackElement, maxNumDepthLevels() - 1>;
2939
2940 Stack stack;
2941 // Since we only have one block in the beginning we set the index to `BF - 1u` (the
2942 // last index)
2943 stack[depth].it = std::prev(stack[depth].container.end());
2944 // The first block to go through
2945 stack[depth].block() = block;
2946 // This distance does not matter as long as it is less than `c_dist - epsilon`, since
2947 // we only have one block in the beginning
2948 stack[depth].distance() = 0.0f;
2949
2950 std::conditional_t<OnlyDistance, bool, Index> c_node;
2951
2952 std::array<std::conditional_t<OnlyDistance, float, std::pair<float, offset_type>>, BF>
2953 d;
2954
2955 for (depth_type max_depth = depth + 1; max_depth > depth;) {
2956 StackElement& se = stack[depth];
2957
2958 if (se.empty() || c_dist - epsilon <= se.distance()) {
2959 ++depth;
2960 continue;
2961 }
2962
2963 block = se.block();
2964 ++se;
2965
2966 StackElement& cur = stack[depth - 1u];
2967
2968 cur.start();
2969
2970 for (std::size_t i{}; BF > i; ++i) {
2971 Index node(block, i);
2972 cur.container[i].first = inner_f(node);
2973 assert(!std::isnan(cur.container[i].first));
2974 cur.container[i].second = children(node);
2975
2976 if constexpr (!FastAsSonic) {
2977 if constexpr (OnlyDistance) {
2978 d[i] = value_f(node);
2979 assert(!std::isnan(d[i]));
2980 } else {
2981 d[i].first = value_f(node);
2982 assert(!std::isnan(d[i].first));
2983 d[i].second = i;
2984 }
2985 }
2986 }
2987
2988 if constexpr (!FastAsSonic) {
2989 if constexpr (OnlyDistance) {
2990 if constexpr (2 == BF) {
2991 UFO_MIN_2(d);
2992 } else if constexpr (4 == BF) {
2993 UFO_MIN_4(d);
2994 } else if constexpr (8 == BF) {
2995 UFO_MIN_8(d);
2996 } else if constexpr (16 == BF) {
2997 UFO_MIN_16(d);
2998 } else {
2999 for (std::size_t i = 1; BF > i; ++i) {
3000 d[0] = UFO_MIN(d[0], d[i]);
3001 }
3002 }
3003
3004 c_dist = c_dist <= d[0] ? c_dist : d[0];
3005 } else {
3006 if constexpr (2 == BF) {
3007 UFO_MIN_PAIR_FIRST_2(d);
3008 } else if constexpr (4 == BF) {
3009 UFO_MIN_PAIR_FIRST_4(d);
3010 } else if constexpr (8 == BF) {
3011 UFO_MIN_PAIR_FIRST_8(d);
3012 } else if constexpr (16 == BF) {
3013 UFO_MIN_PAIR_FIRST_16(d);
3014 } else {
3015 for (std::size_t i = 1; BF > i; ++i) {
3016 d[0] = UFO_MIN_PAIR_FIRST(d[0], d[i]);
3017 }
3018 }
3019
3020 c_node = c_dist <= d[0].first ? c_node : Index{block, d[0].second};
3021 c_dist = c_dist <= d[0].first ? c_dist : d[0].first;
3022 }
3023 }
3024
3025 if (1u == depth) {
3026 for (auto [dist, child_block] : cur.container) {
3027 if (c_dist <= dist + epsilon) {
3028 continue;
3029 }
3030
3031 if constexpr (OnlyDistance) {
3032 for (offset_type i{}; BF > i; ++i) {
3033 d[i] = value_f(Index(child_block, i));
3034 assert(!std::isnan(d[i]));
3035 }
3036
3037 if constexpr (2 == BF) {
3038 UFO_MIN_2(d);
3039 } else if constexpr (4 == BF) {
3040 UFO_MIN_4(d);
3041 } else if constexpr (8 == BF) {
3042 UFO_MIN_8(d);
3043 } else if constexpr (16 == BF) {
3044 UFO_MIN_16(d);
3045 } else {
3046 for (std::size_t i = 1; BF > i; ++i) {
3047 d[0] = UFO_MIN(d[0], d[i]);
3048 }
3049 }
3050
3051 c_dist = c_dist <= d[0] ? c_dist : d[0];
3052 } else {
3053 for (offset_type i{}; BF > i; ++i) {
3054 d[i].first = value_f(Index(child_block, i));
3055 assert(!std::isnan(d[i].first));
3056 d[i].second = i;
3057 }
3058
3059 if constexpr (2 == BF) {
3060 UFO_MIN_PAIR_FIRST_2(d);
3061 } else if constexpr (4 == BF) {
3062 UFO_MIN_PAIR_FIRST_4(d);
3063 } else if constexpr (8 == BF) {
3064 UFO_MIN_PAIR_FIRST_8(d);
3065 } else if constexpr (16 == BF) {
3066 UFO_MIN_PAIR_FIRST_16(d);
3067 } else {
3068 for (std::size_t i = 1; BF > i; ++i) {
3069 d[0] = UFO_MIN_PAIR_FIRST(d[0], d[i]);
3070 }
3071 }
3072
3073 c_node = c_dist <= d[0].first ? c_node : Index{child_block, d[0].second};
3074 c_dist = c_dist <= d[0].first ? c_dist : d[0].first;
3075 }
3076 }
3077 } else {
3078 cur.sort();
3079 --depth;
3080 }
3081 }
3082
3083 if constexpr (OnlyDistance) {
3084 return c_dist;
3085 } else {
3086 return {c_dist, c_node};
3087 }
3088 }
3089
3090 template <class ValueFun, class InnerFun>
3091 [[nodiscard]] std::pair<float, Index> nearestDepthFirst(pos_type block,
3092 depth_type depth, float c_dist,
3093 ValueFun value_f,
3094 InnerFun inner_f) const
3095 {
3096 using Stack =
3097 std::array<std::pair<std::size_t, std::array<std::pair<float, pos_type>, BF>>,
3098 maxNumDepthLevels() - 1>;
3099
3100 Stack stack;
3101 stack[depth].first = BF - 1u;
3102 stack[depth].second[BF - 1].first = 0.0f;
3103 stack[depth].second[BF - 1].second = block;
3104
3105 Index c_node;
3106
3107 for (depth_type max_depth = depth + 1; max_depth > depth;) {
3108 auto& [idx, c] = stack[depth];
3109
3110 if (BF <= idx || c_dist <= c[idx].first) {
3111 ++depth;
3112 continue;
3113 }
3114
3115 block = c[idx].second;
3116 ++idx;
3117
3118 stack[depth - 1].first = 0;
3119 auto& candidates = stack[depth - 1].second;
3120
3121 for (std::size_t i{}; BF > i; ++i) {
3122 Index node(block, i);
3123 candidates[i].first = inner_f(node);
3124 assert(!std::isnan(candidates[i].first));
3125 candidates[i].second = children(node);
3126 }
3127
3128 if (1u == depth) {
3129 std::array<std::pair<float, offset_type>, BF> d;
3130 for (auto [dist, child_block] : candidates) {
3131 if (c_dist <= dist) {
3132 continue;
3133 }
3134
3135 for (offset_type i{}; BF > i; ++i) {
3136 d[i].first = value_f(Index(child_block, i));
3137 assert(!std::isnan(d[i].first));
3138 d[i].second = i;
3139 }
3140
3141 if constexpr (2 == BF) {
3142 UFO_MIN_PAIR_FIRST_2(d);
3143 } else if constexpr (4 == BF) {
3144 UFO_MIN_PAIR_FIRST_4(d);
3145 } else if constexpr (8 == BF) {
3146 UFO_MIN_PAIR_FIRST_8(d);
3147 } else if constexpr (16 == BF) {
3148 UFO_MIN_PAIR_FIRST_16(d);
3149 } else {
3150 for (std::size_t i = 1; BF > i; ++i) {
3151 d[0] = UFO_MIN_PAIR_FIRST(d[0], d[i]);
3152 }
3153 }
3154
3155 c_node = c_dist <= d[0].first ? c_node : Index{child_block, d[0].second};
3156 c_dist = c_dist <= d[0].first ? c_dist : d[0].first;
3157 }
3158 } else {
3159 if constexpr (2 == BF) {
3160 UFO_SORT_ASCENDING_PAIR_FIRST_2(candidates);
3161 } else if constexpr (4 == BF) {
3162 UFO_SORT_ASCENDING_PAIR_FIRST_4(candidates);
3163 } else if constexpr (8 == BF) {
3164 UFO_SORT_ASCENDING_PAIR_FIRST_8(candidates);
3165 } else if constexpr (16 == BF) {
3166 UFO_SORT_ASCENDING_PAIR_FIRST_16(candidates);
3167 } else {
3168 std::sort(candidates.begin(), candidates.end(),
3169 [](auto a, auto b) { return a.first < b.first; });
3170 }
3171 --depth;
3172 }
3173 }
3174
3175 return {c_dist, c_node};
3176 }
3177
3178 // template <class ValueFun, class InnerFun>
3179 // [[nodiscard]] std::pair<float, Index> nearestAStar(pos_type block, depth_type depth,
3180 // float c_dist, float epsilon,
3181 // ValueFun value_f,
3182 // InnerFun inner_f) const
3183 // {
3184 // struct S {
3185 // float dist;
3186 // pos_type block;
3187 // depth_type depth;
3188
3189 // S(float dist, pos_type block, depth_type depth) noexcept
3190 // : dist(dist), block(block), depth(depth)
3191 // {
3192 // }
3193
3194 // bool operator>(S rhs) const noexcept
3195 // {
3196 // // return dist > rhs.dist;
3197 // return dist + (depth << 2) > rhs.dist + (rhs.depth << 2);
3198 // }
3199 // };
3200
3201 // using Queue = std::priority_queue<S, std::vector<S>, std::greater<S>>;
3202
3203 // std::vector<S> container;
3204 // container.reserve(1024);
3205 // Queue queue(std::greater<S>{}, std::move(container));
3206 // queue.emplace(0.0f, block, depth);
3207
3208 // auto max_size = depth << 2;
3209
3210 // Index c_node;
3211
3212 // while (!queue.empty()) {
3213 // auto cur = queue.top();
3214
3215 // if (c_dist + max_size - (cur.depth << 2) <= cur.dist + epsilon) {
3216 // return {c_dist, c_node};
3217 // }
3218
3219 // if (c_dist <= cur.dist + epsilon) {
3220 // queue.pop();
3221 // continue;
3222 // }
3223
3224 // queue.pop();
3225
3226 // block = cur.block;
3227 // depth = cur.depth;
3228
3229 // std::array<std::pair<float, pos_type>, BF> candidates;
3230 // for (std::size_t i{}; BF > i; ++i) {
3231 // Index node(block, i);
3232 // candidates[i].first = inner_f(node);
3233 // assert(!std::isnan(candidates[i].first));
3234 // candidates[i].second = children(node);
3235 // }
3236
3237 // if (1u == depth) {
3238 // std::array<std::pair<float, offset_type>, BF> d;
3239 // for (auto [dist, child_block] : candidates) {
3240 // if (c_dist <= dist + epsilon) {
3241 // continue;
3242 // }
3243
3244 // for (offset_type i{}; BF > i; ++i) {
3245 // d[i].first = value_f(Index(child_block, i));
3246 // assert(!std::isnan(d[i].first));
3247 // d[i].second = i;
3248 // }
3249
3250 // if constexpr (2 == BF) {
3251 // UFO_MIN_PAIR_FIRST_2(d);
3252 // } else if constexpr (4 == BF) {
3253 // UFO_MIN_PAIR_FIRST_4(d);
3254 // } else if constexpr (8 == BF) {
3255 // UFO_MIN_PAIR_FIRST_8(d);
3256 // } else if constexpr (16 == BF) {
3257 // UFO_MIN_PAIR_FIRST_16(d);
3258 // } else {
3259 // for (std::size_t i = 1; BF > i; ++i) {
3260 // d[0] = UFO_MIN_PAIR_FIRST(d[0], d[i]);
3261 // }
3262 // }
3263
3264 // c_node = c_dist <= d[0].first ? c_node : Index{child_block, d[0].second};
3265 // c_dist = c_dist <= d[0].first ? c_dist : d[0].first;
3266 // }
3267 // } else {
3268 // for (auto [dist, child_block] : candidates) {
3269 // if (c_dist <= dist + epsilon) {
3270 // continue;
3271 // }
3272 // queue.emplace(dist, child_block, depth - 1);
3273 // }
3274 // }
3275 // }
3276
3277 // return {c_dist, c_node};
3278 // }
3279
3280 // template <class ValueFun, class InnerFun>
3281 // [[nodiscard]] std::pair<float, Index> nearestAStar(pos_type block, depth_type depth,
3282 // float c_dist, ValueFun value_f,
3283 // InnerFun inner_f) const
3284 // {
3285 // struct S {
3286 // float dist;
3287 // pos_type block;
3288 // depth_type depth;
3289
3290 // S(float dist, pos_type block, depth_type depth) noexcept
3291 // : dist(dist), block(block), depth(depth)
3292 // {
3293 // }
3294
3295 // bool operator>(S rhs) const noexcept
3296 // {
3297 // // return dist > rhs.dist;
3298 // return dist + (depth << 2) > rhs.dist + (rhs.depth << 2);
3299 // }
3300 // };
3301
3302 // using Queue = std::priority_queue<S, std::vector<S>, std::greater<S>>;
3303
3304 // std::vector<S> container;
3305 // container.reserve(1024);
3306 // Queue queue(std::greater<S>{}, std::move(container));
3307 // queue.emplace(0.0f, block, depth);
3308
3309 // auto max_size = depth << 2;
3310
3311 // Index c_node;
3312
3313 // while (!queue.empty()) {
3314 // auto cur = queue.top();
3315
3316 // if (c_dist + max_size - (cur.depth << 2) <= cur.dist) {
3317 // return {c_dist, c_node};
3318 // }
3319
3320 // if (c_dist <= cur.dist) {
3321 // queue.pop();
3322 // continue;
3323 // }
3324
3325 // queue.pop();
3326
3327 // block = cur.block;
3328 // depth = cur.depth;
3329
3330 // std::array<std::pair<float, pos_type>, BF> candidates;
3331 // for (std::size_t i{}; BF > i; ++i) {
3332 // Index node(block, i);
3333 // candidates[i].first = inner_f(node);
3334 // assert(!std::isnan(candidates[i].first));
3335 // candidates[i].second = children(node);
3336 // }
3337
3338 // if (1u == depth) {
3339 // std::array<std::pair<float, offset_type>, BF> d;
3340 // for (auto [dist, child_block] : candidates) {
3341 // if (c_dist <= dist) {
3342 // continue;
3343 // }
3344
3345 // for (offset_type i{}; BF > i; ++i) {
3346 // d[i].first = value_f(Index(child_block, i));
3347 // assert(!std::isnan(d[i].first));
3348 // d[i].second = i;
3349 // }
3350
3351 // if constexpr (2 == BF) {
3352 // UFO_MIN_PAIR_FIRST_2(d);
3353 // } else if constexpr (4 == BF) {
3354 // UFO_MIN_PAIR_FIRST_4(d);
3355 // } else if constexpr (8 == BF) {
3356 // UFO_MIN_PAIR_FIRST_8(d);
3357 // } else if constexpr (16 == BF) {
3358 // UFO_MIN_PAIR_FIRST_16(d);
3359 // } else {
3360 // for (std::size_t i = 1; BF > i; ++i) {
3361 // d[0] = UFO_MIN_PAIR_FIRST(d[0], d[i]);
3362 // }
3363 // }
3364
3365 // c_node = c_dist <= d[0].first ? c_node : Index{child_block, d[0].second};
3366 // c_dist = c_dist <= d[0].first ? c_dist : d[0].first;
3367 // }
3368 // } else {
3369 // for (auto [dist, child_block] : candidates) {
3370 // if (c_dist <= dist) {
3371 // continue;
3372 // }
3373 // queue.emplace(dist, child_block, depth - 1);
3374 // }
3375 // }
3376 // }
3377
3378 // return {c_dist, c_node};
3379 // }
3380
3381 /**************************************************************************************
3382 | |
3383 | Trace |
3384 | |
3385 **************************************************************************************/
3386
3388 Ray ray;
3389 Point t0;
3390 Point t1;
3391 unsigned a{};
3392 };
3393
3395 Point t0;
3396 Point t1;
3397 Point tm;
3398 unsigned cur_node;
3399 Node node;
3400
3401 TraceStackElement() = default;
3402
3403 constexpr TraceStackElement(Node node, unsigned cur_node, Point const& t0,
3404 Point const& t1, Point const& tm)
3405 : node(node), cur_node(cur_node), t0(t0), t1(t1), tm(tm)
3406 {
3407 }
3408 };
3409
3410 template <class NodeType, std::enable_if_t<is_node_type_v<NodeType>, bool> = true>
3411 [[nodiscard]] TraceParams traceInit(NodeType node, Ray const& ray) const
3412 {
3413 return traceInit(ray, center(node), halfLength(node));
3414 }
3415
3416 [[nodiscard]] static constexpr TraceParams traceInit(Ray const& ray,
3417 Point const& center,
3418 Length half_length) noexcept
3419 {
3420 TraceParams params;
3421 params.ray = ray;
3422
3423 for (std::size_t i{}; Dim > i; ++i) {
3424 float origin = 0 > ray.direction[i] ? center[i] * 2 - ray.origin[i] : ray.origin[i];
3425
3426 auto a = center[i] - half_length[i] - origin;
3427 auto b = center[i] + half_length[i] - origin;
3428
3429 // FIXME: Look at
3430 params.t0[i] = 0 == ray.direction[i] ? 1e+25 * a : a / std::abs(ray.direction[i]);
3431 params.t1[i] = 0 == ray.direction[i] ? 1e+25 * b : b / std::abs(ray.direction[i]);
3432
3433 params.a |= unsigned(0 > ray.direction[i]) << i;
3434 }
3435
3436 return params;
3437 }
3438
3439 [[nodiscard]] static constexpr inline unsigned firstNode(Point const& tm,
3440 float const t) noexcept
3441 {
3442 unsigned node = static_cast<unsigned>(tm[0] < t);
3443 for (unsigned i = 1; Dim > i; ++i) {
3444 node |= static_cast<unsigned>(tm[i] < t) << i;
3445 }
3446 return node;
3447 }
3448
3449 [[nodiscard]] static constexpr inline unsigned newNode(unsigned cur,
3450 unsigned dim) noexcept
3451 {
3452 // You are at cur, you want to move along dim in positive direction
3453 unsigned x = 1u << dim;
3454 return ((cur & x) << Dim) | cur | x;
3455 }
3456
3457 template <class Predicate, std::enable_if_t<pred::is_pred_v<Predicate>, bool> = true>
3458 [[nodiscard]] constexpr TraceResult trace(Node node, TraceParams const& params,
3459 Predicate const& pred, float const near_clip,
3460 float const far_clip, bool only_exists) const
3461 {
3462 // TODO: Use `only_exists`
3463
3464 using Filter = pred::Filter<Predicate>;
3465
3466 auto returnable = [this, near_clip, far_clip, &pred](Node const& node, float min_dist,
3467 float max_dist) {
3468 return near_clip <= max_dist && far_clip >= min_dist &&
3469 Filter::returnable(pred, derived(), node);
3470 };
3471
3472 auto traversable = [this, near_clip, far_clip, &pred](
3473 Node const& node, float min_dist, float max_dist) {
3474 return near_clip <= max_dist && far_clip >= min_dist && isParent(node.index) &&
3475 Filter::traversable(pred, derived(), node);
3476 };
3477
3478 constexpr auto const new_node_lut = []() {
3479 std::array<std::array<unsigned, Dim>, BF> lut{};
3480 for (unsigned cur{}; BF != cur; ++cur) {
3481 for (unsigned dim{}; Dim != dim; ++dim) {
3482 lut[cur][dim] = newNode(cur, dim);
3483 }
3484 }
3485 return lut;
3486 }();
3487
3488 auto t0 = params.t0;
3489 auto t1 = params.t1;
3490 auto tm = (t0 + t1) * 0.5f;
3491 auto a = params.a;
3492
3493 auto min_dist = ufo::max(t0);
3494 auto max_dist = ufo::min(t1);
3495
3496 if (min_dist >= max_dist || near_clip > max_dist || far_clip < min_dist) {
3497 return TraceResult{Node(),
3498
3499 std::numeric_limits<float>::infinity()};
3500 } else if (returnable(node, min_dist, max_dist)) {
3501 float distance = std::max(near_clip, min_dist);
3502 return TraceResult{node, distance};
3503 } else if (!traversable(node, min_dist, max_dist)) {
3504 return TraceResult{Node(),
3505
3506 std::numeric_limits<float>::infinity()};
3507 }
3508
3509 unsigned cur_node = firstNode(tm, min_dist);
3510
3511 std::array<TraceStackElement, maxNumDepthLevels()> stack;
3512 stack[0] = TraceStackElement{node, cur_node, t0, t1, tm};
3513
3514 for (int idx{}; 0 <= idx;) {
3515 node = stack[idx].node;
3516 cur_node = stack[idx].cur_node;
3517 t0 = stack[idx].t0;
3518 t1 = stack[idx].t1;
3519 tm = stack[idx].tm;
3520
3521 // We have a need for speed and we don´t need safety here since we know all the
3522 // nodes exist and are valid
3523 node.code = child(node.code, cur_node ^ a);
3524 node.index = child(node.index, cur_node ^ a);
3525
3526 for (unsigned i{}; Dim > i; ++i) {
3527 t0[i] = (cur_node & (1u << i)) ? tm[i] : t0[i];
3528 t1[i] = (cur_node & (1u << i)) ? t1[i] : tm[i];
3529 }
3530
3531 stack[idx].cur_node = new_node_lut[cur_node][minIndex(t1)];
3532 idx -= BF <= stack[idx].cur_node;
3533
3534 min_dist = ufo::max(t0);
3535 max_dist = ufo::min(t1);
3536
3537 if (returnable(node, min_dist, max_dist)) {
3538 float distance = std::max(near_clip, min_dist);
3539 return TraceResult{node, distance};
3540 } else if (!traversable(node, min_dist, max_dist)) {
3541 continue;
3542 }
3543
3544 tm = (t0 + t1) * 0.5f;
3545
3546 unsigned cur_node = firstNode(tm, min_dist);
3547
3548 stack[++idx] = TraceStackElement{node, cur_node, t0, t1, tm};
3549 }
3550
3551 return TraceResult{Node(), std::numeric_limits<float>::infinity()};
3552 }
3553
3554 private:
3555 template <class NodeType>
3556 [[nodiscard]] constexpr auto convert(NodeType node) const
3557 {
3558 using T = remove_cvref_t<NodeType>;
3559 if constexpr (std::is_convertible_v<T, Index>) {
3560 return static_cast<Index>(node);
3561 } else if constexpr (std::is_convertible_v<T, Node>) {
3562 return static_cast<Node>(node);
3563 } else if constexpr (std::is_convertible_v<T, Code>) {
3564 return static_cast<Code>(node);
3565 } else if constexpr (std::is_convertible_v<T, Key>) {
3566 return static_cast<Key>(node);
3567 } else if constexpr (std::is_convertible_v<T, Coord>) {
3568 return static_cast<Coord>(node);
3569 } else if constexpr (std::is_constructible_v<T, Coord>) {
3570 return Coord(node);
3571 } else {
3572 static_assert(is_node_type_v<NodeType>, "Not one of the supported node types.");
3573 }
3574 }
3575
3576 /**************************************************************************************
3577 | |
3578 | Modified |
3579 | |
3580 **************************************************************************************/
3581
3582 [[nodiscard]] int modifiedCount(LeafBlock const& block) const
3583 {
3584 return std::popcount(modified(block));
3585 }
3586
3587 [[nodiscard]] int modifiedCount(InnerBlock const& block) const
3588 {
3589 return std::popcount(modified(block));
3590 }
3591
3592 [[nodiscard]] bool modifiedAll(LeafBlock const& block) const
3593 {
3594 return MODIFIED_ALL_SET == modified(block);
3595 }
3596
3597 [[nodiscard]] bool modifiedAll(InnerBlock const& block) const
3598 {
3599 return MODIFIED_ALL_SET == modified(block);
3600 }
3601
3602 [[nodiscard]] bool modifiedNone(LeafBlock const& block) const
3603 {
3604 return MODIFIED_NONE_SET == modified(block);
3605 }
3606
3607 [[nodiscard]] bool modifiedNone(InnerBlock const& block) const
3608 {
3609 return MODIFIED_NONE_SET == modified(block);
3610 }
3611
3612 [[nodiscard]] bool modified(LeafBlock const& block, offset_type offset) const
3613 {
3614 return modified_type(1) & (modified(block) >> offset);
3615 }
3616
3617 [[nodiscard]] bool modified(InnerBlock const& block, offset_type offset) const
3618 {
3619 return modified_type(1) & (modified(block) >> offset);
3620 }
3621
3622 [[nodiscard]] bool modified(pos_type block, offset_type offset) const
3623 {
3624 return isPureLeaf(block) ? modified(treeLeafBlock(block), offset)
3625 : modified(treeInnerBlock(block), offset);
3626 }
3627
3628 [[nodiscard]] modified_type& modified(LeafBlock& block) { return block.modified; }
3629
3630 [[nodiscard]] modified_type modified(LeafBlock const& block) const
3631 {
3632 return block.modified;
3633 }
3634
3635 [[nodiscard]] modified_type& modified(InnerBlock& block) { return block.modified; }
3636
3637 [[nodiscard]] modified_type modified(InnerBlock const& block) const
3638 {
3639 return block.modified;
3640 }
3641
3642 [[nodiscard]] modified_type& modified(pos_type block)
3643 {
3644 return isPureLeaf(block) ? modified(treeLeafBlock(block))
3645 : modified(treeInnerBlock(block));
3646 }
3647
3648 [[nodiscard]] modified_type modified(pos_type block) const
3649 {
3650 return isPureLeaf(block) ? modified(treeLeafBlock(block))
3651 : modified(treeInnerBlock(block));
3652 }
3653
3654 void modifiedSet(LeafBlock& block, offset_type offset)
3655 {
3656 modified(block) |= static_cast<modified_type>(1u << offset);
3657 }
3658
3659 void modifiedSet(InnerBlock& block, offset_type offset)
3660 {
3661 modified(block) |= static_cast<modified_type>(1u << offset);
3662 }
3663
3664 void modifiedSet(pos_type block, offset_type offset)
3665 {
3666 return isPureLeaf(block) ? modifiedSet(treeLeafBlock(block), offset)
3667 : modifiedSet(treeInnerBlock(block), offset);
3668 }
3669
3670 void modifiedSet(LeafBlock& block) { modified(block) = MODIFIED_ALL_SET; }
3671
3672 void modifiedSet(InnerBlock& block) { modified(block) = MODIFIED_ALL_SET; }
3673
3674 void modifiedSet(pos_type block)
3675 {
3676 return isPureLeaf(block) ? modifiedSet(treeLeafBlock(block))
3677 : modifiedSet(treeInnerBlock(block));
3678 }
3679
3680 void modifiedSetThreadSafe(LeafBlock& block, offset_type offset)
3681 {
3682 auto m = std::atomic_ref(modified(block));
3683 m.fetch_or(static_cast<modified_type>(1u << offset), std::memory_order_relaxed);
3684 }
3685
3686 void modifiedSetThreadSafe(InnerBlock& block, offset_type offset)
3687 {
3688 auto m = std::atomic_ref(modified(block));
3689 m.fetch_or(static_cast<modified_type>(1u << offset), std::memory_order_relaxed);
3690 }
3691
3692 void modifiedSetThreadSafe(pos_type block, offset_type offset)
3693 {
3694 return isPureLeaf(block) ? modifiedSetThreadSafe(treeLeafBlock(block), offset)
3695 : modifiedSetThreadSafe(treeInnerBlock(block), offset);
3696 }
3697
3698 void modifiedSetThreadSafe(LeafBlock& block)
3699 {
3700 auto m = std::atomic_ref(modified(block));
3701 m.store(MODIFIED_ALL_SET, std::memory_order_relaxed);
3702 }
3703
3704 void modifiedSetThreadSafe(InnerBlock& block)
3705 {
3706 auto m = std::atomic_ref(modified(block));
3707 m.store(MODIFIED_ALL_SET, std::memory_order_relaxed);
3708 }
3709
3710 void modifiedSetThreadSafe(pos_type block)
3711 {
3712 return isPureLeaf(block) ? modifiedSetThreadSafe(treeLeafBlock(block))
3713 : modifiedSetThreadSafe(treeInnerBlock(block));
3714 }
3715
3716 void modifiedReset(LeafBlock& block, offset_type offset)
3717 {
3718 modified(block) &= static_cast<modified_type>(~(1u << offset));
3719 }
3720
3721 void modifiedReset(InnerBlock& block, offset_type offset)
3722 {
3723 modified(block) &= static_cast<modified_type>(~(1u << offset));
3724 }
3725
3726 void modifiedReset(pos_type block, offset_type offset)
3727 {
3728 return isPureLeaf(block) ? modifiedSet(treeLeafBlock(block), offset)
3729 : modifiedSet(treeInnerBlock(block), offset);
3730 }
3731
3732 void modifiedReset(LeafBlock& block) { modified(block) = MODIFIED_NONE_SET; }
3733
3734 void modifiedReset(InnerBlock& block) { modified(block) = MODIFIED_NONE_SET; }
3735
3736 void modifiedReset(pos_type block)
3737 {
3738 return isPureLeaf(block) ? modifiedSet(treeLeafBlock(block))
3739 : modifiedSet(treeInnerBlock(block));
3740 }
3741
3742 void modifiedSetParents(Index node)
3743 {
3744 if (Index p = parent(node);
3745 !valid(p) || modified(treeInnerBlockConst(p.pos), p.offset)) {
3746 return;
3747 }
3748
3749 recursUp(node, [this](Index parent, [[maybe_unused]] pos_type children) -> bool {
3750 modified_type& m = modified(treeInnerBlock(parent.pos));
3751 modified_type prev = m;
3752 m |= static_cast<modified_type>(1u << parent.offset);
3753 return m != prev;
3754 });
3755 }
3756
3757 void modifiedSetParentsThreadSafe(Index node)
3758 {
3759 if (Index p = parent(node);
3760 !valid(p) || modified(treeInnerBlockConst(p.pos), p.offset)) {
3761 return;
3762 }
3763
3764 recursUp(node, [this](Index parent, [[maybe_unused]] pos_type children) -> bool {
3765 auto m = std::atomic_ref(modified(treeInnerBlock(parent.pos)));
3766 modified_type v = static_cast<modified_type>(1u << parent.offset);
3767 return v != (m.fetch_or(v, std::memory_order_relaxed) & v);
3768 });
3769 }
3770
3771 void modifiedSetChildren(Index node)
3772 {
3773 recursDown(node, [this]([[maybe_unused]] Index parent, pos_type children) -> bool {
3774 if (isPureLeaf(children)) {
3775 modifiedSet(treeLeafBlock(children));
3776 return false;
3777 } else {
3778 modified_type& m = modified(treeInnerBlock(children));
3779 modified_type prev = m;
3780 m = MODIFIED_ALL_SET;
3781 return m != prev;
3782 }
3783 });
3784 }
3785
3786 void modifiedResetChildren(Index node)
3787 {
3788 recursDown(node, [this]([[maybe_unused]] Index parent, pos_type children) -> bool {
3789 if (isPureLeaf(children)) {
3790 modifiedReset(treeLeafBlock(children));
3791 return false;
3792 } else {
3793 modified_type& m = modified(treeInnerBlock(children));
3794 modified_type prev = m;
3795 m = MODIFIED_NONE_SET;
3796 return m != prev;
3797 }
3798 });
3799 }
3800
3801 /**************************************************************************************
3802 | |
3803 | Children |
3804 | |
3805 **************************************************************************************/
3806
3807 [[nodiscard]] std::array<pos_type, BF> const& children(InnerBlock const& block) const
3808 {
3809 return block.children;
3810 }
3811
3812 [[nodiscard]] pos_type children(InnerBlock const& block, offset_type offset) const
3813 {
3814 return children(block)[offset];
3815 }
3816
3817 /**************************************************************************************
3818 | |
3819 | Parent |
3820 | |
3821 **************************************************************************************/
3822
3823 [[nodiscard]] Index parent(LeafBlock const& block) const
3824 {
3825 return Index(block.parent_block, block.parent_offset);
3826 }
3827
3828 [[nodiscard]] Index parent(InnerBlock const& block) const
3829 {
3830 return Index(block.parent_block, block.parent_offset);
3831 }
3832
3833 private:
3834 // The number of depth levels
3835 depth_type num_depth_levels_;
3836 // Half the maximum key value the tree can store
3837 key_type half_max_value_;
3838
3839 // Stores the node half length at a given depth, where the index is the depth
3840 std::array<Length, maxNumDepthLevels() + 1> node_half_length_;
3841 // Reciprocal of the node half length at a given depth, where the index is the depth
3842 std::array<Length, maxNumDepthLevels() + 1> node_half_length_reciprocal_;
3843};
3844
3845template <class Derived, std::size_t Dim, class... Blocks>
3846bool operator==(Tree<Derived, Dim, Blocks...> const& lhs,
3847 Tree<Derived, Dim, Blocks...> const& rhs)
3848{
3849 return lhs.num_depth_levels_ == rhs.num_depth_levels_ &&
3850 lhs.node_half_length_ == rhs.node_half_length_ &&
3851 std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(),
3852 [&lhs, &rhs](TreeNode<Dim> const& a, TreeNode<Dim> const& b) {
3853 return 0 != a.index.offset ||
3854 (a.code == b.code &&
3855 lhs.treeBlock(a.index) == rhs.treeBlock(b.index) &&
3856 ((lhs.template data<Blocks>(a.index.pos) ==
3857 rhs.template data<Blocks>(b.index.pos)) &&
3858 ...));
3859 });
3860}
3861
3862template <class Derived, std::size_t Dim, class... Blocks>
3863bool operator!=(Tree<Derived, Dim, Blocks...> const& lhs,
3864 Tree<Derived, Dim, Blocks...> const& rhs)
3865{
3866 return !(lhs == rhs);
3867}
3868} // namespace ufo
3869
3870#endif // UFO_CONTAINER_TREE_HPP
bool exists(pos_type block) const
Checks if a block exists.
Definition data.hpp:92
Utilizing curiously recurring template pattern (CRTP)
Definition tree.hpp:104
bool anyLeaf(pos_type block) const
Checks if any node of a block is a leaf.
Definition tree.hpp:2538
constexpr Coord center(NodeType node) const
Returns the center of node.
Definition tree.hpp:646
Coord center() const
Returns the center of the tree (/ root node).
Definition tree.hpp:637
constexpr pos_type block() const noexcept
Returns the block position of the root node.
Definition tree.hpp:743
std::optional< Coord > centerChecked(NodeType node) const
Returns the center of node if the node is valid (i.e., valid(node)).
Definition tree.hpp:682
void reserve(std::size_t num_nodes)
Increase the capacity of the tree to at least hold num_nodes nodes.
Definition tree.hpp:229
constexpr Length halfLength(NodeType node) const
Returns the half length of node, i.e. length(node) / 2.
Definition tree.hpp:408
bool valid(NodeType node) const
Checks if an index is valid.
Definition tree.hpp:1370
Length lengthReciprocal() const
Returns the reciprocal of the length of the tree (/ root node), i.e. 1 / length().
Definition tree.hpp:422
Length halfLength() const
Returns the half length of the tree (/ root node), i.e. length() / 2.
Definition tree.hpp:379
void traverse(UnaryFun f) const
Depth first traversal of the tree, starting at the root node. The function 'f' will be called for eac...
Definition tree.hpp:1617
Bounds bounds(NodeType node) const
Returns the bounds of node.
Definition tree.hpp:587
constexpr offset_type offset() const noexcept
Returns the offset of the root node.
Definition tree.hpp:770
void traverse(UnaryFun f, Predicate const &pred, bool only_exists=true) const
Depth first traversal of the tree, starting at the root node. The function 'f' will be called for eac...
Definition tree.hpp:1672
Node operator[](NodeType node) const
Get the node corresponding to a code.
Definition tree.hpp:882
bool isParent(NodeType node) const
Checks if the node is a parent (i.e., has children).
Definition tree.hpp:1308
bool isPureLeaf(pos_type block) const
Checks if the block is pure leaf (i.e., can never have children).
Definition tree.hpp:1256
Node node(NodeType node) const
Returns the node corresponding to node.
Definition tree.hpp:852
bool valid(pos_type block) const
Checks if a block is valid.
Definition tree.hpp:1361
std::size_t size() const
Returns the number of nodes in the tree.
Definition tree.hpp:218
Length halfLengthReciprocal(NodeType node) const
Returns the reciprocal of the half length of node, i.e. 1 / (length(node) / 2) = 2 / length(node).
Definition tree.hpp:500
Length halfLength(depth_type depth) const
Returns the half length of nodes at depth, i.e. length(depth) / 2.
Definition tree.hpp:392
depth_type depth() const
Returns the depth of the root node, i.e. numDepthLevels() - 1.
Definition tree.hpp:290
static constexpr Point childCenter(Point center, Length half_length, offset_type child)
Returns the center of the child_indexth child.
Definition tree.hpp:2593
void traverse(NodeType node, UnaryFun f, Predicate pred, bool only_exists=true) const
Depth first traversal of the tree, starting at node. The function 'f' will be called for each travers...
Definition tree.hpp:1690
Point max(NodeType node) const
Returns the maximum point of node.
Definition tree.hpp:551
bool noneParent(pos_type block) const
Checks if no nodes of a block are parents.
Definition tree.hpp:2573
bool isInside(Point coord) const
Checks if a coordinate is inside the tree bounds, i.e. inside bounds().
Definition tree.hpp:610
bool anyParent(pos_type block) const
Checks if any node of a block is a parent.
Definition tree.hpp:2565
Length lengthReciprocal(NodeType node) const
Returns the reciprocal of the length of node, i.e. 1 / length(node).
Definition tree.hpp:452
Length lengthReciprocal(depth_type depth) const
Returns the reciprocal of the length of nodes at depth, i.e. 1 / length(depth).
Definition tree.hpp:436
constexpr Index index() const noexcept
Returns the index of the root node.
Definition tree.hpp:803
constexpr auto child(NodeType node, offset_type offset) const
Returns the i:th child of node.
Definition tree.hpp:1450
pos_type block(NodeType node) const
Returns the block position of node.
Definition tree.hpp:756
Length length() const
Returns the length of the tree (/ root node), i.e. leaf_node_length * 2^depth().
Definition tree.hpp:342
auto childChecked(NodeType node, offset_type offset) const
Get a child of a node with bounds checking.
Definition tree.hpp:1480
bool allLeaf(pos_type block) const
Checks if all nodes of a block are leaves.
Definition tree.hpp:2516
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
constexpr bool isRoot(NodeType node) const
Checks if the node is the root of the tree.
Definition tree.hpp:1331
Length halfLengthReciprocal(depth_type depth) const
Returns the reciprocal of the half length of nodes at depth, i.e. 1 / (length(depth) / 2) = 2 / lengt...
Definition tree.hpp:483
depth_type depth(pos_type block) const
Returns the depth of the block.
Definition tree.hpp:300
Length length(NodeType node) const
Returns the length of node, i.e. leaf_node_length * 2^depth(node).
Definition tree.hpp:366
Length length(depth_type depth) const
Returns the length of nodes at depth, i.e. leaf_node_length * 2^depth.
Definition tree.hpp:353
static constexpr std::size_t dimensions() noexcept
Returns the number of dimensions of the tree (i.e., 1 = binary tree, 2 = quadtree,...
Definition tree.hpp:211
static constexpr depth_type maxNumDepthLevels() noexcept
Returns the maximum number of depth levels a tree can have.
Definition tree.hpp:278
bool allParent(pos_type block) const
Checks if all nodes of a block are parents.
Definition tree.hpp:2557
constexpr depth_type numDepthLevels() const noexcept
Returns the number of depth levels of the tree, i.e. depth() + 1.
Definition tree.hpp:261
Node node() const
Returns the root node.
Definition tree.hpp:843
constexpr depth_type depth(NodeType node) const
Returns the depth of the node.
Definition tree.hpp:314
constexpr Derived & derived()
Returns a reference of the derived class.
Definition tree.hpp:2244
Point min() const
Returns the minimum point of the tree (/ root node).
Definition tree.hpp:514
bool noneLeaf(pos_type block) const
Checks if no nodes of a block are leaves.
Definition tree.hpp:2549
coord_type centerAxis(NodeType node, std::size_t axis) const
Returns the center of node for the axis specified.
Definition tree.hpp:711
bool modified(NodeType node) const
Check if a node of the tree is in a modified state.
Definition tree.hpp:990
void clear()
Erases all nodes from the tree.
Definition tree.hpp:234
bool isLeaf(NodeType node) const
Checks if the node is a leaf (i.e., has no children).
Definition tree.hpp:1292
bool exists(NodeType node) const
Checks if a node exists.
Definition tree.hpp:1413
Point max() const
Returns the maximum point of the tree (/ root node).
Definition tree.hpp:533
coord_type centerAxis(std::size_t axis) const
Returns the center of the tree (/ root node) for the axis specified.
Definition tree.hpp:697
static constexpr depth_type minNumDepthLevels() noexcept
Returns the minimum number of depth levels a tree must have.
Definition tree.hpp:271
bool isPureLeaf(NodeType node) const
Checks if the node is a pure leaf (i.e., can never have children).
Definition tree.hpp:1271
bool modified() const
Check if the root of the tree is modified.
Definition tree.hpp:981
std::optional< coord_type > centerAxisChecked(NodeType node, std::size_t axis) const
Returns the center of node for the axis specified, if the node is valid (i.e., valid(node)).
Definition tree.hpp:727
Point min(NodeType node) const
Returns the minimum point of node.
Definition tree.hpp:523
Length halfLengthReciprocal() const
Returns the reciprocal of the half length of the tree (/ root node), i.e. 1 / (length() / 2) = 2 / le...
Definition tree.hpp:466
void traverse(NodeType node, UnaryFun f) const
Depth first traversal of the tree, starting at node. The function 'f' will be called for each travers...
Definition tree.hpp:1633
Bounds bounds() const
Returns the bounds of the tree (/ root node).
Definition tree.hpp:567
constexpr Derived const & derived() const
Returns a reference of the derived class.
Definition tree.hpp:2251
static constexpr Point parentCenter(Point center, Length half_length, offset_type index)
Returns the center of the parent of the node.
Definition tree.hpp:2616
offset_type offset(NodeType node) const
Returns the offset of node.
Definition tree.hpp:780
constexpr Vec< Dim, T > cast(Vec< Dim, U > const &v) noexcept
Casts each element of a vector to a new type.
Definition vec.hpp:1042
STL namespace.
All vision-related classes and functions.
Definition cloud.hpp:49
constexpr Vec< Dim, T > ldexp(Vec< Dim, T > v, int exp) noexcept
Multiplies each component of a floating-point vector by 2^exp.
Definition vec.hpp:1707
constexpr Vec< Dim, T > floor(Vec< Dim, T > v) noexcept
Returns the component-wise floor of a floating-point vector.
Definition vec.hpp:1404
constexpr T b(Lab< T, Flags > color) noexcept
Returns the un-weighted blue–yellow axis value.
Definition lab.hpp:326
constexpr bool isnormal(Vec< Dim, T > const &v) noexcept
Returns true if all components of a floating-point vector are normal.
Definition vec.hpp:1624
constexpr T a(Lab< T, Flags > color) noexcept
Returns the un-weighted green–red axis value.
Definition lab.hpp:310
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
Vec< 3, T > axis(Quat< T > const &q) noexcept
Extracts the unit rotation axis from a unit quaternion.
Definition quat.hpp:869
PointCloud< Dim, T, Rest... > transform(Transform< Dim, T > const &t, PointCloud< Dim, T, Rest... > pc)
Applies a rigid transform to every point position and returns the result.
constexpr bool isfinite(Vec< Dim, T > const &v) noexcept
Returns true if all components of a floating-point vector are finite.
Definition vec.hpp:1610
constexpr std::size_t minIndex(Vec< Dim, T > const &v) noexcept
Returns the index of the smallest element in a vector.
Definition vec.hpp:1283
constexpr auto distance(A const &a, B const &b)
Computes the minimum distance between two shapes.
Definition distance.hpp:61
Axis-Aligned Bounding Box (AABB) in Dim-dimensional space.
Definition aabb.hpp:70
Vec< Dim, T > direction
The direction of the ray.
Definition ray.hpp:79
Vec< Dim, T > origin
The origin of the ray.
Definition ray.hpp:72
static constexpr std::size_t size() noexcept
Returns the number of dimensions.
Definition vec.hpp:200