Point Cloud Library (PCL)  1.11.1-dev
octree2buf_base.hpp
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2010-2012, Willow Garage, Inc.
6  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  * * Neither the name of Willow Garage, Inc. nor the names of its
20  * contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  * $Id$
37  */
38 
39 #ifndef PCL_OCTREE_2BUF_BASE_HPP
40 #define PCL_OCTREE_2BUF_BASE_HPP
41 
42 namespace pcl {
43 namespace octree {
44 //////////////////////////////////////////////////////////////////////////////////////////////
45 template <typename LeafContainerT, typename BranchContainerT>
47 : leaf_count_(0)
48 , branch_count_(1)
49 , root_node_(new BranchNode())
50 , depth_mask_(0)
51 , buffer_selector_(0)
52 , tree_dirty_flag_(false)
53 , octree_depth_(0)
54 , dynamic_depth_enabled_(false)
55 {}
56 
57 //////////////////////////////////////////////////////////////////////////////////////////////
58 template <typename LeafContainerT, typename BranchContainerT>
60 {
61  // deallocate tree structure
62  deleteTree();
63  delete (root_node_);
64 }
65 
66 //////////////////////////////////////////////////////////////////////////////////////////////
67 template <typename LeafContainerT, typename BranchContainerT>
68 void
70  unsigned int max_voxel_index_arg)
71 {
72  unsigned int treeDepth;
73 
74  assert(max_voxel_index_arg > 0);
75 
76  // tree depth == amount of bits of maxVoxels
77  treeDepth = std::max(
78  (std::min(static_cast<unsigned int>(OctreeKey::maxDepth),
79  static_cast<unsigned int>(std::ceil(std::log2(max_voxel_index_arg))))),
80  static_cast<unsigned int>(0));
81 
82  // define depthMask_ by setting a single bit to 1 at bit position == tree depth
83  depth_mask_ = (1 << (treeDepth - 1));
84 }
85 
86 //////////////////////////////////////////////////////////////////////////////////////////////
87 template <typename LeafContainerT, typename BranchContainerT>
88 void
90 {
91  assert(depth_arg > 0);
92 
93  // set octree depth
94  octree_depth_ = depth_arg;
95 
96  // define depthMask_ by setting a single bit to 1 at bit position == tree depth
97  depth_mask_ = (1 << (depth_arg - 1));
98 
99  // define max. keys
100  max_key_.x = max_key_.y = max_key_.z = (1 << depth_arg) - 1;
101 }
102 
103 //////////////////////////////////////////////////////////////////////////////////////////////
104 template <typename LeafContainerT, typename BranchContainerT>
105 LeafContainerT*
107  unsigned int idx_y_arg,
108  unsigned int idx_z_arg)
109 {
110  // generate key
111  OctreeKey key(idx_x_arg, idx_y_arg, idx_z_arg);
112 
113  // check if key exist in octree
114  return (findLeaf(key));
115 }
116 
117 //////////////////////////////////////////////////////////////////////////////////////////////
118 template <typename LeafContainerT, typename BranchContainerT>
119 LeafContainerT*
121  unsigned int idx_y_arg,
122  unsigned int idx_z_arg)
123 {
124  // generate key
125  OctreeKey key(idx_x_arg, idx_y_arg, idx_z_arg);
126 
127  // check if key exist in octree
128  return (createLeaf(key));
129 }
130 
131 //////////////////////////////////////////////////////////////////////////////////////////////
132 template <typename LeafContainerT, typename BranchContainerT>
133 bool
135  unsigned int idx_x_arg, unsigned int idx_y_arg, unsigned int idx_z_arg) const
136 {
137  // generate key
138  OctreeKey key(idx_x_arg, idx_y_arg, idx_z_arg);
139 
140  // check if key exist in octree
141  return existLeaf(key);
142 }
143 
144 //////////////////////////////////////////////////////////////////////////////////////////////
145 template <typename LeafContainerT, typename BranchContainerT>
146 void
148  unsigned int idx_y_arg,
149  unsigned int idx_z_arg)
150 {
151  // generate key
152  OctreeKey key(idx_x_arg, idx_y_arg, idx_z_arg);
153 
154  // free voxel at key
155  return (this->removeLeaf(key));
156 }
157 
158 //////////////////////////////////////////////////////////////////////////////////////////////
159 template <typename LeafContainerT, typename BranchContainerT>
160 void
162 {
163  if (root_node_) {
164  // reset octree
165  deleteBranch(*root_node_);
166  leaf_count_ = 0;
167  branch_count_ = 1;
168 
169  tree_dirty_flag_ = false;
170  depth_mask_ = 0;
171  octree_depth_ = 0;
172  }
173 }
174 
175 //////////////////////////////////////////////////////////////////////////////////////////////
176 template <typename LeafContainerT, typename BranchContainerT>
177 void
179 {
180  if (tree_dirty_flag_) {
181  // make sure that all unused branch nodes from previous buffer are deleted
182  treeCleanUpRecursive(root_node_);
183  }
184 
185  // switch butter selector
186  buffer_selector_ = !buffer_selector_;
187 
188  // reset flags
189  tree_dirty_flag_ = true;
190  leaf_count_ = 0;
191  branch_count_ = 1;
192 
193  // we can safely remove children references of root node
194  for (unsigned char child_idx = 0; child_idx < 8; child_idx++) {
195  root_node_->setChildPtr(buffer_selector_, child_idx, nullptr);
196  }
197 }
198 
199 //////////////////////////////////////////////////////////////////////////////////////////////
200 template <typename LeafContainerT, typename BranchContainerT>
201 void
203  std::vector<char>& binary_tree_out_arg, bool do_XOR_encoding_arg)
204 {
205  OctreeKey new_key;
206 
207  // clear binary vector
208  binary_tree_out_arg.clear();
209  binary_tree_out_arg.reserve(this->branch_count_);
210 
211  serializeTreeRecursive(
212  root_node_, new_key, &binary_tree_out_arg, nullptr, do_XOR_encoding_arg, false);
213 
214  // serializeTreeRecursive cleans-up unused octree nodes in previous octree
215  tree_dirty_flag_ = false;
216 }
217 
218 //////////////////////////////////////////////////////////////////////////////////////////////
219 template <typename LeafContainerT, typename BranchContainerT>
220 void
222  std::vector<char>& binary_tree_out_arg,
223  std::vector<LeafContainerT*>& leaf_container_vector_arg,
224  bool do_XOR_encoding_arg)
225 {
226  OctreeKey new_key;
227 
228  // clear output vectors
229  binary_tree_out_arg.clear();
230  leaf_container_vector_arg.clear();
231 
232  leaf_container_vector_arg.reserve(leaf_count_);
233  binary_tree_out_arg.reserve(this->branch_count_);
234 
235  serializeTreeRecursive(root_node_,
236  new_key,
237  &binary_tree_out_arg,
238  &leaf_container_vector_arg,
239  do_XOR_encoding_arg,
240  false);
241 
242  // serializeTreeRecursive cleans-up unused octree nodes in previous octree
243  tree_dirty_flag_ = false;
244 }
245 
246 //////////////////////////////////////////////////////////////////////////////////////////////
247 template <typename LeafContainerT, typename BranchContainerT>
248 void
250  std::vector<LeafContainerT*>& leaf_container_vector_arg)
251 {
252  OctreeKey new_key;
253 
254  // clear output vector
255  leaf_container_vector_arg.clear();
256 
257  leaf_container_vector_arg.reserve(leaf_count_);
258 
259  serializeTreeRecursive(
260  root_node_, new_key, nullptr, &leaf_container_vector_arg, false, false);
261 
262  // serializeLeafsRecursive cleans-up unused octree nodes in previous octree
263  tree_dirty_flag_ = false;
264 }
265 
266 //////////////////////////////////////////////////////////////////////////////////////////////
267 template <typename LeafContainerT, typename BranchContainerT>
268 void
270  std::vector<char>& binary_tree_in_arg, bool do_XOR_decoding_arg)
271 {
272  OctreeKey new_key;
273 
274  // we will rebuild an octree -> reset leafCount
275  leaf_count_ = 0;
276 
277  // iterator for binary tree structure vector
278  std::vector<char>::const_iterator binary_tree_in_it = binary_tree_in_arg.begin();
279  std::vector<char>::const_iterator binary_tree_in_it_end = binary_tree_in_arg.end();
280 
281  deserializeTreeRecursive(root_node_,
282  depth_mask_,
283  new_key,
284  binary_tree_in_it,
285  binary_tree_in_it_end,
286  nullptr,
287  nullptr,
288  false,
289  do_XOR_decoding_arg);
290 
291  // we modified the octree structure -> clean-up/tree-reset might be required
292  tree_dirty_flag_ = false;
293 }
294 
295 //////////////////////////////////////////////////////////////////////////////////////////////
296 template <typename LeafContainerT, typename BranchContainerT>
297 void
299  std::vector<char>& binary_tree_in_arg,
300  std::vector<LeafContainerT*>& leaf_container_vector_arg,
301  bool do_XOR_decoding_arg)
302 {
303  OctreeKey new_key;
304 
305  // set data iterator to first element
306  typename std::vector<LeafContainerT*>::const_iterator leaf_container_vector_it =
307  leaf_container_vector_arg.begin();
308 
309  // set data iterator to last element
310  typename std::vector<LeafContainerT*>::const_iterator leaf_container_vector_it_end =
311  leaf_container_vector_arg.end();
312 
313  // we will rebuild an octree -> reset leafCount
314  leaf_count_ = 0;
315 
316  // iterator for binary tree structure vector
317  std::vector<char>::const_iterator binary_tree_in_it = binary_tree_in_arg.begin();
318  std::vector<char>::const_iterator binary_tree_in_it_end = binary_tree_in_arg.end();
319 
320  deserializeTreeRecursive(root_node_,
321  depth_mask_,
322  new_key,
323  binary_tree_in_it,
324  binary_tree_in_it_end,
325  &leaf_container_vector_it,
326  &leaf_container_vector_it_end,
327  false,
328  do_XOR_decoding_arg);
329 
330  // we modified the octree structure -> clean-up/tree-reset might be required
331  tree_dirty_flag_ = false;
332 }
333 
334 //////////////////////////////////////////////////////////////////////////////////////////////
335 template <typename LeafContainerT, typename BranchContainerT>
336 void
338  std::vector<LeafContainerT*>& leaf_container_vector_arg)
339 {
340  OctreeKey new_key;
341 
342  // clear output vector
343  leaf_container_vector_arg.clear();
344  leaf_container_vector_arg.reserve(leaf_count_);
345 
346  serializeTreeRecursive(
347  root_node_, new_key, nullptr, &leaf_container_vector_arg, false, true);
348 
349  // serializeLeafsRecursive cleans-up unused octree nodes in previous octree buffer
350  tree_dirty_flag_ = false;
351 }
352 
353 //////////////////////////////////////////////////////////////////////////////////////////////
354 template <typename LeafContainerT, typename BranchContainerT>
355 unsigned int
357  const OctreeKey& key_arg,
358  unsigned int depth_mask_arg,
359  BranchNode* branch_arg,
360  LeafNode*& return_leaf_arg,
361  BranchNode*& parent_of_leaf_arg,
362  bool branch_reset_arg)
363 {
364  // branch reset -> this branch has been taken from previous buffer
365  if (branch_reset_arg) {
366  // we can safely remove children references
367  for (unsigned char child_idx = 0; child_idx < 8; child_idx++) {
368  branch_arg->setChildPtr(buffer_selector_, child_idx, nullptr);
369  }
370  }
371 
372  // find branch child from key
373  unsigned char child_idx = key_arg.getChildIdxWithDepthMask(depth_mask_arg);
374 
375  if (depth_mask_arg > 1) {
376  // we have not reached maximum tree depth
377  BranchNode* child_branch;
378  bool doNodeReset;
379 
380  doNodeReset = false;
381 
382  // if required branch does not exist
383  if (!branch_arg->hasChild(buffer_selector_, child_idx)) {
384  // check if we find a branch node reference in previous buffer
385 
386  if (branch_arg->hasChild(!buffer_selector_, child_idx)) {
387  OctreeNode* child_node = branch_arg->getChildPtr(!buffer_selector_, child_idx);
388 
389  if (child_node->getNodeType() == BRANCH_NODE) {
390  child_branch = static_cast<BranchNode*>(child_node);
391  branch_arg->setChildPtr(buffer_selector_, child_idx, child_node);
392  }
393  else {
394  // depth has changed.. child in preceding buffer is a leaf node.
395  deleteBranchChild(*branch_arg, !buffer_selector_, child_idx);
396  child_branch = createBranchChild(*branch_arg, child_idx);
397  }
398 
399  // take child branch from previous buffer
400  doNodeReset = true; // reset the branch pointer array of stolen child node
401  }
402  else {
403  // if required branch does not exist -> create it
404  child_branch = createBranchChild(*branch_arg, child_idx);
405  }
406 
407  branch_count_++;
408  }
409  // required branch node already exists - use it
410  else
411  child_branch = static_cast<BranchNode*>(
412  branch_arg->getChildPtr(buffer_selector_, child_idx));
413 
414  // recursively proceed with indexed child branch
415  return createLeafRecursive(key_arg,
416  depth_mask_arg / 2,
417  child_branch,
418  return_leaf_arg,
419  parent_of_leaf_arg,
420  doNodeReset);
421  }
422 
423  // branch childs are leaf nodes
424  LeafNode* child_leaf;
425  if (!branch_arg->hasChild(buffer_selector_, child_idx)) {
426  // leaf node at child_idx does not exist
427 
428  // check if we can take copy a reference from previous buffer
429  if (branch_arg->hasChild(!buffer_selector_, child_idx)) {
430 
431  OctreeNode* child_node = branch_arg->getChildPtr(!buffer_selector_, child_idx);
432  if (child_node->getNodeType() == LEAF_NODE) {
433  child_leaf = static_cast<LeafNode*>(child_node);
434  branch_arg->setChildPtr(buffer_selector_, child_idx, child_node);
435  }
436  else {
437  // depth has changed.. child in preceding buffer is a leaf node.
438  deleteBranchChild(*branch_arg, !buffer_selector_, child_idx);
439  child_leaf = createLeafChild(*branch_arg, child_idx);
440  }
441  leaf_count_++;
442  }
443  else {
444  // if required leaf does not exist -> create it
445  child_leaf = createLeafChild(*branch_arg, child_idx);
446  leaf_count_++;
447  }
448 
449  // return leaf node
450  return_leaf_arg = child_leaf;
451  parent_of_leaf_arg = branch_arg;
452  }
453  else {
454  // leaf node already exist
455  return_leaf_arg =
456  static_cast<LeafNode*>(branch_arg->getChildPtr(buffer_selector_, child_idx));
457  parent_of_leaf_arg = branch_arg;
458  }
459 
460  return depth_mask_arg;
461 }
462 
463 //////////////////////////////////////////////////////////////////////////////////////////////
464 template <typename LeafContainerT, typename BranchContainerT>
465 void
467  const OctreeKey& key_arg,
468  unsigned int depth_mask_arg,
469  BranchNode* branch_arg,
470  LeafContainerT*& result_arg) const
471 {
472  // return leaf node
473  unsigned char child_idx;
474 
475  // find branch child from key
476  child_idx = key_arg.getChildIdxWithDepthMask(depth_mask_arg);
477 
478  if (depth_mask_arg > 1) {
479  // we have not reached maximum tree depth
480  BranchNode* child_branch;
481  child_branch =
482  static_cast<BranchNode*>(branch_arg->getChildPtr(buffer_selector_, child_idx));
483 
484  if (child_branch)
485  // recursively proceed with indexed child branch
486  findLeafRecursive(key_arg, depth_mask_arg / 2, child_branch, result_arg);
487  }
488  else {
489  // we reached leaf node level
490  if (branch_arg->hasChild(buffer_selector_, child_idx)) {
491  // return existing leaf node
492  LeafNode* leaf_node =
493  static_cast<LeafNode*>(branch_arg->getChildPtr(buffer_selector_, child_idx));
494  result_arg = leaf_node->getContainerPtr();
495  }
496  }
497 }
498 
499 //////////////////////////////////////////////////////////////////////////////////////////////
500 template <typename LeafContainerT, typename BranchContainerT>
501 bool
503  const OctreeKey& key_arg, unsigned int depth_mask_arg, BranchNode* branch_arg)
504 {
505  // index to branch child
506  unsigned char child_idx;
507  // indicates if branch is empty and can be safely removed
508  bool bNoChilds;
509 
510  // find branch child from key
511  child_idx = key_arg.getChildIdxWithDepthMask(depth_mask_arg);
512 
513  if (depth_mask_arg > 1) {
514  // we have not reached maximum tree depth
515  BranchNode* child_branch;
516 
517  // next branch child on our path through the tree
518  child_branch =
519  static_cast<BranchNode*>(branch_arg->getChildPtr(buffer_selector_, child_idx));
520 
521  if (child_branch) {
522  // recursively explore the indexed child branch
523  bool bBranchOccupied =
524  deleteLeafRecursive(key_arg, depth_mask_arg / 2, child_branch);
525 
526  if (!bBranchOccupied) {
527  // child branch does not own any sub-child nodes anymore -> delete child branch
528  deleteBranchChild(*branch_arg, buffer_selector_, child_idx);
529  branch_count_--;
530  }
531  }
532  }
533  else {
534  // our child is a leaf node -> delete it
535  deleteBranchChild(*branch_arg, buffer_selector_, child_idx);
536  leaf_count_--;
537  }
538 
539  // check if current branch still owns childs
540  bNoChilds = false;
541  for (child_idx = 0; child_idx < 8; child_idx++) {
542  bNoChilds = branch_arg->hasChild(buffer_selector_, child_idx);
543  if (bNoChilds)
544  break;
545  }
546 
547  // return true if current branch can be deleted
548  return (bNoChilds);
549 }
550 
551 //////////////////////////////////////////////////////////////////////////////////////////////
552 template <typename LeafContainerT, typename BranchContainerT>
553 void
555  BranchNode* branch_arg,
556  OctreeKey& key_arg,
557  std::vector<char>* binary_tree_out_arg,
558  typename std::vector<LeafContainerT*>* leaf_container_vector_arg,
559  bool do_XOR_encoding_arg,
560  bool new_leafs_filter_arg)
561 {
562  // bit pattern
563  char branch_bit_pattern_curr_buffer;
564  char branch_bit_pattern_prev_buffer;
565  char node_XOR_bit_pattern;
566 
567  // occupancy bit patterns of branch node (current and previous octree buffer)
568  branch_bit_pattern_curr_buffer = getBranchBitPattern(*branch_arg, buffer_selector_);
569  branch_bit_pattern_prev_buffer = getBranchBitPattern(*branch_arg, !buffer_selector_);
570 
571  // XOR of current and previous occupancy bit patterns
572  node_XOR_bit_pattern =
573  branch_bit_pattern_curr_buffer ^ branch_bit_pattern_prev_buffer;
574 
575  if (binary_tree_out_arg) {
576  if (do_XOR_encoding_arg) {
577  // write XOR bit pattern to output vector
578  binary_tree_out_arg->push_back(node_XOR_bit_pattern);
579  }
580  else {
581  // write bit pattern of current buffer to output vector
582  binary_tree_out_arg->push_back(branch_bit_pattern_curr_buffer);
583  }
584  }
585 
586  // iterate over all children
587  for (unsigned char child_idx = 0; child_idx < 8; child_idx++) {
588  if (branch_arg->hasChild(buffer_selector_, child_idx)) {
589  // add current branch voxel to key
590  key_arg.pushBranch(child_idx);
591 
592  OctreeNode* child_node = branch_arg->getChildPtr(buffer_selector_, child_idx);
593 
594  switch (child_node->getNodeType()) {
595  case BRANCH_NODE: {
596  // recursively proceed with indexed child branch
597  serializeTreeRecursive(static_cast<BranchNode*>(child_node),
598  key_arg,
599  binary_tree_out_arg,
600  leaf_container_vector_arg,
601  do_XOR_encoding_arg,
602  new_leafs_filter_arg);
603  break;
604  }
605  case LEAF_NODE: {
606  LeafNode* child_leaf = static_cast<LeafNode*>(child_node);
607 
608  if (new_leafs_filter_arg) {
609  if (!branch_arg->hasChild(!buffer_selector_, child_idx)) {
610  if (leaf_container_vector_arg)
611  leaf_container_vector_arg->push_back(child_leaf->getContainerPtr());
612 
613  serializeTreeCallback(**child_leaf, key_arg);
614  }
615  }
616  else {
617 
618  if (leaf_container_vector_arg)
619  leaf_container_vector_arg->push_back(child_leaf->getContainerPtr());
620 
621  serializeTreeCallback(**child_leaf, key_arg);
622  }
623 
624  break;
625  }
626  default:
627  break;
628  }
629 
630  // pop current branch voxel from key
631  key_arg.popBranch();
632  }
633  else if (branch_arg->hasChild(!buffer_selector_, child_idx)) {
634  // delete branch, free memory
635  deleteBranchChild(*branch_arg, !buffer_selector_, child_idx);
636  }
637  }
638 }
639 
640 //////////////////////////////////////////////////////////////////////////////////////////////
641 template <typename LeafContainerT, typename BranchContainerT>
642 void
644  BranchNode* branch_arg,
645  unsigned int depth_mask_arg,
646  OctreeKey& key_arg,
647  typename std::vector<char>::const_iterator& binaryTreeIT_arg,
648  typename std::vector<char>::const_iterator& binaryTreeIT_End_arg,
649  typename std::vector<LeafContainerT*>::const_iterator* dataVectorIterator_arg,
650  typename std::vector<LeafContainerT*>::const_iterator* dataVectorEndIterator_arg,
651  bool branch_reset_arg,
652  bool do_XOR_decoding_arg)
653 {
654 
655  // branch reset -> this branch has been taken from previous buffer
656  if (branch_reset_arg) {
657  // we can safely remove children references
658  for (unsigned char child_idx = 0; child_idx < 8; child_idx++) {
659  branch_arg->setChildPtr(buffer_selector_, child_idx, nullptr);
660  }
661  }
662 
663  if (binaryTreeIT_arg != binaryTreeIT_End_arg) {
664  // read branch occupancy bit pattern from vector
665  char nodeBits = *binaryTreeIT_arg++;
666 
667  // recover branch occupancy bit pattern
668  char recoveredNodeBits;
669  if (do_XOR_decoding_arg) {
670  recoveredNodeBits =
671  getBranchBitPattern(*branch_arg, !buffer_selector_) ^ nodeBits;
672  }
673  else {
674  recoveredNodeBits = nodeBits;
675  }
676 
677  // iterate over all children
678  for (unsigned char child_idx = 0; child_idx < 8; child_idx++) {
679  // if occupancy bit for child_idx is set..
680  if (recoveredNodeBits & (1 << child_idx)) {
681  // add current branch voxel to key
682  key_arg.pushBranch(child_idx);
683 
684  if (depth_mask_arg > 1) {
685  // we have not reached maximum tree depth
686 
687  bool doNodeReset = false;
688 
689  BranchNode* child_branch;
690 
691  // check if we find a branch node reference in previous buffer
692  if (!branch_arg->hasChild(buffer_selector_, child_idx)) {
693 
694  if (branch_arg->hasChild(!buffer_selector_, child_idx)) {
695  OctreeNode* child_node =
696  branch_arg->getChildPtr(!buffer_selector_, child_idx);
697 
698  if (child_node->getNodeType() == BRANCH_NODE) {
699  child_branch = static_cast<BranchNode*>(child_node);
700  branch_arg->setChildPtr(buffer_selector_, child_idx, child_node);
701  }
702  else {
703  // depth has changed.. child in preceding buffer is a leaf node.
704  deleteBranchChild(*branch_arg, !buffer_selector_, child_idx);
705  child_branch = createBranchChild(*branch_arg, child_idx);
706  }
707 
708  // take child branch from previous buffer
709  doNodeReset = true; // reset the branch pointer array of stolen child node
710  }
711  else {
712  // if required branch does not exist -> create it
713  child_branch = createBranchChild(*branch_arg, child_idx);
714  }
715 
716  branch_count_++;
717  }
718  else {
719  // required branch node already exists - use it
720  child_branch = static_cast<BranchNode*>(
721  branch_arg->getChildPtr(buffer_selector_, child_idx));
722  }
723 
724  // recursively proceed with indexed child branch
725  deserializeTreeRecursive(child_branch,
726  depth_mask_arg / 2,
727  key_arg,
728  binaryTreeIT_arg,
729  binaryTreeIT_End_arg,
730  dataVectorIterator_arg,
731  dataVectorEndIterator_arg,
732  doNodeReset,
733  do_XOR_decoding_arg);
734  }
735  else {
736  // branch childs are leaf nodes
737  LeafNode* child_leaf;
738 
739  // check if we can take copy a reference pointer from previous buffer
740  if (branch_arg->hasChild(!buffer_selector_, child_idx)) {
741  // take child leaf node from previous buffer
742  OctreeNode* child_node =
743  branch_arg->getChildPtr(!buffer_selector_, child_idx);
744  if (child_node->getNodeType() == LEAF_NODE) {
745  child_leaf = static_cast<LeafNode*>(child_node);
746  branch_arg->setChildPtr(buffer_selector_, child_idx, child_node);
747  }
748  else {
749  // depth has changed.. child in preceding buffer is a leaf node.
750  deleteBranchChild(*branch_arg, !buffer_selector_, child_idx);
751  child_leaf = createLeafChild(*branch_arg, child_idx);
752  }
753  }
754  else {
755  // if required leaf does not exist -> create it
756  child_leaf = createLeafChild(*branch_arg, child_idx);
757  }
758 
759  // we reached leaf node level
760 
761  if (dataVectorIterator_arg &&
762  (*dataVectorIterator_arg != *dataVectorEndIterator_arg)) {
763  LeafContainerT& container = **child_leaf;
764  container = ***dataVectorIterator_arg;
765  ++*dataVectorIterator_arg;
766  }
767 
768  leaf_count_++;
769 
770  // execute deserialization callback
771  deserializeTreeCallback(**child_leaf, key_arg);
772  }
773 
774  // pop current branch voxel from key
775  key_arg.popBranch();
776  }
777  else if (branch_arg->hasChild(!buffer_selector_, child_idx)) {
778  // remove old branch pointer information in current branch
779  branch_arg->setChildPtr(buffer_selector_, child_idx, nullptr);
780 
781  // remove unused branches in previous buffer
782  deleteBranchChild(*branch_arg, !buffer_selector_, child_idx);
783  }
784  }
785  }
786 }
787 
788 //////////////////////////////////////////////////////////////////////////////////////////////
789 template <typename LeafContainerT, typename BranchContainerT>
790 void
792  BranchNode* branch_arg)
793 {
794  // occupancy bit pattern of branch node (previous octree buffer)
795  char occupied_children_bit_pattern_prev_buffer =
796  getBranchBitPattern(*branch_arg, !buffer_selector_);
797 
798  // XOR of current and previous occupancy bit patterns
799  char node_XOR_bit_pattern = getBranchXORBitPattern(*branch_arg);
800 
801  // bit pattern indicating unused octree nodes in previous branch
802  char unused_branches_bit_pattern =
803  node_XOR_bit_pattern & occupied_children_bit_pattern_prev_buffer;
804 
805  // iterate over all children
806  for (unsigned char child_idx = 0; child_idx < 8; child_idx++) {
807  if (branch_arg->hasChild(buffer_selector_, child_idx)) {
808  OctreeNode* child_node = branch_arg->getChildPtr(buffer_selector_, child_idx);
809 
810  switch (child_node->getNodeType()) {
811  case BRANCH_NODE: {
812  // recursively proceed with indexed child branch
813  treeCleanUpRecursive(static_cast<BranchNode*>(child_node));
814  break;
815  }
816  case LEAF_NODE:
817  // leaf level - nothing to do..
818  break;
819  default:
820  break;
821  }
822  }
823 
824  // check for unused branches in previous buffer
825  if (unused_branches_bit_pattern & (1 << child_idx)) {
826  // delete branch, free memory
827  deleteBranchChild(*branch_arg, !buffer_selector_, child_idx);
828  }
829  }
830 }
831 } // namespace octree
832 } // namespace pcl
833 
834 #define PCL_INSTANTIATE_Octree2BufBase(T) \
835  template class PCL_EXPORTS pcl::octree::Octree2BufBase<T>;
836 
837 #endif
pcl
Definition: convolution.h:46
pcl::octree::OctreeKey::pushBranch
void pushBranch(unsigned char childIndex)
push a child node to the octree key
Definition: octree_key.h:112
pcl::octree::OctreeNode::getNodeType
virtual node_type_t getNodeType() const =0
Pure virtual method for receiving the type of octree node (branch or leaf)
pcl::octree::BufferedBranchNode::getChildPtr
OctreeNode * getChildPtr(unsigned char buffer_arg, unsigned char index_arg) const
Get child pointer in current branch node.
Definition: octree2buf_base.h:95
pcl::octree::OctreeKey::popBranch
void popBranch()
pop child node from octree key
Definition: octree_key.h:122
pcl::octree::OctreeKey
Octree key class
Definition: octree_key.h:52
pcl::octree::OctreeNode
Abstract octree node class
Definition: octree_nodes.h:58
pcl::octree::BufferedBranchNode::hasChild
bool hasChild(unsigned char buffer_arg, unsigned char index_arg) const
Check if branch is pointing to a particular child node.
Definition: octree2buf_base.h:121
pcl::octree::LEAF_NODE
@ LEAF_NODE
Definition: octree_nodes.h:51
pcl::octree::Octree2BufBase
Octree double buffer class
Definition: octree2buf_base.h:217
pcl::octree::OctreeLeafNode
Abstract octree leaf class
Definition: octree_nodes.h:80
pcl::octree::BRANCH_NODE
@ BRANCH_NODE
Definition: octree_nodes.h:51
pcl::octree::Octree2BufBase::Octree2BufBase
Octree2BufBase()
Empty constructor.
Definition: octree2buf_base.hpp:46
pcl::octree::BufferedBranchNode
Definition: octree2buf_base.h:53
pcl::octree::OctreeKey::getChildIdxWithDepthMask
unsigned char getChildIdxWithDepthMask(unsigned int depthMask) const
get child node index using depthMask
Definition: octree_key.h:134
pcl::octree::BufferedBranchNode::setChildPtr
void setChildPtr(unsigned char buffer_arg, unsigned char index_arg, OctreeNode *newNode_arg)
Set child pointer in current branch node.
Definition: octree2buf_base.h:107
pcl::octree::OctreeLeafNode::getContainerPtr
const ContainerT * getContainerPtr() const
Get const pointer to container.
Definition: octree_nodes.h:153