coal 3.0.1
Coal, The Collision Detection Library. Previously known as HPP-FCL, fork of FCL -- The Flexible Collision Library
Loading...
Searching...
No Matches
hierarchy_tree-inl.h
Go to the documentation of this file.
1/*
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2011-2014, Willow Garage, Inc.
5 * Copyright (c) 2014-2016, Open Source Robotics Foundation
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer in the documentation and/or other materials provided
17 * with the distribution.
18 * * Neither the name of Open Source Robotics Foundation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 */
35
38#ifndef COAL_HIERARCHY_TREE_INL_H
39#define COAL_HIERARCHY_TREE_INL_H
40
42
43namespace coal {
44
45namespace detail {
46
47//==============================================================================
48template <typename BV>
49HierarchyTree<BV>::HierarchyTree(int bu_threshold_, int topdown_level_) {
50 root_node = nullptr;
51 n_leaves = 0;
52 free_node = nullptr;
53 max_lookahead_level = -1;
54 opath = 0;
55 bu_threshold = bu_threshold_;
56 topdown_level = topdown_level_;
57}
58
59//==============================================================================
60template <typename BV>
64
65//==============================================================================
66template <typename BV>
67void HierarchyTree<BV>::init(std::vector<Node*>& leaves, int level) {
68 switch (level) {
69 case 0:
70 init_0(leaves);
71 break;
72 case 1:
73 init_1(leaves);
74 break;
75 case 2:
76 init_2(leaves);
77 break;
78 case 3:
79 init_3(leaves);
80 break;
81 default:
82 init_0(leaves);
83 }
84}
85
86//==============================================================================
87template <typename BV>
89 void* data) {
90 Node* leaf = createNode(nullptr, bv, data);
91 insertLeaf(root_node, leaf);
92 ++n_leaves;
93 return leaf;
94}
95
96//==============================================================================
97template <typename BV>
99 removeLeaf(leaf);
100 deleteNode(leaf);
101 --n_leaves;
102}
103
104//==============================================================================
105template <typename BV>
107 if (root_node) recurseDeleteNode(root_node);
108 n_leaves = 0;
109 delete free_node;
110 free_node = nullptr;
111 max_lookahead_level = -1;
112 opath = 0;
113}
114
115//==============================================================================
116template <typename BV>
118 return (nullptr == root_node);
119}
120
121//==============================================================================
122template <typename BV>
123void HierarchyTree<BV>::update(Node* leaf, int lookahead_level) {
124 // TODO(DamrongGuoy): Since we update a leaf node by removing and
125 // inserting the same leaf node, it is likely to change the structure of
126 // the tree even if no object's pose has changed. In the future,
127 // find a way to preserve the structure of the tree to solve this issue:
128 // https://github.com/flexible-collision-library/fcl/issues/368
129
130 // First we remove the leaf node pointed by `leaf` variable from the tree.
131 // The `sub_root` variable is the root of the subtree containing nodes
132 // whose BVs were adjusted due to node removal.
133 typename HierarchyTree<BV>::Node* sub_root = removeLeaf(leaf);
134 if (sub_root) {
135 if (lookahead_level > 0) {
136 // For positive `lookahead_level`, we move the `sub_root` variable up.
137 for (int i = 0; (i < lookahead_level) && sub_root->parent; ++i)
138 sub_root = sub_root->parent;
139 } else
140 // By default, lookahead_level = -1, and we reset the `sub_root` variable
141 // to the root of the entire tree.
142 sub_root = root_node;
143 }
144 // Then we insert the node pointed by `leaf` variable back into the
145 // subtree rooted at `sub_root` variable.
146 insertLeaf(sub_root, leaf);
147}
148
149//==============================================================================
150template <typename BV>
151bool HierarchyTree<BV>::update(Node* leaf, const BV& bv) {
152 if (leaf->bv.contain(bv)) return false;
153 update_(leaf, bv);
154 return true;
155}
156
157//==============================================================================
158template <typename S, typename BV>
160 static bool run(const HierarchyTree<BV>& tree,
161 typename HierarchyTree<BV>::Node* leaf, const BV& bv,
162 const Vec3s& /*vel*/, Scalar /*margin*/) {
163 if (leaf->bv.contain(bv)) return false;
164 tree.update_(leaf, bv);
165 return true;
166 }
167
168 static bool run(const HierarchyTree<BV>& tree,
169 typename HierarchyTree<BV>::Node* leaf, const BV& bv,
170 const Vec3s& /*vel*/) {
171 if (leaf->bv.contain(bv)) return false;
172 tree.update_(leaf, bv);
173 return true;
174 }
175};
176
177//==============================================================================
178template <typename BV>
179bool HierarchyTree<BV>::update(Node* leaf, const BV& bv, const Vec3s& vel,
180 Scalar margin) {
181 return UpdateImpl<Scalar, BV>::run(*this, leaf, bv, vel, margin);
182}
183
184//==============================================================================
185template <typename BV>
186bool HierarchyTree<BV>::update(Node* leaf, const BV& bv, const Vec3s& vel) {
187 return UpdateImpl<Scalar, BV>::run(*this, leaf, bv, vel);
188}
189
190//==============================================================================
191template <typename BV>
193 if (!root_node) return 0;
194 return getMaxHeight(root_node);
195}
196
197//==============================================================================
198template <typename BV>
200 if (!root_node) return 0;
201
202 size_t max_depth;
203 getMaxDepth(root_node, 0, max_depth);
204 return max_depth;
205}
206
207//==============================================================================
208template <typename BV>
210 if (root_node) {
211 std::vector<Node*> leaves;
212 leaves.reserve(n_leaves);
213 fetchLeaves(root_node, leaves);
214 bottomup(leaves.begin(), leaves.end());
215 root_node = leaves[0];
216 }
217}
218
219//==============================================================================
220template <typename BV>
222 if (root_node) {
223 std::vector<Node*> leaves;
224 leaves.reserve(n_leaves);
225 fetchLeaves(root_node, leaves);
226 root_node = topdown(leaves.begin(), leaves.end());
227 }
228}
229
230//==============================================================================
231template <typename BV>
233 if (iterations < 0) iterations = (int)n_leaves;
234 if (root_node && (iterations > 0)) {
235 for (int i = 0; i < iterations; ++i) {
236 Node* node = root_node;
237 unsigned int bit = 0;
238 while (!node->isLeaf()) {
239 node = sort(node, root_node)->children[(opath >> bit) & 1];
240 bit = (bit + 1) & (sizeof(unsigned int) * 8 - 1);
241 }
242 update(node);
243 ++opath;
244 }
245 }
246}
247
248//==============================================================================
249template <typename BV>
251 if (root_node) recurseRefit(root_node);
252}
253
254//==============================================================================
255template <typename BV>
257 std::vector<Node*>& leaves) const {
258 if (!root->isLeaf()) {
259 extractLeaves(root->children[0], leaves);
260 extractLeaves(root->children[1], leaves);
261 } else
262 leaves.push_back(root);
263}
264
265//==============================================================================
266template <typename BV>
268 return n_leaves;
269}
270
271//==============================================================================
272template <typename BV>
274 return root_node;
275}
276
277//==============================================================================
278template <typename BV>
280 return root_node;
281}
282
283//==============================================================================
284template <typename BV>
285void HierarchyTree<BV>::print(Node* root, int depth) {
286 for (int i = 0; i < depth; ++i) std::cout << " ";
287 std::cout << " (" << root->bv.min_[0] << ", " << root->bv.min_[1] << ", "
288 << root->bv.min_[2] << "; " << root->bv.max_[0] << ", "
289 << root->bv.max_[1] << ", " << root->bv.max_[2] << ")" << std::endl;
290 if (root->isLeaf()) {
291 } else {
292 print(root->children[0], depth + 1);
293 print(root->children[1], depth + 1);
294 }
295}
296
297//==============================================================================
298template <typename BV>
299void HierarchyTree<BV>::bottomup(const NodeVecIterator lbeg,
300 const NodeVecIterator lend) {
301 NodeVecIterator lcur_end = lend;
302 while (lbeg < lcur_end - 1) {
303 NodeVecIterator min_it1 = lbeg;
304 NodeVecIterator min_it2 = lbeg + 1;
305 Scalar min_size = (std::numeric_limits<Scalar>::max)();
306 for (NodeVecIterator it1 = lbeg; it1 < lcur_end; ++it1) {
307 for (NodeVecIterator it2 = it1 + 1; it2 < lcur_end; ++it2) {
308 Scalar cur_size = ((*it1)->bv + (*it2)->bv).size();
309 if (cur_size < min_size) {
310 min_size = cur_size;
311 min_it1 = it1;
312 min_it2 = it2;
313 }
314 }
315 }
316
317 Node* n[2] = {*min_it1, *min_it2};
318 Node* p = createNode(nullptr, n[0]->bv, n[1]->bv, nullptr);
319 p->children[0] = n[0];
320 p->children[1] = n[1];
321 n[0]->parent = p;
322 n[1]->parent = p;
323 *min_it1 = p;
324 Node* tmp = *min_it2;
325 lcur_end--;
326 *min_it2 = *lcur_end;
327 *lcur_end = tmp;
328 }
329}
330
331//==============================================================================
332template <typename BV>
333typename HierarchyTree<BV>::Node* HierarchyTree<BV>::topdown(
334 const NodeVecIterator lbeg, const NodeVecIterator lend) {
335 switch (topdown_level) {
336 case 0:
337 return topdown_0(lbeg, lend);
338 break;
339 case 1:
340 return topdown_1(lbeg, lend);
341 break;
342 default:
343 return topdown_0(lbeg, lend);
344 }
345}
346
347//==============================================================================
348template <typename BV>
349size_t HierarchyTree<BV>::getMaxHeight(Node* node) const {
350 if (!node->isLeaf()) {
351 size_t height1 = getMaxHeight(node->children[0]);
352 size_t height2 = getMaxHeight(node->children[1]);
353 return std::max(height1, height2) + 1;
354 } else
355 return 0;
356}
357
358//==============================================================================
359template <typename BV>
360void HierarchyTree<BV>::getMaxDepth(Node* node, size_t depth,
361 size_t& max_depth) const {
362 if (!node->isLeaf()) {
363 getMaxDepth(node->children[0], depth + 1, max_depth);
364 getMaxDepth(node->children[1], depth + 1, max_depth);
365 } else
366 max_depth = std::max(max_depth, depth);
367}
368
369//==============================================================================
370template <typename BV>
371typename HierarchyTree<BV>::Node* HierarchyTree<BV>::topdown_0(
372 const NodeVecIterator lbeg, const NodeVecIterator lend) {
373 long num_leaves = lend - lbeg;
374 if (num_leaves > 1) {
375 if (num_leaves > bu_threshold) {
376 BV vol = (*lbeg)->bv;
377 for (NodeVecIterator it = lbeg + 1; it < lend; ++it) vol += (*it)->bv;
378
379 int best_axis = 0;
380 Scalar extent[3] = {vol.width(), vol.height(), vol.depth()};
381 if (extent[1] > extent[0]) best_axis = 1;
382 if (extent[2] > extent[best_axis]) best_axis = 2;
383
384 // compute median
385 NodeVecIterator lcenter = lbeg + num_leaves / 2;
386 std::nth_element(lbeg, lcenter, lend,
387 std::bind(&nodeBaseLess<BV>, std::placeholders::_1,
388 std::placeholders::_2, std::ref(best_axis)));
389
390 Node* node = createNode(nullptr, vol, nullptr);
391 node->children[0] = topdown_0(lbeg, lcenter);
392 node->children[1] = topdown_0(lcenter, lend);
393 node->children[0]->parent = node;
394 node->children[1]->parent = node;
395 return node;
396 } else {
397 bottomup(lbeg, lend);
398 return *lbeg;
399 }
400 }
401 return *lbeg;
402}
403
404//==============================================================================
405template <typename BV>
406typename HierarchyTree<BV>::Node* HierarchyTree<BV>::topdown_1(
407 const NodeVecIterator lbeg, const NodeVecIterator lend) {
408 long num_leaves = lend - lbeg;
409 if (num_leaves > 1) {
410 if (num_leaves > bu_threshold) {
411 Vec3s split_p = (*lbeg)->bv.center();
412 BV vol = (*lbeg)->bv;
413 NodeVecIterator it;
414 for (it = lbeg + 1; it < lend; ++it) {
415 split_p += (*it)->bv.center();
416 vol += (*it)->bv;
417 }
418 split_p /= static_cast<Scalar>(num_leaves);
419 int best_axis = -1;
420 long bestmidp = num_leaves;
421 int splitcount[3][2] = {{0, 0}, {0, 0}, {0, 0}};
422 for (it = lbeg; it < lend; ++it) {
423 Vec3s x = (*it)->bv.center() - split_p;
424 for (int j = 0; j < 3; ++j) ++splitcount[j][x[j] > 0 ? 1 : 0];
425 }
426
427 for (int i = 0; i < 3; ++i) {
428 if ((splitcount[i][0] > 0) && (splitcount[i][1] > 0)) {
429 long midp = std::abs(splitcount[i][0] - splitcount[i][1]);
430 if (midp < bestmidp) {
431 best_axis = i;
432 bestmidp = midp;
433 }
434 }
435 }
436
437 if (best_axis < 0) best_axis = 0;
438
439 Scalar split_value = split_p[best_axis];
440 NodeVecIterator lcenter = lbeg;
441 for (it = lbeg; it < lend; ++it) {
442 if ((*it)->bv.center()[best_axis] < split_value) {
443 Node* temp = *it;
444 *it = *lcenter;
445 *lcenter = temp;
446 ++lcenter;
447 }
448 }
449
450 Node* node = createNode(nullptr, vol, nullptr);
451 node->children[0] = topdown_1(lbeg, lcenter);
452 node->children[1] = topdown_1(lcenter, lend);
453 node->children[0]->parent = node;
454 node->children[1]->parent = node;
455 return node;
456 } else {
457 bottomup(lbeg, lend);
458 return *lbeg;
459 }
460 }
461 return *lbeg;
462}
463
464//==============================================================================
465template <typename BV>
466void HierarchyTree<BV>::init_0(std::vector<Node*>& leaves) {
467 clear();
468 root_node = topdown(leaves.begin(), leaves.end());
469 n_leaves = leaves.size();
470 max_lookahead_level = -1;
471 opath = 0;
472}
473
474//==============================================================================
475template <typename BV>
476void HierarchyTree<BV>::init_1(std::vector<Node*>& leaves) {
477 clear();
478
479 BV bound_bv;
480 if (leaves.size() > 0) bound_bv = leaves[0]->bv;
481 for (size_t i = 1; i < leaves.size(); ++i) bound_bv += leaves[i]->bv;
482
483 morton_functor<Scalar, uint32_t> coder(bound_bv);
484 for (size_t i = 0; i < leaves.size(); ++i)
485 leaves[i]->code = coder(leaves[i]->bv.center());
486
487 std::sort(leaves.begin(), leaves.end(), SortByMorton());
488
489 root_node = mortonRecurse_0(leaves.begin(), leaves.end(),
490 (1 << (coder.bits() - 1)), coder.bits() - 1);
491
492 refit();
493 n_leaves = leaves.size();
494 max_lookahead_level = -1;
495 opath = 0;
496}
497
498//==============================================================================
499template <typename BV>
500void HierarchyTree<BV>::init_2(std::vector<Node*>& leaves) {
501 clear();
502
503 BV bound_bv;
504 if (leaves.size() > 0) bound_bv = leaves[0]->bv;
505 for (size_t i = 1; i < leaves.size(); ++i) bound_bv += leaves[i]->bv;
506
507 morton_functor<Scalar, uint32_t> coder(bound_bv);
508 for (size_t i = 0; i < leaves.size(); ++i)
509 leaves[i]->code = coder(leaves[i]->bv.center());
510
511 std::sort(leaves.begin(), leaves.end(), SortByMorton());
512
513 root_node = mortonRecurse_1(leaves.begin(), leaves.end(),
514 (1 << (coder.bits() - 1)), coder.bits() - 1);
515
516 refit();
517 n_leaves = leaves.size();
518 max_lookahead_level = -1;
519 opath = 0;
520}
521
522//==============================================================================
523template <typename BV>
524void HierarchyTree<BV>::init_3(std::vector<Node*>& leaves) {
525 clear();
526
527 BV bound_bv;
528 if (leaves.size() > 0) bound_bv = leaves[0]->bv;
529 for (size_t i = 1; i < leaves.size(); ++i) bound_bv += leaves[i]->bv;
530
531 morton_functor<Scalar, uint32_t> coder(bound_bv);
532 for (size_t i = 0; i < leaves.size(); ++i)
533 leaves[i]->code = coder(leaves[i]->bv.center());
534
535 std::sort(leaves.begin(), leaves.end(), SortByMorton());
536
537 root_node = mortonRecurse_2(leaves.begin(), leaves.end());
538
539 refit();
540 n_leaves = leaves.size();
541 max_lookahead_level = -1;
542 opath = 0;
543}
544
545//==============================================================================
546template <typename BV>
547typename HierarchyTree<BV>::Node* HierarchyTree<BV>::mortonRecurse_0(
548 const NodeVecIterator lbeg, const NodeVecIterator lend,
549 const uint32_t& split, int bits) {
550 long num_leaves = lend - lbeg;
551 if (num_leaves > 1) {
552 if (bits > 0) {
553 Node dummy;
554 dummy.code = split;
555 NodeVecIterator lcenter =
556 std::lower_bound(lbeg, lend, &dummy, SortByMorton());
557
558 if (lcenter == lbeg) {
559 uint32_t split2 = split | (1 << (bits - 1));
560 return mortonRecurse_0(lbeg, lend, split2, bits - 1);
561 } else if (lcenter == lend) {
562 uint32_t split1 = (split & (~(1 << bits))) | (1 << (bits - 1));
563 return mortonRecurse_0(lbeg, lend, split1, bits - 1);
564 } else {
565 uint32_t split1 = (split & (~(1 << bits))) | (1 << (bits - 1));
566 uint32_t split2 = split | (1 << (bits - 1));
567
568 Node* child1 = mortonRecurse_0(lbeg, lcenter, split1, bits - 1);
569 Node* child2 = mortonRecurse_0(lcenter, lend, split2, bits - 1);
570 Node* node = createNode(nullptr, nullptr);
571 node->children[0] = child1;
572 node->children[1] = child2;
573 child1->parent = node;
574 child2->parent = node;
575 return node;
576 }
577 } else {
578 Node* node = topdown(lbeg, lend);
579 return node;
580 }
581 } else
582 return *lbeg;
583}
584
585//==============================================================================
586template <typename BV>
587typename HierarchyTree<BV>::Node* HierarchyTree<BV>::mortonRecurse_1(
588 const NodeVecIterator lbeg, const NodeVecIterator lend,
589 const uint32_t& split, int bits) {
590 long num_leaves = lend - lbeg;
591 if (num_leaves > 1) {
592 if (bits > 0) {
593 Node dummy;
594 dummy.code = split;
595 NodeVecIterator lcenter =
596 std::lower_bound(lbeg, lend, &dummy, SortByMorton());
597
598 if (lcenter == lbeg) {
599 uint32_t split2 = split | (1 << (bits - 1));
600 return mortonRecurse_1(lbeg, lend, split2, bits - 1);
601 } else if (lcenter == lend) {
602 uint32_t split1 = (split & (~(1 << bits))) | (1 << (bits - 1));
603 return mortonRecurse_1(lbeg, lend, split1, bits - 1);
604 } else {
605 uint32_t split1 = (split & (~(1 << bits))) | (1 << (bits - 1));
606 uint32_t split2 = split | (1 << (bits - 1));
607
608 Node* child1 = mortonRecurse_1(lbeg, lcenter, split1, bits - 1);
609 Node* child2 = mortonRecurse_1(lcenter, lend, split2, bits - 1);
610 Node* node = createNode(nullptr, nullptr);
611 node->children[0] = child1;
612 node->children[1] = child2;
613 child1->parent = node;
614 child2->parent = node;
615 return node;
616 }
617 } else {
618 Node* child1 = mortonRecurse_1(lbeg, lbeg + num_leaves / 2, 0, bits - 1);
619 Node* child2 = mortonRecurse_1(lbeg + num_leaves / 2, lend, 0, bits - 1);
620 Node* node = createNode(nullptr, nullptr);
621 node->children[0] = child1;
622 node->children[1] = child2;
623 child1->parent = node;
624 child2->parent = node;
625 return node;
626 }
627 } else
628 return *lbeg;
629}
630
631//==============================================================================
632template <typename BV>
633typename HierarchyTree<BV>::Node* HierarchyTree<BV>::mortonRecurse_2(
634 const NodeVecIterator lbeg, const NodeVecIterator lend) {
635 long num_leaves = lend - lbeg;
636 if (num_leaves > 1) {
637 Node* child1 = mortonRecurse_2(lbeg, lbeg + num_leaves / 2);
638 Node* child2 = mortonRecurse_2(lbeg + num_leaves / 2, lend);
639 Node* node = createNode(nullptr, nullptr);
640 node->children[0] = child1;
641 node->children[1] = child2;
642 child1->parent = node;
643 child2->parent = node;
644 return node;
645 } else
646 return *lbeg;
647}
648
649//==============================================================================
650template <typename BV>
651void HierarchyTree<BV>::update_(Node* leaf, const BV& bv) {
652 Node* root = removeLeaf(leaf);
653 if (root) {
654 if (max_lookahead_level >= 0) {
655 for (int i = 0; (i < max_lookahead_level) && root->parent; ++i)
656 root = root->parent;
657 } else
658 root = root_node;
659 }
660
661 leaf->bv = bv;
662 insertLeaf(root, leaf);
663}
664
665//==============================================================================
666template <typename BV>
667typename HierarchyTree<BV>::Node* HierarchyTree<BV>::sort(Node* n, Node*& r) {
668 Node* p = n->parent;
669 if (p > n) {
670 size_t i = indexOf(n);
671 size_t j = 1 - i;
672 Node* s = p->children[j];
673 Node* q = p->parent;
674 if (q)
675 q->children[indexOf(p)] = n;
676 else
677 r = n;
678 s->parent = n;
679 p->parent = n;
680 n->parent = q;
681 p->children[0] = n->children[0];
682 p->children[1] = n->children[1];
683 n->children[0]->parent = p;
684 n->children[1]->parent = p;
685 n->children[i] = p;
686 n->children[j] = s;
687 std::swap(p->bv, n->bv);
688 return p;
689 }
690 return n;
691}
692
693//==============================================================================
694template <typename BV>
695void HierarchyTree<BV>::insertLeaf(Node* const sub_root, Node* const leaf)
696// Attempts to insert `leaf` into a subtree rooted at `sub_root`.
697// 1. If the whole tree is empty, then `leaf` simply becomes the tree.
698// 2. Otherwise, a leaf node called `sibling` of the subtree rooted at
699// `sub_root` is selected (the selection criteria is a black box for this
700// algorithm), and the `sibling` leaf is replaced by an internal node with
701// two children, `sibling` and `leaf`. The bounding volumes are updated as
702// necessary.
703{
704 if (!root_node) {
705 // If the entire tree is empty, the node pointed by `leaf` variable will
706 // become the root of the tree.
707 root_node = leaf;
708 leaf->parent = nullptr;
709 return;
710 }
711 // Traverse the tree from the given `sub_root` down to an existing leaf
712 // node that we call `sibling`. The `sibling` node will eventually become
713 // the sibling of the given `leaf` node.
714 Node* sibling = sub_root;
715 while (!sibling->isLeaf()) {
716 sibling = sibling->children[select(*leaf, *(sibling->children[0]),
717 *(sibling->children[1]))];
718 }
719 Node* prev = sibling->parent;
720 // Create a new `node` that later will become the new parent of both the
721 // `sibling` and the given `leaf`.
722 Node* node = createNode(prev, leaf->bv, sibling->bv, nullptr);
723 if (prev)
724 // If the parent `prev` of the `sibling` is an interior node, we will
725 // replace the `sibling` with the subtree {node {`sibling`, leaf}} like
726 // this:
727 // Before After
728 //
729 // ╱ ╱
730 // prev prev
731 // ╱ ╲ ─> ╱ ╲
732 // sibling ... node ...
733 // ╱ ╲
734 // sibling leaf
735 {
736 prev->children[indexOf(sibling)] = node;
737 node->children[0] = sibling;
738 sibling->parent = node;
739 node->children[1] = leaf;
740 leaf->parent = node;
741 // Now that we've inserted `leaf` some of the existing bounding
742 // volumes might not fully enclose their children. Walk up the tree
743 // looking for parents that don't already enclose their children
744 // and create a new tight-fitting bounding volume for those.
745 do {
746 if (!prev->bv.contain(node->bv))
747 prev->bv = prev->children[0]->bv + prev->children[1]->bv;
748 else
749 break;
750 node = prev;
751 } while (nullptr != (prev = node->parent));
752 } else
753 // If the `sibling` has no parent, i.e., the tree is a singleton,
754 // we will replace it with the 3-node tree {node {`sibling`, `leaf`}} like
755 // this:
756 //
757 // node
758 // ╱ ╲
759 // sibling leaf
760 {
761 node->children[0] = sibling;
762 sibling->parent = node;
763 node->children[1] = leaf;
764 leaf->parent = node;
765 root_node = node;
766 }
767
768 // Note that the above algorithm always adds the new `leaf` node as the right
769 // child, i.e., children[1]. Calling removeLeaf(l) followed by calling
770 // this function insertLeaf(l) where l is a left child will result in
771 // switching l and its sibling even if no object's pose has changed.
772}
773
774//==============================================================================
775template <typename BV>
776typename HierarchyTree<BV>::Node* HierarchyTree<BV>::removeLeaf(
777 Node* const leaf) {
778 // Deletes `leaf` by replacing the subtree consisting of `leaf`, its sibling,
779 // and its parent with just its sibling. It then "tightens" the ancestor
780 // bounding volumes. Returns a pointer to the parent of the highest node whose
781 // BV changed due to the removal.
782 if (leaf == root_node) {
783 // If the `leaf` node is the only node in the tree, the tree becomes empty.
784 root_node = nullptr;
785 return nullptr;
786 }
787 Node* parent = leaf->parent;
788 Node* prev = parent->parent;
789 Node* sibling = parent->children[1 - indexOf(leaf)];
790 if (prev) {
791 // If the parent node is not the root node, the sibling node will
792 // replace the parent node like this:
793 //
794 // Before After
795 // ... ...
796 // ╱ ╱
797 // prev prev
798 // ╱ ╲ ╱ ╲
799 // parent ... ─> sibling ...
800 // ╱ ╲ ╱╲
801 // leaf sibling ...
802 // ╱╲
803 // ...
804 //
805 // Step 1: replace the subtree {parent {leaf, sibling {...}}} with
806 // {sibling {...}}.
807 prev->children[indexOf(parent)] = sibling;
808 sibling->parent = prev;
809 deleteNode(parent);
810 // Step 2: tighten up the BVs of the ancestor nodes.
811 while (prev) {
812 BV new_bv = prev->children[0]->bv + prev->children[1]->bv;
813 if (!(new_bv == prev->bv)) {
814 prev->bv = new_bv;
815 prev = prev->parent;
816 } else
817 break;
818 }
819
820 return prev ? prev : root_node;
821 } else {
822 // If the parent node is the root node, the sibling node will become the
823 // root of the whole tree like this:
824 //
825 // Before After
826 //
827 // parent
828 // ╱ ╲
829 // leaf sibling ─> sibling
830 // ╱╲ ╱╲
831 // ... ...
832 root_node = sibling;
833 sibling->parent = nullptr;
834 deleteNode(parent);
835 return root_node;
836 }
837}
838
839//==============================================================================
840template <typename BV>
841void HierarchyTree<BV>::fetchLeaves(Node* root, std::vector<Node*>& leaves,
842 int depth) {
843 if ((!root->isLeaf()) && depth) {
844 fetchLeaves(root->children[0], leaves, depth - 1);
845 fetchLeaves(root->children[1], leaves, depth - 1);
846 deleteNode(root);
847 } else {
848 leaves.push_back(root);
849 }
850}
851
852//==============================================================================
853template <typename BV>
854size_t HierarchyTree<BV>::indexOf(Node* node) {
855 // node cannot be nullptr
856 return (node->parent->children[1] == node);
857}
858
859//==============================================================================
860template <typename BV>
861typename HierarchyTree<BV>::Node* HierarchyTree<BV>::createNode(Node* parent,
862 const BV& bv,
863 void* data) {
864 Node* node = createNode(parent, data);
865 node->bv = bv;
866 return node;
867}
868
869//==============================================================================
870template <typename BV>
871typename HierarchyTree<BV>::Node* HierarchyTree<BV>::createNode(Node* parent,
872 const BV& bv1,
873 const BV& bv2,
874 void* data) {
875 Node* node = createNode(parent, data);
876 node->bv = bv1 + bv2;
877 return node;
878}
879
880//==============================================================================
881template <typename BV>
882typename HierarchyTree<BV>::Node* HierarchyTree<BV>::createNode(Node* parent,
883 void* data) {
884 Node* node = nullptr;
885 if (free_node) {
886 node = free_node;
887 free_node = nullptr;
888 } else
889 node = new Node();
890 node->parent = parent;
891 node->data = data;
892 node->children[1] = 0;
893 return node;
894}
895
896//==============================================================================
897template <typename BV>
898void HierarchyTree<BV>::deleteNode(Node* node) {
899 if (free_node != node) {
900 delete free_node;
901 free_node = node;
902 }
903}
904
905//==============================================================================
906template <typename BV>
907void HierarchyTree<BV>::recurseDeleteNode(Node* node) {
908 if (!node->isLeaf()) {
909 recurseDeleteNode(node->children[0]);
910 recurseDeleteNode(node->children[1]);
911 }
912
913 if (node == root_node) root_node = nullptr;
914 deleteNode(node);
915}
916
917//==============================================================================
918template <typename BV>
919void HierarchyTree<BV>::recurseRefit(Node* node) {
920 if (!node->isLeaf()) {
921 recurseRefit(node->children[0]);
922 recurseRefit(node->children[1]);
923 node->bv = node->children[0]->bv + node->children[1]->bv;
924 } else
925 return;
926}
927
928//==============================================================================
929template <typename BV>
931 if (a->bv.center()[d] < b->bv.center()[d]) return true;
932 return false;
933}
934
935//==============================================================================
936template <typename S, typename BV>
938 static std::size_t run(const NodeBase<BV>& /*query*/,
939 const NodeBase<BV>& /*node1*/,
940 const NodeBase<BV>& /*node2*/) {
941 return 0;
942 }
943
944 static std::size_t run(const BV& /*query*/, const NodeBase<BV>& /*node1*/,
945 const NodeBase<BV>& /*node2*/) {
946 return 0;
947 }
948};
949
950//==============================================================================
951template <typename BV>
952size_t select(const NodeBase<BV>& query, const NodeBase<BV>& node1,
953 const NodeBase<BV>& node2) {
954 return SelectImpl<Scalar, BV>::run(query, node1, node2);
955}
956
957//==============================================================================
958template <typename BV>
959size_t select(const BV& query, const NodeBase<BV>& node1,
960 const NodeBase<BV>& node2) {
961 return SelectImpl<Scalar, BV>::run(query, node1, node2);
962}
963
964//==============================================================================
965template <typename S>
966struct SelectImpl<S, AABB> {
967 static std::size_t run(const NodeBase<AABB>& node,
968 const NodeBase<AABB>& node1,
969 const NodeBase<AABB>& node2) {
970 const AABB& bv = node.bv;
971 const AABB& bv1 = node1.bv;
972 const AABB& bv2 = node2.bv;
973 Vec3s v = bv.min_ + bv.max_;
974 Vec3s v1 = v - (bv1.min_ + bv1.max_);
975 Vec3s v2 = v - (bv2.min_ + bv2.max_);
976 Scalar d1 = fabs(v1[0]) + fabs(v1[1]) + fabs(v1[2]);
977 Scalar d2 = fabs(v2[0]) + fabs(v2[1]) + fabs(v2[2]);
978 return (d1 < d2) ? 0 : 1;
979 }
980
981 static std::size_t run(const AABB& query, const NodeBase<AABB>& node1,
982 const NodeBase<AABB>& node2) {
983 const AABB& bv = query;
984 const AABB& bv1 = node1.bv;
985 const AABB& bv2 = node2.bv;
986 Vec3s v = bv.min_ + bv.max_;
987 Vec3s v1 = v - (bv1.min_ + bv1.max_);
988 Vec3s v2 = v - (bv2.min_ + bv2.max_);
989 Scalar d1 = fabs(v1[0]) + fabs(v1[1]) + fabs(v1[2]);
990 Scalar d2 = fabs(v2[0]) + fabs(v2[1]) + fabs(v2[2]);
991 return (d1 < d2) ? 0 : 1;
992 }
993};
994
995} // namespace detail
996} // namespace coal
997
998#endif
A class describing the AABB collision structure, which is a box in 3D space determined by two diagona...
Definition AABB.h:55
Vec3s min_
The min point in the AABB.
Definition AABB.h:58
Vec3s max_
The max point in the AABB.
Definition AABB.h:60
Class for hierarchy tree structure.
Definition hierarchy_tree.h:56
~HierarchyTree()
Definition hierarchy_tree-inl.h:61
Node * getRoot() const
get the root of the tree
Definition hierarchy_tree-inl.h:273
HierarchyTree(int bu_threshold_=16, int topdown_level_=0)
Create hierarchy tree with suitable setting. bu_threshold decides the height of tree node to start bo...
Definition hierarchy_tree-inl.h:49
void balanceBottomup()
balance the tree from bottom
Definition hierarchy_tree-inl.h:209
void update(Node *leaf, int lookahead_level=-1)
Updates a leaf node. A use case is when the bounding volume of an object changes. Ensure every parent...
Definition hierarchy_tree-inl.h:123
Node * insert(const BV &bv, void *data)
Insest a node.
Definition hierarchy_tree-inl.h:88
void clear()
Clear the tree.
Definition hierarchy_tree-inl.h:106
void remove(Node *leaf)
Remove a leaf node.
Definition hierarchy_tree-inl.h:98
void balanceTopdown()
balance the tree from top
Definition hierarchy_tree-inl.h:221
void init(std::vector< Node * > &leaves, int level=0)
Initialize the tree by a set of leaves using algorithm with a given level.
Definition hierarchy_tree-inl.h:67
void refit()
refit the tree, i.e., when the leaf nodes' bounding volumes change, update the entire tree in a botto...
Definition hierarchy_tree-inl.h:250
bool empty() const
Whether the tree is empty.
Definition hierarchy_tree-inl.h:117
size_t getMaxDepth() const
get the max depth of the tree
Definition hierarchy_tree-inl.h:199
size_t size() const
number of leaves in the tree
Definition hierarchy_tree-inl.h:267
void balanceIncremental(int iterations)
balance the tree in an incremental way
Definition hierarchy_tree-inl.h:232
NodeBase< BV > Node
Definition hierarchy_tree.h:58
void print(Node *root, int depth)
print the tree in a recursive way
Definition hierarchy_tree-inl.h:285
size_t getMaxHeight() const
get the max height of the tree
Definition hierarchy_tree-inl.h:192
void extractLeaves(const Node *root, std::vector< Node * > &leaves) const
extract all the leaves of the tree
Definition hierarchy_tree-inl.h:256
size_t select(const NodeBase< BV > &query, const NodeBase< BV > &node1, const NodeBase< BV > &node2)
select from node1 and node2 which is close to a given query. 0 for node1 and 1 for node2
Definition hierarchy_tree-inl.h:952
bool nodeBaseLess(NodeBase< BV > *a, NodeBase< BV > *b, int d)
Compare two nodes accoording to the d-th dimension of node center.
Definition hierarchy_tree-inl.h:930
Main namespace.
Definition broadphase_bruteforce.h:44
Eigen::Matrix< Scalar, 3, 1 > Vec3s
Definition data_types.h:70
double Scalar
Definition data_types.h:68
dynamic AABB tree node
Definition node_base.h:49
NodeBase< BV > * children[2]
for leaf node, children nodes
Definition node_base.h:64
bool isLeaf() const
whether is a leaf
Definition node_base-inl.h:54
NodeBase< BV > * parent
pointer to parent node
Definition node_base.h:54
BV bv
the bounding volume for the node
Definition node_base.h:51
static std::size_t run(const AABB &query, const NodeBase< AABB > &node1, const NodeBase< AABB > &node2)
Definition hierarchy_tree-inl.h:981
static std::size_t run(const NodeBase< AABB > &node, const NodeBase< AABB > &node1, const NodeBase< AABB > &node2)
Definition hierarchy_tree-inl.h:967
Definition hierarchy_tree-inl.h:937
static std::size_t run(const BV &, const NodeBase< BV > &, const NodeBase< BV > &)
Definition hierarchy_tree-inl.h:944
static std::size_t run(const NodeBase< BV > &, const NodeBase< BV > &, const NodeBase< BV > &)
Definition hierarchy_tree-inl.h:938
Definition hierarchy_tree-inl.h:159
static bool run(const HierarchyTree< BV > &tree, typename HierarchyTree< BV >::Node *leaf, const BV &bv, const Vec3s &, Scalar)
Definition hierarchy_tree-inl.h:160
static bool run(const HierarchyTree< BV > &tree, typename HierarchyTree< BV >::Node *leaf, const BV &bv, const Vec3s &)
Definition hierarchy_tree-inl.h:168