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 HPP_FCL_HIERARCHY_TREE_INL_H
39 #define HPP_FCL_HIERARCHY_TREE_INL_H
40 
42 
43 namespace hpp {
44 namespace fcl {
45 
46 namespace detail {
47 
48 //==============================================================================
49 template <typename BV>
50 HierarchyTree<BV>::HierarchyTree(int bu_threshold_, int topdown_level_) {
51  root_node = nullptr;
52  n_leaves = 0;
53  free_node = nullptr;
54  max_lookahead_level = -1;
55  opath = 0;
56  bu_threshold = bu_threshold_;
57  topdown_level = topdown_level_;
58 }
59 
60 //==============================================================================
61 template <typename BV>
63  clear();
64 }
65 
66 //==============================================================================
67 template <typename BV>
68 void HierarchyTree<BV>::init(std::vector<Node*>& leaves, int level) {
69  switch (level) {
70  case 0:
71  init_0(leaves);
72  break;
73  case 1:
74  init_1(leaves);
75  break;
76  case 2:
77  init_2(leaves);
78  break;
79  case 3:
80  init_3(leaves);
81  break;
82  default:
83  init_0(leaves);
84  }
85 }
86 
87 //==============================================================================
88 template <typename BV>
90  void* data) {
91  Node* leaf = createNode(nullptr, bv, data);
92  insertLeaf(root_node, leaf);
93  ++n_leaves;
94  return leaf;
95 }
96 
97 //==============================================================================
98 template <typename BV>
100  removeLeaf(leaf);
101  deleteNode(leaf);
102  --n_leaves;
103 }
104 
105 //==============================================================================
106 template <typename BV>
108  if (root_node) recurseDeleteNode(root_node);
109  n_leaves = 0;
110  delete free_node;
111  free_node = nullptr;
112  max_lookahead_level = -1;
113  opath = 0;
114 }
115 
116 //==============================================================================
117 template <typename BV>
119  return (nullptr == root_node);
120 }
121 
122 //==============================================================================
123 template <typename BV>
124 void HierarchyTree<BV>::update(Node* leaf, int lookahead_level) {
125  // TODO(DamrongGuoy): Since we update a leaf node by removing and
126  // inserting the same leaf node, it is likely to change the structure of
127  // the tree even if no object's pose has changed. In the future,
128  // find a way to preserve the structure of the tree to solve this issue:
129  // https://github.com/flexible-collision-library/fcl/issues/368
130 
131  // First we remove the leaf node pointed by `leaf` variable from the tree.
132  // The `sub_root` variable is the root of the subtree containing nodes
133  // whose BVs were adjusted due to node removal.
134  typename HierarchyTree<BV>::Node* sub_root = removeLeaf(leaf);
135  if (sub_root) {
136  if (lookahead_level > 0) {
137  // For positive `lookahead_level`, we move the `sub_root` variable up.
138  for (int i = 0; (i < lookahead_level) && sub_root->parent; ++i)
139  sub_root = sub_root->parent;
140  } else
141  // By default, lookahead_level = -1, and we reset the `sub_root` variable
142  // to the root of the entire tree.
143  sub_root = root_node;
144  }
145  // Then we insert the node pointed by `leaf` variable back into the
146  // subtree rooted at `sub_root` variable.
147  insertLeaf(sub_root, leaf);
148 }
149 
150 //==============================================================================
151 template <typename BV>
152 bool HierarchyTree<BV>::update(Node* leaf, const BV& bv) {
153  if (leaf->bv.contain(bv)) return false;
154  update_(leaf, bv);
155  return true;
156 }
157 
158 //==============================================================================
159 template <typename S, typename BV>
160 struct UpdateImpl {
161  static bool run(const HierarchyTree<BV>& tree,
162  typename HierarchyTree<BV>::Node* leaf, const BV& bv,
163  const Vec3f& /*vel*/, FCL_REAL /*margin*/) {
164  if (leaf->bv.contain(bv)) return false;
165  tree.update_(leaf, bv);
166  return true;
167  }
168 
169  static bool run(const HierarchyTree<BV>& tree,
170  typename HierarchyTree<BV>::Node* leaf, const BV& bv,
171  const Vec3f& /*vel*/) {
172  if (leaf->bv.contain(bv)) return false;
173  tree.update_(leaf, bv);
174  return true;
175  }
176 };
177 
178 //==============================================================================
179 template <typename BV>
180 bool HierarchyTree<BV>::update(Node* leaf, const BV& bv, const Vec3f& vel,
181  FCL_REAL margin) {
182  return UpdateImpl<FCL_REAL, BV>::run(*this, leaf, bv, vel, margin);
183 }
184 
185 //==============================================================================
186 template <typename BV>
187 bool HierarchyTree<BV>::update(Node* leaf, const BV& bv, const Vec3f& vel) {
188  return UpdateImpl<FCL_REAL, BV>::run(*this, leaf, bv, vel);
189 }
190 
191 //==============================================================================
192 template <typename BV>
194  if (!root_node) return 0;
195  return getMaxHeight(root_node);
196 }
197 
198 //==============================================================================
199 template <typename BV>
201  if (!root_node) return 0;
202 
203  size_t max_depth;
204  getMaxDepth(root_node, 0, max_depth);
205  return max_depth;
206 }
207 
208 //==============================================================================
209 template <typename BV>
211  if (root_node) {
212  std::vector<Node*> leaves;
213  leaves.reserve(n_leaves);
214  fetchLeaves(root_node, leaves);
215  bottomup(leaves.begin(), leaves.end());
216  root_node = leaves[0];
217  }
218 }
219 
220 //==============================================================================
221 template <typename BV>
223  if (root_node) {
224  std::vector<Node*> leaves;
225  leaves.reserve(n_leaves);
226  fetchLeaves(root_node, leaves);
227  root_node = topdown(leaves.begin(), leaves.end());
228  }
229 }
230 
231 //==============================================================================
232 template <typename BV>
234  if (iterations < 0) iterations = (int)n_leaves;
235  if (root_node && (iterations > 0)) {
236  for (int i = 0; i < iterations; ++i) {
237  Node* node = root_node;
238  unsigned int bit = 0;
239  while (!node->isLeaf()) {
240  node = sort(node, root_node)->children[(opath >> bit) & 1];
241  bit = (bit + 1) & (sizeof(unsigned int) * 8 - 1);
242  }
243  update(node);
244  ++opath;
245  }
246  }
247 }
248 
249 //==============================================================================
250 template <typename BV>
252  if (root_node) recurseRefit(root_node);
253 }
254 
255 //==============================================================================
256 template <typename BV>
258  std::vector<Node*>& leaves) const {
259  if (!root->isLeaf()) {
260  extractLeaves(root->children[0], leaves);
261  extractLeaves(root->children[1], leaves);
262  } else
263  leaves.push_back(root);
264 }
265 
266 //==============================================================================
267 template <typename BV>
268 size_t HierarchyTree<BV>::size() const {
269  return n_leaves;
270 }
271 
272 //==============================================================================
273 template <typename BV>
275  return root_node;
276 }
277 
278 //==============================================================================
279 template <typename BV>
281  return root_node;
282 }
283 
284 //==============================================================================
285 template <typename BV>
286 void HierarchyTree<BV>::print(Node* root, int depth) {
287  for (int i = 0; i < depth; ++i) std::cout << " ";
288  std::cout << " (" << root->bv.min_[0] << ", " << root->bv.min_[1] << ", "
289  << root->bv.min_[2] << "; " << root->bv.max_[0] << ", "
290  << root->bv.max_[1] << ", " << root->bv.max_[2] << ")" << std::endl;
291  if (root->isLeaf()) {
292  } else {
293  print(root->children[0], depth + 1);
294  print(root->children[1], depth + 1);
295  }
296 }
297 
298 //==============================================================================
299 template <typename BV>
301  const NodeVecIterator lend) {
302  NodeVecIterator lcur_end = lend;
303  while (lbeg < lcur_end - 1) {
304  NodeVecIterator min_it1, min_it2;
305  FCL_REAL min_size = (std::numeric_limits<FCL_REAL>::max)();
306  for (NodeVecIterator it1 = lbeg; it1 < lcur_end; ++it1) {
307  for (NodeVecIterator it2 = it1 + 1; it2 < lcur_end; ++it2) {
308  FCL_REAL 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 //==============================================================================
332 template <typename BV>
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 //==============================================================================
348 template <typename BV>
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 //==============================================================================
359 template <typename BV>
360 void 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 //==============================================================================
370 template <typename BV>
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  FCL_REAL 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 //==============================================================================
405 template <typename BV>
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  Vec3f 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<FCL_REAL>(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  Vec3f 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  FCL_REAL 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 //==============================================================================
465 template <typename BV>
466 void 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 //==============================================================================
475 template <typename BV>
476 void 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<FCL_REAL, 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 //==============================================================================
499 template <typename BV>
500 void 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<FCL_REAL, 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 //==============================================================================
523 template <typename BV>
524 void 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<FCL_REAL, 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 //==============================================================================
546 template <typename BV>
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 //==============================================================================
586 template <typename BV>
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 //==============================================================================
632 template <typename BV>
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 //==============================================================================
650 template <typename BV>
651 void 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 //==============================================================================
666 template <typename BV>
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 //==============================================================================
694 template <typename BV>
695 void 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 //==============================================================================
775 template <typename BV>
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 //==============================================================================
840 template <typename BV>
841 void 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 //==============================================================================
853 template <typename BV>
855  // node cannot be nullptr
856  return (node->parent->children[1] == node);
857 }
858 
859 //==============================================================================
860 template <typename BV>
862  const BV& bv,
863  void* data) {
864  Node* node = createNode(parent, data);
865  node->bv = bv;
866  return node;
867 }
868 
869 //==============================================================================
870 template <typename BV>
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 //==============================================================================
881 template <typename BV>
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 //==============================================================================
897 template <typename BV>
899  if (free_node != node) {
900  delete free_node;
901  free_node = node;
902  }
903 }
904 
905 //==============================================================================
906 template <typename BV>
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 //==============================================================================
918 template <typename BV>
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 //==============================================================================
929 template <typename BV>
931  if (a->bv.center()[d] < b->bv.center()[d]) return true;
932  return false;
933 }
934 
935 //==============================================================================
936 template <typename S, typename BV>
937 struct SelectImpl {
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 //==============================================================================
951 template <typename BV>
952 size_t select(const NodeBase<BV>& query, const NodeBase<BV>& node1,
953  const NodeBase<BV>& node2) {
954  return SelectImpl<FCL_REAL, BV>::run(query, node1, node2);
955 }
956 
957 //==============================================================================
958 template <typename BV>
959 size_t select(const BV& query, const NodeBase<BV>& node1,
960  const NodeBase<BV>& node2) {
961  return SelectImpl<FCL_REAL, BV>::run(query, node1, node2);
962 }
963 
964 //==============================================================================
965 template <typename S>
966 struct 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  Vec3f v = bv.min_ + bv.max_;
974  Vec3f v1 = v - (bv1.min_ + bv1.max_);
975  Vec3f v2 = v - (bv2.min_ + bv2.max_);
976  FCL_REAL d1 = fabs(v1[0]) + fabs(v1[1]) + fabs(v1[2]);
977  FCL_REAL 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  Vec3f v = bv.min_ + bv.max_;
987  Vec3f v1 = v - (bv1.min_ + bv1.max_);
988  Vec3f v2 = v - (bv2.min_ + bv2.max_);
989  FCL_REAL d1 = fabs(v1[0]) + fabs(v1[1]) + fabs(v1[2]);
990  FCL_REAL d2 = fabs(v2[0]) + fabs(v2[1]) + fabs(v2[2]);
991  return (d1 < d2) ? 0 : 1;
992  }
993 };
994 
995 } // namespace detail
996 } // namespace fcl
997 } // namespace hpp
998 
999 #endif
Node * createNode(Node *parent, const BV &bv, void *data)
create one node (leaf or internal)
void init_2(std::vector< Node *> &leaves)
init tree from leaves using morton code. It uses morton_0, i.e., for nodes which is of depth more tha...
Vec3f min_
The min point in the AABB.
Definition: BV/AABB.h:57
q
static std::size_t run(const AABB &query, const NodeBase< AABB > &node1, const NodeBase< AABB > &node2)
std::vector< NodeBase< hpp::fcl::AABB > *>::iterator NodeVecIterator
bool isLeaf() const
whether is a leaf
Definition: node_base-inl.h:55
Main namespace.
uint32_t code
morton code for current BV
Definition: node_base.h:70
void balanceTopdown()
balance the tree from top
static bool run(const HierarchyTree< BV > &tree, typename HierarchyTree< BV >::Node *leaf, const BV &bv, const Vec3f &, FCL_REAL)
Node * mortonRecurse_2(const NodeVecIterator lbeg, const NodeVecIterator lend)
Node * topdown_1(const NodeVecIterator lbeg, const NodeVecIterator lend)
construct a tree from a list of nodes stored in [lbeg, lend) in a topdown manner. During construction...
NodeBase< BV > * parent
pointer to parent node
Definition: node_base.h:55
static size_t indexOf(Node *node)
Node * getRoot() const
get the root of the tree
void fetchLeaves(Node *root, std::vector< Node *> &leaves, int depth=-1)
Delete all internal nodes and return all leaves nodes with given depth from root. ...
Node * mortonRecurse_1(const NodeVecIterator lbeg, const NodeVecIterator lend, const uint32_t &split, int bits)
list v
Definition: obb.py:45
void balanceIncremental(int iterations)
balance the tree in an incremental way
void refit()
refit the tree, i.e., when the leaf nodes&#39; bounding volumes change, update the entire tree in a botto...
size_t size() const
number of leaves in the tree
NodeBase< BV > * children[2]
for leaf node, children nodes
Definition: node_base.h:65
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...
Class for hierarchy tree structure.
double FCL_REAL
Definition: data_types.h:65
x
size_t getMaxHeight() const
get the max height of the tree
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...
Node * topdown_0(const NodeVecIterator lbeg, const NodeVecIterator lend)
construct a tree from a list of nodes stored in [lbeg, lend) in a topdown manner. During construction...
void balanceBottomup()
balance the tree from bottom
Node * mortonRecurse_0(const NodeVecIterator lbeg, const NodeVecIterator lend, const uint32_t &split, int bits)
A class describing the AABB collision structure, which is a box in 3D space determined by two diagona...
Definition: BV/AABB.h:54
Vec3f max_
The max point in the AABB.
Definition: BV/AABB.h:59
void extractLeaves(const Node *root, std::vector< Node *> &leaves) const
extract all the leaves of the tree
void remove(Node *leaf)
Remove a leaf node.
static std::size_t run(const BV &, const NodeBase< BV > &, const NodeBase< BV > &)
Node * sort(Node *n, Node *&r)
sort node n and its parent according to their memory position
void insertLeaf(Node *const sub_root, Node *const leaf)
Insert a leaf node and also update its ancestors. Maintain the tree as a full binary tree (every inte...
size_t getMaxDepth() const
get the max depth of the tree
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 ...
Node * topdown(const NodeVecIterator lbeg, const NodeVecIterator lend)
construct a tree for a set of leaves from top
void print(Node *root, int depth)
print the tree in a recursive way
void bottomup(const NodeVecIterator lbeg, const NodeVecIterator lend)
construct a tree for a set of leaves from bottom – very heavy way
dynamic AABB tree node
Definition: node_base.h:50
void init_3(std::vector< Node *> &leaves)
init tree from leaves using morton code. It uses morton_2, i.e., for all nodes, we simply divide the ...
Node * insert(const BV &bv, void *data)
Insest a node.
static bool run(const HierarchyTree< BV > &tree, typename HierarchyTree< BV >::Node *leaf, const BV &bv, const Vec3f &)
void init(std::vector< Node *> &leaves, int level=0)
Initialize the tree by a set of leaves using algorithm with a given level.
Node * removeLeaf(Node *const leaf)
Remove a leaf. Maintain the tree as a full binary tree (every interior node has exactly two children)...
void init_1(std::vector< Node *> &leaves)
init tree from leaves using morton code. It uses morton_0, i.e., for nodes which is of depth more tha...
BV bv
the bounding volume for the node
Definition: node_base.h:52
Eigen::Matrix< FCL_REAL, 3, 1 > Vec3f
Definition: data_types.h:66
void update_(Node *leaf, const BV &bv)
update one leaf node&#39;s bounding volume
bool empty() const
Whether the tree is empty.
void print(const Tensor &tensor)
static std::size_t run(const NodeBase< AABB > &node, const NodeBase< AABB > &node1, const NodeBase< AABB > &node2)
static std::size_t run(const NodeBase< BV > &, const NodeBase< BV > &, const NodeBase< BV > &)
bool nodeBaseLess(NodeBase< BV > *a, NodeBase< BV > *b, int d)
Compare two nodes accoording to the d-th dimension of node center.
void init_0(std::vector< Node *> &leaves)
init tree from leaves in the topdown manner (topdown_0 or topdown_1)


hpp-fcl
Author(s):
autogenerated on Fri Jun 2 2023 02:39:01