coal/broadphase/detail/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 
43 namespace coal {
44 
45 namespace detail {
46 
47 //==============================================================================
48 template <typename BV>
49 HierarchyTree<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 //==============================================================================
60 template <typename BV>
62  clear();
63 }
64 
65 //==============================================================================
66 template <typename BV>
67 void 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 //==============================================================================
87 template <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 //==============================================================================
97 template <typename BV>
99  removeLeaf(leaf);
100  deleteNode(leaf);
101  --n_leaves;
102 }
103 
104 //==============================================================================
105 template <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 //==============================================================================
116 template <typename BV>
118  return (nullptr == root_node);
119 }
120 
121 //==============================================================================
122 template <typename BV>
123 void 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 //==============================================================================
150 template <typename BV>
151 bool 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 //==============================================================================
158 template <typename S, typename BV>
159 struct UpdateImpl {
160  static bool run(const HierarchyTree<BV>& tree,
161  typename HierarchyTree<BV>::Node* leaf, const BV& bv,
162  const Vec3s& /*vel*/, CoalScalar /*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 //==============================================================================
178 template <typename BV>
179 bool HierarchyTree<BV>::update(Node* leaf, const BV& bv, const Vec3s& vel,
180  CoalScalar margin) {
181  return UpdateImpl<CoalScalar, BV>::run(*this, leaf, bv, vel, margin);
182 }
183 
184 //==============================================================================
185 template <typename BV>
186 bool HierarchyTree<BV>::update(Node* leaf, const BV& bv, const Vec3s& vel) {
187  return UpdateImpl<CoalScalar, BV>::run(*this, leaf, bv, vel);
188 }
189 
190 //==============================================================================
191 template <typename BV>
193  if (!root_node) return 0;
194  return getMaxHeight(root_node);
195 }
196 
197 //==============================================================================
198 template <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 //==============================================================================
208 template <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 //==============================================================================
220 template <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 //==============================================================================
231 template <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 //==============================================================================
249 template <typename BV>
251  if (root_node) recurseRefit(root_node);
252 }
253 
254 //==============================================================================
255 template <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 //==============================================================================
266 template <typename BV>
267 size_t HierarchyTree<BV>::size() const {
268  return n_leaves;
269 }
270 
271 //==============================================================================
272 template <typename BV>
274  return root_node;
275 }
276 
277 //==============================================================================
278 template <typename BV>
280  return root_node;
281 }
282 
283 //==============================================================================
284 template <typename BV>
285 void 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 //==============================================================================
298 template <typename BV>
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  CoalScalar min_size = (std::numeric_limits<CoalScalar>::max)();
306  for (NodeVecIterator it1 = lbeg; it1 < lcur_end; ++it1) {
307  for (NodeVecIterator it2 = it1 + 1; it2 < lcur_end; ++it2) {
308  CoalScalar 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  CoalScalar 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  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<CoalScalar>(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  CoalScalar 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<CoalScalar, 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<CoalScalar, 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<CoalScalar, 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<CoalScalar, 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<CoalScalar, 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  Vec3s v = bv.min_ + bv.max_;
974  Vec3s v1 = v - (bv1.min_ + bv1.max_);
975  Vec3s v2 = v - (bv2.min_ + bv2.max_);
976  CoalScalar d1 = fabs(v1[0]) + fabs(v1[1]) + fabs(v1[2]);
977  CoalScalar 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  CoalScalar d1 = fabs(v1[0]) + fabs(v1[1]) + fabs(v1[2]);
990  CoalScalar 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
hierarchy_tree.h
coal::detail::SelectImpl::run
static std::size_t run(const BV &, const NodeBase< BV > &, const NodeBase< BV > &)
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:944
coal::Vec3s
Eigen::Matrix< CoalScalar, 3, 1 > Vec3s
Definition: coal/data_types.h:77
geometric_shapes.d1
float d1
Definition: scripts/geometric_shapes.py:31
coal::detail::HierarchyTree< coal::AABB >::NodeVecIterator
std::vector< NodeBase< coal::AABB > * >::iterator NodeVecIterator
Definition: coal/broadphase/detail/hierarchy_tree.h:142
print
void print(const Eigen::SparseMatrix< Scalar, Options > &mat)
coal::detail::HierarchyTree::insert
Node * insert(const BV &bv, void *data)
Insest a node.
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:88
coal::detail::HierarchyTree::print
void print(Node *root, int depth)
print the tree in a recursive way
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:285
coal::detail::SelectImpl::run
static std::size_t run(const NodeBase< BV > &, const NodeBase< BV > &, const NodeBase< BV > &)
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:938
coal::detail::HierarchyTree::getMaxDepth
size_t getMaxDepth() const
get the max depth of the tree
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:199
data
data
uint32_t
uint32_t
coal
Main namespace.
Definition: coal/broadphase/broadphase_bruteforce.h:44
coal::detail::HierarchyTree::update
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: coal/broadphase/detail/hierarchy_tree-inl.h:123
coal::detail::HierarchyTree::balanceIncremental
void balanceIncremental(int iterations)
balance the tree in an incremental way
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:232
coal::detail::SelectImpl< S, AABB >::run
static std::size_t run(const AABB &query, const NodeBase< AABB > &node1, const NodeBase< AABB > &node2)
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:981
coal::detail::NodeBase::code
uint32_t code
morton code for current BV
Definition: coal/broadphase/detail/node_base.h:69
octree.r
r
Definition: octree.py:9
coal::detail::NodeBase::data
void * data
Definition: coal/broadphase/detail/node_base.h:65
coal::AABB
A class describing the AABB collision structure, which is a box in 3D space determined by two diagona...
Definition: coal/BV/AABB.h:55
coal::detail::HierarchyTree::getMaxHeight
size_t getMaxHeight() const
get the max height of the tree
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:192
a
list a
coal::detail::HierarchyTree::refit
void refit()
refit the tree, i.e., when the leaf nodes' bounding volumes change, update the entire tree in a botto...
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:250
coal::AABB::max_
Vec3s max_
The max point in the AABB.
Definition: coal/BV/AABB.h:60
coal::detail::HierarchyTree::balanceTopdown
void balanceTopdown()
balance the tree from top
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:221
coal::detail::HierarchyTree::clear
void clear()
Clear the tree.
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:106
coal::detail::HierarchyTree::bottomup
void bottomup(const NodeVecIterator lbeg, const NodeVecIterator lend)
construct a tree for a set of leaves from bottom – very heavy way
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:299
coal::detail::HierarchyTree::getRoot
Node * getRoot() const
get the root of the tree
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:273
d
d
coal::detail::NodeBase::children
NodeBase< BV > * children[2]
for leaf node, children nodes
Definition: coal/broadphase/detail/node_base.h:64
coal::detail::HierarchyTree
Class for hierarchy tree structure.
Definition: coal/broadphase/detail/hierarchy_tree.h:56
x
x
coal::detail::HierarchyTree::empty
bool empty() const
Whether the tree is empty.
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:117
coal::detail::NodeBase::parent
NodeBase< BV > * parent
pointer to parent node
Definition: coal/broadphase/detail/node_base.h:54
coal::detail::HierarchyTree::topdown
Node * topdown(const NodeVecIterator lbeg, const NodeVecIterator lend)
construct a tree for a set of leaves from top
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:333
omniidl_be_python_with_docstring.run
def run(tree, args)
Definition: omniidl_be_python_with_docstring.py:140
q
q
coal::detail::SelectImpl
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:937
coal::detail::HierarchyTree::~HierarchyTree
~HierarchyTree()
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:61
coal::detail::HierarchyTree::update_
void update_(Node *leaf, const BV &bv)
update one leaf node's bounding volume
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:651
coal::AABB::min_
Vec3s min_
The min point in the AABB.
Definition: coal/BV/AABB.h:58
generate_distance_plot.b
float b
Definition: generate_distance_plot.py:7
coal::detail::NodeBase::isLeaf
bool isLeaf() const
whether is a leaf
Definition: coal/broadphase/detail/node_base-inl.h:54
coal::detail::HierarchyTree::extractLeaves
void extractLeaves(const Node *root, std::vector< Node * > &leaves) const
extract all the leaves of the tree
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:256
coal::detail::UpdateImpl::run
static bool run(const HierarchyTree< BV > &tree, typename HierarchyTree< BV >::Node *leaf, const BV &bv, const Vec3s &)
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:168
coal::detail::UpdateImpl
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:159
coal::detail::HierarchyTree::topdown_0
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...
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:371
coal::detail::HierarchyTree::size
size_t size() const
number of leaves in the tree
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:267
coal::detail::HierarchyTree::init
void init(std::vector< Node * > &leaves, int level=0)
Initialize the tree by a set of leaves using algorithm with a given level.
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:67
coal::detail::NodeBase::bv
BV bv
the bounding volume for the node
Definition: coal/broadphase/detail/node_base.h:51
coal::detail::SelectImpl< S, AABB >::run
static std::size_t run(const NodeBase< AABB > &node, const NodeBase< AABB > &node1, const NodeBase< AABB > &node2)
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:967
coal::detail::HierarchyTree::HierarchyTree
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: coal/broadphase/detail/hierarchy_tree-inl.h:49
coal::detail::nodeBaseLess
bool nodeBaseLess(NodeBase< BV > *a, NodeBase< BV > *b, int d)
Compare two nodes accoording to the d-th dimension of node center.
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:930
coal::CoalScalar
double CoalScalar
Definition: coal/data_types.h:76
coal::detail::UpdateImpl::run
static bool run(const HierarchyTree< BV > &tree, typename HierarchyTree< BV >::Node *leaf, const BV &bv, const Vec3s &, CoalScalar)
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:160
coal::detail::HierarchyTree::balanceBottomup
void balanceBottomup()
balance the tree from bottom
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:209
coal::detail::select
size_t select(const BV &query, const NodeBase< BV > &node1, const NodeBase< BV > &node2)
select from node1 and node2 which is close to a given query bounding volume. 0 for node1 and 1 for no...
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:959
coal::detail::NodeBase
dynamic AABB tree node
Definition: coal/broadphase/detail/node_base.h:49
coal::detail::HierarchyTree::remove
void remove(Node *leaf)
Remove a leaf node.
Definition: coal/broadphase/detail/hierarchy_tree-inl.h:98
obb.v
list v
Definition: obb.py:48


hpp-fcl
Author(s):
autogenerated on Sat Nov 23 2024 03:44:58