13#ifndef INCLUDE_AABBTREE_TREE_HXX
14#define INCLUDE_AABBTREE_TREE_HXX
35template <
typename Real, Integer N>
class Tree {
37 static_assert(std::is_floating_point<Real>::value,
38 "Tree Real type must be a floating-point type.");
39 static_assert(std::is_integral<Integer>::value,
40 "Tree dimension type must be an integer type.");
41 static_assert(N > 0,
"Tree dimension must be positive.");
88 os <<
"AABB TREE INFO" << std::endl
89 <<
"\tAmbient dimension : " << N << std::endl
90 <<
"\tBasic type : " <<
typeid(Real).name() << std::endl
91 <<
"\tObjects : " <<
objects << std::endl
92 <<
"\tNodes : " <<
nodes << std::endl
93 <<
"\tLeafs : " <<
leafs << std::endl
94 <<
"\tLong boxes : " <<
long_boxes << std::endl
95 <<
"\tDepth : " <<
depth << std::endl
96 <<
"\tLeft nodes : " <<
left_nodes << std::endl
97 <<
"\tLeft leafs : " <<
left_leafs << std::endl
99 <<
"\tLeft depth : " <<
left_depth << std::endl
120 std::priority_queue<QueueItem, std::vector<QueueItem>,
189 constexpr char CMD[]{
"AABBtree::Tree::max_dumpings(...): "};
191 CMD <<
"input must be a positive integer in the range [1, "
207 constexpr char CMD[]{
"AABBtree::Tree::max_nodal_objects(...): "};
209 CMD <<
"input must be a positive integer.");
224 constexpr char CMD[]{
"AABBtree::Tree::separation_ratio_tolerance(...): "};
226 CMD <<
"input must be in the range [0, 1].");
276 void build(std::unique_ptr<BoxUniquePtrList> boxes_ptr) {
278 m_boxes_ptr = std::move(boxes_ptr);
290 "AABBtree::Tree::build(...): The boxes pointer is "
291 "not valid. Please provide a valid pointer to the "
292 "bounding boxes before building the tree.");
322 m_stack.reserve(2 * num_boxes + 1);
337 if (
node.box_num <= 1) {
344 std::iota(sorting, sorting + N, 0);
346 return sizes[i] > sizes[j];
348 std::sort(sorting, sorting + N, compare);
350 Integer axis, n_long, n_left, n_right, id_ini, id_end;
351 Real separation_line, separation_tolerance;
355 Integer axis_saved{sorting[0]};
356 bool valid_axis_found{
false};
358 axis = sorting[dump];
359 separation_line =
node.box.baricenter(axis);
363 n_long = n_left = n_right = 0;
364 id_ini =
node.box_ptr;
365 id_end =
node.box_ptr +
node.box_num;
367 Real baricenter{0.0};
368 while (id_ini < id_end) {
371 box_id.
which_side(separation_line, separation_tolerance, axis)};
387 baricenter += box_id.
max()[axis] + box_id.
min()[axis];
389 baricenter /= 2.0 *
node.box_num;
392 Integer n_diff{std::abs(n_left - n_right)};
394 n_diff < n_diff_saved) ||
396 n_long_saved = n_long;
397 n_diff_saved = n_diff;
400 m_map.data() +
node.box_ptr);
401 valid_axis_found =
true;
410 "AABBtree::Tree::build(...): Failed to find a valid "
414 if (n_long_saved ==
node.box_num) {
419 std::copy_n(m_map.data() +
node.box_ptr,
node.box_num,
421 n_long = n_long_saved;
423 separation_line =
node.box.baricenter(axis);
427 n_left = n_right = 0;
428 id_ini =
node.box_ptr + n_long;
429 id_end =
node.box_ptr +
node.box_num;
430 while (id_ini < id_end) {
433 box_id.
which_side(separation_line, separation_tolerance, axis)};
473 node.box_num = n_long;
474 node.box_long.set_empty();
475 for (
Integer i{0}; i < n_long; ++i) {
481 for (
Integer i{0}; i < n_left; ++i) {
488 for (
Integer i{0}; i < n_right; ++i) {
512 template <
typename Object>
530 m_stack.emplace_back(0);
550 if (
node.box_num > 0) {
554 for (
Integer i{id_ini}; i < id_end; ++i) {
557 candidates.insert(pos);
563 if (
node.child_l > 0) {
566 if (
node.child_r > 0) {
572 return !candidates.empty();
606 auto negate = [](
Integer const id) {
return -1 - id; };
609 auto stack_emplace_back = [
this](
Integer const node_1,
621 stack_emplace_back(0, 0);
631 Integer const id_2{id_s2 < 0 ? negate(id_s2) : id_s2};
634 Integer const id_1{id_s1 < 0 ? negate(id_s1) : id_s1};
660 for (
Integer i{id_1_ini}; i < id_1_end; ++i) {
663 !boxes_1[pos_1]->intersects(node_2.
box_long)) {
666 for (
Integer j{id_2_ini}; j < id_2_end; ++j) {
669 boxes_1[pos_1]->intersects(*boxes_2[pos_2]))
670 candidates[pos_1].insert(pos_2);
674 for (
Integer j{id_2_ini}; j < id_2_end; ++j) {
677 !boxes_2[pos_2]->intersects(node_1.
box_long)) {
680 for (
Integer i{id_1_ini}; i < id_1_end; ++i) {
683 boxes_1[pos_1]->intersects(*boxes_2[pos_2]))
684 candidates[pos_1].insert(pos_2);
692 bool const leaf_1{node_1.
child_l < 0};
693 bool const leaf_2{node_2.
child_l < 0};
694 if (leaf_1 && leaf_2) {
699 stack_emplace_back(id_1, node_2.
child_l);
700 stack_emplace_back(id_1, node_2.
child_r);
702 stack_emplace_back(node_1.
child_l, id_2);
703 stack_emplace_back(node_1.
child_r, id_2);
708 stack_emplace_back(node_1.
child_l, id_s2);
709 stack_emplace_back(node_1.
child_r, id_s2);
711 stack_emplace_back(negate(id_1), id_2);
712 }
else if (id_s2 >= 0) {
713 stack_emplace_back(id_s1, node_2.
child_l);
714 stack_emplace_back(id_s1, node_2.
child_r);
718 stack_emplace_back(id_s1, node_2.
child_l);
719 stack_emplace_back(id_s1, node_2.
child_r);
721 stack_emplace_back(id_1, negate(id_2));
722 }
else if (id_s1 >= 0) {
723 stack_emplace_back(node_1.
child_l, id_s2);
724 stack_emplace_back(node_1.
child_r, id_s2);
731 return !candidates.empty();
760 auto negate = [](
Integer const id) {
return -1 - id; };
763 auto stack_emplace_back = [
this](
Integer const node_1,
768 stack_emplace_back(0, 0);
777 Integer const id_2{id_s2 < 0 ? negate(id_s2) : id_s2};
780 Integer const id_1{id_s1 < 0 ? negate(id_s1) : id_s1};
801 for (
Integer i{id_1_ini}; i < id_1_end; ++i) {
807 for (
Integer j{id_2_ini}; j < id_2_end; ++j) {
809 if (pos_1 == pos_2) {
814 candidates[pos_1].insert(pos_2);
818 for (
Integer j{id_2_ini}; j < id_2_end; ++j) {
824 for (
Integer i{id_1_ini}; i < id_1_end; ++i) {
826 if (pos_1 == pos_2) {
831 candidates[pos_1].insert(pos_2);
839 bool const leaf_1{node_1.
child_l < 0};
840 bool const leaf_2{node_2.
child_l < 0};
841 if (leaf_1 && leaf_2) {
846 stack_emplace_back(id_1, node_2.
child_l);
847 stack_emplace_back(id_1, node_2.
child_r);
849 stack_emplace_back(node_1.
child_l, id_2);
850 stack_emplace_back(node_1.
child_r, id_2);
855 stack_emplace_back(node_1.
child_l, id_s2);
856 stack_emplace_back(node_1.
child_r, id_s2);
858 stack_emplace_back(negate(id_1), id_2);
859 }
else if (id_s2 >= 0) {
860 stack_emplace_back(id_s1, node_2.
child_l);
861 stack_emplace_back(id_s1, node_2.
child_r);
865 stack_emplace_back(id_s1, node_2.
child_l);
866 stack_emplace_back(id_s1, node_2.
child_r);
868 stack_emplace_back(id_1, negate(id_2));
869 }
else if (id_s1 >= 0) {
870 stack_emplace_back(node_1.
child_l, id_s2);
871 stack_emplace_back(node_1.
child_r, id_s2);
878 return !candidates.empty();
889 bool intersects{this->
intersect(*
this, candidates_map)};
891 for (
const auto &[key, values] : candidates_map) {
892 for (
int value : values) {
893 candidates.emplace(key);
894 candidates.emplace(value);
909 template <
typename Object>
927 m_stack.emplace_back(0);
931 Real
distance{std::numeric_limits<Real>::infinity()};
943 Real tmp_distance{
node.box.interior_distance(obj)};
953 if (
node.box_num > 0) {
958 for (
Integer i{id_ini}; i < id_end; ++i) {
961 tmp_distance =
boxes[pos]->interior_distance(obj);
964 candidates.insert(pos);
966 }
else if (tmp_distance ==
distance) {
967 candidates.insert(pos);
974 if (
node.child_l > 0) {
977 if (
node.child_r > 0) {
1013 auto negate = [](
Integer const id) {
return -1 - id; };
1016 auto stack_emplace_back = [
this](
Integer const node_1,
1021 stack_emplace_back(0, 0);
1024 Real
distance{std::numeric_limits<Real>::infinity()};
1030 Integer const id_2{id_s2 >= 0 ? id_s2 : negate(id_s2)};
1033 Integer const id_1{id_s1 >= 0 ? id_s1 : negate(id_s1)};
1058 for (
Integer i{id_1_ini}; i < id_1_end; ++i) {
1061 tmp_distance = boxes_1[pos_1]->interior_distance(node_2.
box_long);
1065 for (
Integer j{id_2_ini}; j < id_2_end; ++j) {
1069 boxes_1[pos_1]->interior_distance(*boxes_2[pos_2]);
1072 candidates[pos_1].insert(pos_2);
1074 }
else if (tmp_distance ==
distance) {
1075 candidates[pos_1].insert(pos_2);
1080 for (
Integer j{id_2_ini}; j < id_2_end; ++j) {
1083 tmp_distance = boxes_2[pos_2]->interior_distance(node_1.
box_long);
1087 for (
Integer i{id_1_ini}; i < id_1_end; ++i) {
1091 boxes_1[pos_1]->interior_distance(*boxes_2[pos_2]);
1094 candidates[pos_1].insert(pos_2);
1096 }
else if (tmp_distance ==
distance) {
1097 candidates[pos_1].insert(pos_2);
1106 bool const leaf_1{node_1.
child_l < 0};
1107 bool const leaf_2{node_2.
child_l < 0};
1108 if (leaf_1 && leaf_2) {
1114 stack_emplace_back(id_1, node_2.
child_l);
1115 stack_emplace_back(id_1, node_2.
child_r);
1116 }
else if (leaf_2) {
1117 stack_emplace_back(node_1.
child_l, id_2);
1118 stack_emplace_back(node_1.
child_r, id_2);
1123 stack_emplace_back(node_1.
child_l, id_s2);
1124 stack_emplace_back(node_1.
child_r, id_s2);
1126 stack_emplace_back(negate(id_1), id_2);
1127 }
else if (id_s2 >= 0) {
1128 stack_emplace_back(id_s1, node_2.
child_l);
1129 stack_emplace_back(id_s1, node_2.
child_r);
1133 stack_emplace_back(id_s1, node_2.
child_l);
1134 stack_emplace_back(id_s1, node_2.
child_r);
1136 stack_emplace_back(id_1, negate(id_2));
1137 }
else if (id_s1 >= 0) {
1138 stack_emplace_back(node_1.
child_l, id_s2);
1139 stack_emplace_back(node_1.
child_r, id_s2);
1162 template <
typename Object,
typename Function = std::function<
1163 Real(Object
const &,
Box const &)>>
1166 Function distance_function = [](Object
const &o,
Box const &b) {
1188 using Pair = std::pair<Real, Integer>;
1189 auto cmp = [](
const Pair &a,
const Pair &b) {
return a.first < b.first; };
1190 std::priority_queue<Pair, std::vector<Pair>,
decltype(cmp)> queue(cmp);
1194 std::numeric_limits<Real>::infinity()};
1206 Real tmp_distance{distance_function(obj,
node.box)};
1215 if (
node.box_num > 0) {
1218 for (
Integer i{id_ini}; i < id_end; ++i) {
1221 tmp_distance = distance_function(obj, *
boxes[pos]);
1223 if (
static_cast<Integer>(queue.size()) < n) {
1224 queue.emplace(tmp_distance, pos);
1227 queue.emplace(tmp_distance, pos);
1235 if (
node.child_l > 0) {
1238 if (
node.child_r > 0) {
1244 Real min_distance{queue.empty() ?
distance : queue.top().first};
1245 while (!queue.empty()) {
1246 candidates.insert(queue.top().second);
1249 return min_distance;
1265 template <
typename Object,
typename Function = std::function<
1266 Real(Object
const &,
Box const &)>>
1268 Object
const &obj, Real
const max_distance,
IndexSet &candidates,
1269 Function distance_function = [](Object
const &o,
Box const &b) {
1311 if (
node.box_num > 0) {
1314 for (
Integer i{id_ini}; i < id_end; ++i) {
1319 candidates.insert(pos);
1325 if (
node.child_l > 0) {
1328 if (
node.child_r > 0) {
1334 return !candidates.empty();
1349 m_stack.emplace_back(i);
1350 std::vector<Integer> depth_stack;
1351 depth_stack.reserve(2 * this->
size() + 1);
1352 depth_stack.emplace_back(0);
1359 depth_stack.pop_back();
1360 if (
node.child_l == -1) {
1361 d = std::max(d,
depth);
1364 depth_stack.emplace_back(
depth + 1);
1366 if (
node.child_r == -1) {
1367 d = std::max(d,
depth);
1370 depth_stack.emplace_back(
depth + 1);
1390 m_stack.emplace_back(i);
1395 if (
node.child_l == -1) {
1401 if (
node.child_r == -1) {
1423 this->
nodes(m_tree_structure[0].child_l,
stats.left_leafs,
stats.left_nodes,
1424 stats.left_long_boxes);
1425 this->
depth(m_tree_structure[0].child_l,
stats.left_depth);
1426 this->
nodes(m_tree_structure[0].child_r,
stats.right_leafs,
1428 this->
depth(m_tree_structure[0].child_r,
stats.right_depth);
1430 stats.balance_ratio =
static_cast<Real
>(
stats.left_leafs) /
1431 static_cast<Real
>(
stats.right_leafs);
1432 stats.depth_ratio =
static_cast<Real
>(
stats.left_depth) /
1433 static_cast<Real
>(
stats.right_depth);
1436 stats.check_counter =
#define AABBTREE_ASSERT(COND, MSG)
Definition AABBtree.hh:48
#define AABBTREE_ASSERT_WARNING(COND, MSG)
Definition AABBtree.hh:64
A class representing an axis-aligned bounding box (AABB) in N-dimensional space.
Definition Box.hxx:50
Box & extend(Point const &p)
Definition Box.hxx:511
void set_empty()
Definition Box.hxx:333
Side which_side(Real const x, Real const tol, Integer const dim) const
Definition Box.hxx:447
Real interior_distance(Point const &p) const
Definition Box.hxx:576
Point const & min() const
Definition Box.hxx:176
Side
Definition Box.hxx:437
@ RIGHT
Definition Box.hxx:437
@ LEFT
Definition Box.hxx:437
bool intersects(Box const &b) const
Definition Box.hxx:343
Point const & max() const
Definition Box.hxx:188
Integer m_long_check_counter
Definition Tree.hxx:151
Integer max_nodal_objects() const
Definition Tree.hxx:217
PriorityQueue m_queue
Definition Tree.hxx:157
Real closest(Object const &obj, Integer const n, IndexSet &candidates, Function distance_function=[](Object const &o, Box const &b) { return b.interior_distance(o);}) const
Definition Tree.hxx:1164
bool intersect(Tree const &tree, IndexMap &candidates) const
Definition Tree.hxx:581
void build(std::unique_ptr< BoxUniquePtrList > boxes_ptr)
Definition Tree.hxx:276
Integer max_dumpings() const
Definition Tree.hxx:200
Integer size() const
Definition Tree.hxx:255
AABBtree::BoxUniquePtr< Real, N > BoxUniquePtr
Definition Tree.hxx:114
AABBtree::Point< Real, N > Point
Definition Tree.hxx:117
void max_dumpings(Integer const max_dumpings)
Definition Tree.hxx:188
std::unique_ptr< BoxUniquePtrList > m_boxes_ptr
Definition Tree.hxx:138
Integer m_objs_check_counter
Definition Tree.hxx:152
void build()
Definition Tree.hxx:286
bool within_distance(Object const &obj, Real const max_distance, IndexSet &candidates, Function distance_function=[](Object const &o, Box const &b) { return b.interior_distance(o);}) const
Definition Tree.hxx:1267
bool self_intersect(IndexSet &candidates) const
Definition Tree.hxx:887
void clear()
Definition Tree.hxx:266
std::tuple< Integer, Integer, Real > QueueItem
Definition Tree.hxx:118
Integer m_max_nodal_objects
Definition Tree.hxx:146
BoxUniquePtr const & box(Integer const i) const
Definition Tree.hxx:182
AABBtree::BoxUniquePtrList< Real, N > BoxUniquePtrList
Definition Tree.hxx:115
bool self_intersect(IndexMap &candidates) const
Definition Tree.hxx:739
void nodes(Integer const i, Integer &l, Integer &n, Integer &b) const
Definition Tree.hxx:1383
Real separation_ratio_tolerance() const
Definition Tree.hxx:234
AABBtree::Box< Real, N > Box
Definition Tree.hxx:113
void depth(Integer const i, Integer &d) const
Definition Tree.hxx:1342
Integer m_node_check_counter
Definition Tree.hxx:150
std::vector< Node > const & structure() const
Definition Tree.hxx:242
Real m_separation_ratio_tolerance
Definition Tree.hxx:147
Node const & node(Integer const i) const
Definition Tree.hxx:249
Integer m_dump_counter
Definition Tree.hxx:153
void max_nodal_objects(Integer const max_nodal_objects)
Definition Tree.hxx:206
IndexList m_tree_boxes_map
Definition Tree.hxx:141
Real distance(Object const &obj, IndexSet &candidates) const
Definition Tree.hxx:910
Integer m_max_dumpings
Definition Tree.hxx:145
void print(OutStream &os) const
Definition Tree.hxx:1447
Real distance(Tree const &tree, IndexMap &candidates) const
Definition Tree.hxx:992
IndexList m_stack
Definition Tree.hxx:156
void stats(Statistics &stats) const
Definition Tree.hxx:1415
bool is_empty() const
Definition Tree.hxx:261
void separation_ratio_tolerance(Real const ratio)
Definition Tree.hxx:223
BoxUniquePtrList const & boxes() const
Definition Tree.hxx:175
std::priority_queue< QueueItem, std::vector< QueueItem >, std::function< bool(QueueItem, QueueItem)> > PriorityQueue
Definition Tree.hxx:119
AABBtree::Vector< Real, N > Vector
Definition Tree.hxx:116
bool intersect(Object const &obj, IndexSet &candidates) const
Definition Tree.hxx:513
std::vector< Node > m_tree_structure
Definition Tree.hxx:140
Namespace for the AABBtree library.
Definition AABBtree.hh:81
std::basic_ostream< char > OutStream
Definition AABBtree.hh:96
Eigen::Vector< Real, N > Point
Definition AABBtree.hh:105
std::map< Integer, IndexSet > IndexMap
Definition AABBtree.hh:94
std::set< Integer > IndexSet
Definition AABBtree.hh:93
std::unique_ptr< Box< Real, N > > BoxUniquePtr
Definition AABBtree.hh:101
std::vector< BoxUniquePtr< Real, N > > BoxUniquePtrList
Definition AABBtree.hh:103
std::vector< Integer > IndexList
Definition AABBtree.hh:95
Eigen::Vector< Real, N > Vector
Definition AABBtree.hh:104
AABBTREE_DEFAULT_INTEGER_TYPE Integer
The Integer type used in the AABBtree class.
Definition AABBtree.hh:89
Integer parent
Definition Tree.hxx:132
Box box_long
Definition Tree.hxx:128
Box box
Definition Tree.hxx:127
Integer child_l
Definition Tree.hxx:133
Integer box_num
Definition Tree.hxx:130
Integer box_tot_num
Definition Tree.hxx:131
Integer child_r
Definition Tree.hxx:134
Integer box_ptr
Definition Tree.hxx:129
Integer right_long_boxes
Definition Tree.hxx:59
void reset() noexcept
Definition Tree.hxx:80
Integer check_counter
Definition Tree.hxx:66
Integer right_leafs
Definition Tree.hxx:58
Integer depth
Definition Tree.hxx:52
Real depth_ratio
Definition Tree.hxx:63
Integer right_nodes
Definition Tree.hxx:57
Integer nodes
Definition Tree.hxx:49
Integer long_check_counter
Definition Tree.hxx:68
Integer long_boxes
Definition Tree.hxx:51
Integer node_check_counter
Definition Tree.hxx:67
Integer left_leafs
Definition Tree.hxx:54
Integer dump_counter
Definition Tree.hxx:61
Integer left_nodes
Definition Tree.hxx:53
Integer objs_check_counter
Definition Tree.hxx:69
Integer leafs
Definition Tree.hxx:50
Integer left_long_boxes
Definition Tree.hxx:55
void print(OutStream &os) const
Definition Tree.hxx:86
Integer right_depth
Definition Tree.hxx:60
Real balance_ratio
Definition Tree.hxx:62
Integer left_depth
Definition Tree.hxx:56
Integer objects
Definition Tree.hxx:48