Point Cloud Library (PCL)  1.15.1-dev
octree_base.hpp
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2010-2011, 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_BASE_HPP
40 #define PCL_OCTREE_BASE_HPP
41 
42 #include <pcl/octree/octree_base.h>
43 #include <pcl/octree/octree_key.h>
44 
45 #include <vector>
46 
47 namespace pcl {
48 namespace octree {
49 //////////////////////////////////////////////////////////////////////////////////////////////
50 template <typename LeafContainerT, typename BranchContainerT>
52 : root_node_(new BranchNode())
53 {}
54 
55 //////////////////////////////////////////////////////////////////////////////////////////////
56 template <typename LeafContainerT, typename BranchContainerT>
58 {
59  // deallocate tree structure
60  deleteTree();
61  delete (root_node_);
62 }
63 
64 //////////////////////////////////////////////////////////////////////////////////////////////
65 template <typename LeafContainerT, typename BranchContainerT>
66 void
68  uindex_t max_voxel_index_arg)
69 {
70  uindex_t tree_depth;
71 
72  if (max_voxel_index_arg <= 0) {
73  PCL_ERROR("[pcl::octree::OctreeBase::setMaxVoxelIndex] Max voxel index (%lu) must "
74  "be > 0!\n",
75  max_voxel_index_arg);
76  return;
77  }
78 
79  // tree depth == bitlength of maxVoxels
80  tree_depth =
81  std::min(static_cast<uindex_t>(OctreeKey::getMaxDepth()),
82  static_cast<uindex_t>(std::ceil(std::log2(max_voxel_index_arg))));
83 
84  setTreeDepth(tree_depth);
85 }
86 
87 //////////////////////////////////////////////////////////////////////////////////////////////
88 template <typename LeafContainerT, typename BranchContainerT>
89 void
91 {
92  if (depth_arg <= 0) {
93  PCL_ERROR("[pcl::octree::OctreeBase::setTreeDepth] Tree depth (%lu) must be > 0!\n",
94  depth_arg);
95  return;
96  }
97  if (depth_arg > OctreeKey::getMaxDepth()) {
98  PCL_ERROR("[pcl::octree::OctreeBase::setTreeDepth] Tree depth (%lu) must be <= max "
99  "depth(%lu)!\n",
100  depth_arg,
102  return;
103  }
104 
105  // set octree depth
106  octree_depth_ = depth_arg;
107 
108  // define depth_mask_ by setting a single bit to 1 at bit position == tree depth
109  depth_mask_ = (1 << (depth_arg - 1));
110 
111  // define max_key_
112  max_key_.x = max_key_.y = max_key_.z = (1 << depth_arg) - 1;
113 }
114 
115 //////////////////////////////////////////////////////////////////////////////////////////////
116 template <typename LeafContainerT, typename BranchContainerT>
117 LeafContainerT*
119  uindex_t idx_y_arg,
120  uindex_t idx_z_arg) const
121 {
122  // generate key
123  OctreeKey key(idx_x_arg, idx_y_arg, idx_z_arg);
124 
125  // find the leaf node addressed by key
126  return (findLeaf(key));
127 }
128 
129 //////////////////////////////////////////////////////////////////////////////////////////////
130 template <typename LeafContainerT, typename BranchContainerT>
131 LeafContainerT*
133  uindex_t idx_y_arg,
134  uindex_t idx_z_arg)
135 {
136  // generate key
137  OctreeKey key(idx_x_arg, idx_y_arg, idx_z_arg);
138 
139  // create a leaf node addressed by key
140  return (createLeaf(key));
141 }
142 
143 //////////////////////////////////////////////////////////////////////////////////////////////
144 template <typename LeafContainerT, typename BranchContainerT>
145 bool
147  uindex_t idx_y_arg,
148  uindex_t idx_z_arg) const
149 {
150  // generate key
151  OctreeKey key(idx_x_arg, idx_y_arg, idx_z_arg);
152 
153  // check if key exist in octree
154  return (existLeaf(key));
155 }
156 
157 //////////////////////////////////////////////////////////////////////////////////////////////
158 template <typename LeafContainerT, typename BranchContainerT>
159 void
161  uindex_t idx_y_arg,
162  uindex_t idx_z_arg)
163 {
164  // generate key
165  OctreeKey key(idx_x_arg, idx_y_arg, idx_z_arg);
166 
167  // delete the leaf node addressed by key
168  deleteLeafRecursive(key, depth_mask_, root_node_);
169 }
170 
171 //////////////////////////////////////////////////////////////////////////////////////////////
172 template <typename LeafContainerT, typename BranchContainerT>
173 void
175 {
176 
177  if (root_node_) {
178  // reset octree
179  deleteBranch(*root_node_);
180  leaf_count_ = 0;
181  branch_count_ = 1;
182  }
183 }
184 
185 //////////////////////////////////////////////////////////////////////////////////////////////
186 template <typename LeafContainerT, typename BranchContainerT>
187 void
189  std::vector<char>& binary_tree_out_arg) const
190 {
191 
192  OctreeKey new_key;
193 
194  // clear binary vector
195  binary_tree_out_arg.clear();
196  binary_tree_out_arg.reserve(this->branch_count_);
197 
198  serializeTreeRecursive(root_node_, new_key, &binary_tree_out_arg, nullptr);
199 }
200 
201 //////////////////////////////////////////////////////////////////////////////////////////////
202 template <typename LeafContainerT, typename BranchContainerT>
203 void
205  std::vector<char>& binary_tree_out_arg,
206  std::vector<LeafContainerT*>& leaf_container_vector_arg) const
207 {
208 
209  OctreeKey new_key;
210 
211  // clear output vectors
212  binary_tree_out_arg.clear();
213  leaf_container_vector_arg.clear();
214 
215  binary_tree_out_arg.reserve(this->branch_count_);
216  leaf_container_vector_arg.reserve(this->leaf_count_);
217 
218  serializeTreeRecursive(
219  root_node_, new_key, &binary_tree_out_arg, &leaf_container_vector_arg);
220 }
221 
222 //////////////////////////////////////////////////////////////////////////////////////////////
223 template <typename LeafContainerT, typename BranchContainerT>
224 void
226  std::vector<LeafContainerT*>& leaf_container_vector_arg)
227 {
228  OctreeKey new_key;
229 
230  // clear output vector
231  leaf_container_vector_arg.clear();
232 
233  leaf_container_vector_arg.reserve(this->leaf_count_);
234 
235  serializeTreeRecursive(root_node_, new_key, nullptr, &leaf_container_vector_arg);
236 }
237 
238 //////////////////////////////////////////////////////////////////////////////////////////////
239 template <typename LeafContainerT, typename BranchContainerT>
240 void
242  std::vector<char>& binary_tree_out_arg)
243 {
244  OctreeKey new_key;
245 
246  // free existing tree before tree rebuild
247  deleteTree();
248 
249  // iterator for binary tree structure vector
250  auto binary_tree_out_it = binary_tree_out_arg.cbegin();
251  auto binary_tree_out_it_end = binary_tree_out_arg.cend();
252 
253  deserializeTreeRecursive(root_node_,
254  depth_mask_,
255  new_key,
256  binary_tree_out_it,
257  binary_tree_out_it_end,
258  nullptr,
259  nullptr);
260 }
261 
262 //////////////////////////////////////////////////////////////////////////////////////////////
263 template <typename LeafContainerT, typename BranchContainerT>
264 void
266  std::vector<char>& binary_tree_in_arg,
267  std::vector<LeafContainerT*>& leaf_container_vector_arg)
268 {
269  OctreeKey new_key;
270 
271  // set data iterator to first element
272  auto leaf_vector_it = leaf_container_vector_arg.cbegin();
273 
274  // set data iterator to last element
275  auto leaf_vector_it_end = leaf_container_vector_arg.cend();
276 
277  // free existing tree before tree rebuild
278  deleteTree();
279 
280  // iterator for binary tree structure vector
281  auto binary_tree_input_it = binary_tree_in_arg.cbegin();
282  auto binary_tree_input_it_end = binary_tree_in_arg.cend();
283 
284  deserializeTreeRecursive(root_node_,
285  depth_mask_,
286  new_key,
287  binary_tree_input_it,
288  binary_tree_input_it_end,
289  &leaf_vector_it,
290  &leaf_vector_it_end);
291 }
292 
293 //////////////////////////////////////////////////////////////////////////////////////////////
294 template <typename LeafContainerT, typename BranchContainerT>
295 uindex_t
297  const OctreeKey& key_arg,
298  uindex_t depth_mask_arg,
299  BranchNode* branch_arg,
300  LeafNode*& return_leaf_arg,
301  BranchNode*& parent_of_leaf_arg)
302 {
303  // index to branch child
304  unsigned char child_idx;
305 
306  // find branch child from key
307  child_idx = key_arg.getChildIdxWithDepthMask(depth_mask_arg);
308 
309  OctreeNode* child_node = (*branch_arg)[child_idx];
310 
311  if (!child_node) {
312  if ((!dynamic_depth_enabled_) && (depth_mask_arg > 1)) {
313  // if required branch does not exist -> create it
314  BranchNode* childBranch = createBranchChild(*branch_arg, child_idx);
315 
316  branch_count_++;
317 
318  // recursively proceed with indexed child branch
319  return createLeafRecursive(key_arg,
320  depth_mask_arg >> 1,
321  childBranch,
322  return_leaf_arg,
323  parent_of_leaf_arg);
324  }
325  // if leaf node at child_idx does not exist
326  LeafNode* leaf_node = createLeafChild(*branch_arg, child_idx);
327  return_leaf_arg = leaf_node;
328  parent_of_leaf_arg = branch_arg;
329  this->leaf_count_++;
330  }
331  else {
332  // Node exists already
333  switch (child_node->getNodeType()) {
334  case BRANCH_NODE:
335  // recursively proceed with indexed child branch
336  return createLeafRecursive(key_arg,
337  depth_mask_arg >> 1,
338  static_cast<BranchNode*>(child_node),
339  return_leaf_arg,
340  parent_of_leaf_arg);
341  break;
342 
343  case LEAF_NODE:
344  return_leaf_arg = static_cast<LeafNode*>(child_node);
345  parent_of_leaf_arg = branch_arg;
346  break;
347  }
348  }
349 
350  return (depth_mask_arg >> 1);
351 }
352 
353 //////////////////////////////////////////////////////////////////////////////////////////////
354 template <typename LeafContainerT, typename BranchContainerT>
355 void
357  const OctreeKey& key_arg,
358  uindex_t depth_mask_arg,
359  BranchNode* branch_arg,
360  LeafContainerT*& result_arg) const
361 {
362  // index to branch child
363  unsigned char child_idx;
364 
365  // find branch child from key
366  child_idx = key_arg.getChildIdxWithDepthMask(depth_mask_arg);
367 
368  OctreeNode* child_node = (*branch_arg)[child_idx];
369 
370  if (child_node) {
371  switch (child_node->getNodeType()) {
372  case BRANCH_NODE:
373  // we have not reached maximum tree depth
374  BranchNode* child_branch;
375  child_branch = static_cast<BranchNode*>(child_node);
376 
377  findLeafRecursive(key_arg, depth_mask_arg >> 1, child_branch, result_arg);
378  break;
379 
380  case LEAF_NODE:
381  // return existing leaf node
382  LeafNode* child_leaf;
383  child_leaf = static_cast<LeafNode*>(child_node);
384 
385  result_arg = child_leaf->getContainerPtr();
386  break;
387  }
388  }
389 }
390 
391 //////////////////////////////////////////////////////////////////////////////////////////////
392 template <typename LeafContainerT, typename BranchContainerT>
393 bool
395  const OctreeKey& key_arg, uindex_t depth_mask_arg, BranchNode* branch_arg)
396 {
397  // index to branch child
398  unsigned char child_idx;
399  // indicates if branch has children, if so, it can't be removed
400  bool b_has_children;
401 
402  // find branch child from key
403  child_idx = key_arg.getChildIdxWithDepthMask(depth_mask_arg);
404 
405  OctreeNode* child_node = (*branch_arg)[child_idx];
406 
407  if (child_node) {
408  switch (child_node->getNodeType()) {
409 
410  case BRANCH_NODE:
411  BranchNode* child_branch;
412  child_branch = static_cast<BranchNode*>(child_node);
413 
414  // recursively explore the indexed child branch
415  b_has_children = deleteLeafRecursive(key_arg, depth_mask_arg >> 1, child_branch);
416 
417  if (!b_has_children) {
418  // child branch does not own any sub-child nodes anymore -> delete child branch
419  deleteBranchChild(*branch_arg, child_idx);
420  branch_count_--;
421  }
422  break;
423 
424  case LEAF_NODE:
425  // return existing leaf node
426 
427  // our child is a leaf node -> delete it
428  deleteBranchChild(*branch_arg, child_idx);
429  this->leaf_count_--;
430  break;
431  }
432  }
433 
434  // check if current branch still owns children
435  b_has_children = false;
436  for (child_idx = 0; (!b_has_children) && (child_idx < 8); child_idx++) {
437  b_has_children = branch_arg->hasChild(child_idx);
438  }
439  // return false if current branch can be deleted
440  return (b_has_children);
441 }
442 
443 //////////////////////////////////////////////////////////////////////////////////////////////
444 template <typename LeafContainerT, typename BranchContainerT>
445 void
447  const BranchNode* branch_arg,
448  OctreeKey& key_arg,
449  std::vector<char>* binary_tree_out_arg,
450  typename std::vector<LeafContainerT*>* leaf_container_vector_arg) const
451 {
452  char node_bit_pattern;
453 
454  // branch occupancy bit pattern
455  node_bit_pattern = getBranchBitPattern(*branch_arg);
456 
457  // write bit pattern to output vector
458  if (binary_tree_out_arg)
459  binary_tree_out_arg->push_back(node_bit_pattern);
460 
461  // iterate over all children
462  for (unsigned char child_idx = 0; child_idx < 8; child_idx++) {
463 
464  // if child exist
465  if (branch_arg->hasChild(child_idx)) {
466  // add current branch voxel to key
467  key_arg.pushBranch(child_idx);
468 
469  OctreeNode* childNode = branch_arg->getChildPtr(child_idx);
470 
471  switch (childNode->getNodeType()) {
472  case BRANCH_NODE: {
473  // recursively proceed with indexed child branch
474  serializeTreeRecursive(static_cast<const BranchNode*>(childNode),
475  key_arg,
476  binary_tree_out_arg,
477  leaf_container_vector_arg);
478  break;
479  }
480  case LEAF_NODE: {
481  auto* child_leaf = static_cast<LeafNode*>(childNode);
482 
483  if (leaf_container_vector_arg)
484  leaf_container_vector_arg->push_back(child_leaf->getContainerPtr());
485 
486  // we reached a leaf node -> execute serialization callback
487  serializeTreeCallback(**child_leaf, key_arg);
488  break;
489  }
490  default:
491  break;
492  }
493 
494  // pop current branch voxel from key
495  key_arg.popBranch();
496  }
497  }
498 }
499 
500 //////////////////////////////////////////////////////////////////////////////////////////////
501 template <typename LeafContainerT, typename BranchContainerT>
502 void
504  BranchNode* branch_arg,
505  uindex_t depth_mask_arg,
506  OctreeKey& key_arg,
507  typename std::vector<char>::const_iterator& binary_tree_input_it_arg,
508  typename std::vector<char>::const_iterator& binary_tree_input_it_end_arg,
509  typename std::vector<LeafContainerT*>::const_iterator* leaf_container_vector_it_arg,
510  typename std::vector<LeafContainerT*>::const_iterator*
511  leaf_container_vector_it_end_arg)
512 {
513 
514  if (binary_tree_input_it_arg != binary_tree_input_it_end_arg) {
515  // read branch occupancy bit pattern from input vector
516  char node_bits = (*binary_tree_input_it_arg);
517  binary_tree_input_it_arg++;
518 
519  // iterate over all children
520  for (unsigned char child_idx = 0; child_idx < 8; child_idx++) {
521  // if occupancy bit for child_idx is set..
522  if (node_bits & (1 << child_idx)) {
523  // add current branch voxel to key
524  key_arg.pushBranch(child_idx);
525 
526  if (depth_mask_arg > 1) {
527  // we have not reached maximum tree depth
528  BranchNode* newBranch = createBranchChild(*branch_arg, child_idx);
529 
530  branch_count_++;
531 
532  // recursively proceed with new child branch
533  deserializeTreeRecursive(newBranch,
534  depth_mask_arg >> 1,
535  key_arg,
536  binary_tree_input_it_arg,
537  binary_tree_input_it_end_arg,
538  leaf_container_vector_it_arg,
539  leaf_container_vector_it_end_arg);
540  }
541  else {
542  // we reached leaf node level
543 
544  LeafNode* child_leaf = createLeafChild(*branch_arg, child_idx);
545 
546  if (leaf_container_vector_it_arg &&
547  (*leaf_container_vector_it_arg != *leaf_container_vector_it_end_arg)) {
548  LeafContainerT& container = **child_leaf;
549  LeafContainerT* src_container_ptr = **leaf_container_vector_it_arg;
550  container = *src_container_ptr;
551  ++*leaf_container_vector_it_arg;
552  }
553 
554  leaf_count_++;
555 
556  // execute deserialization callback
557  deserializeTreeCallback(**child_leaf, key_arg);
558  }
559 
560  // pop current branch voxel from key
561  key_arg.popBranch();
562  }
563  }
564  }
565 }
566 
567 } // namespace octree
568 } // namespace pcl
569 
570 #define PCL_INSTANTIATE_OctreeBase(T) \
571  template class PCL_EXPORTS pcl::octree::OctreeBase<T>;
572 
573 #endif
void findLeafRecursive(const OctreeKey &key_arg, uindex_t depth_mask_arg, BranchNode *branch_arg, LeafContainerT *&result_arg) const
Recursively search for a given leaf node and return a pointer.
void setTreeDepth(uindex_t max_depth_arg)
Set the maximum depth of the octree.
Definition: octree_base.hpp:90
void deserializeTreeRecursive(BranchNode *branch_arg, uindex_t depth_mask_arg, OctreeKey &key_arg, typename std::vector< char >::const_iterator &binary_tree_input_it_arg, typename std::vector< char >::const_iterator &binary_tree_input_it_end_arg, typename std::vector< LeafContainerT * >::const_iterator *leaf_container_vector_it_arg, typename std::vector< LeafContainerT * >::const_iterator *leaf_container_vector_it_end_arg)
Recursive method for deserializing octree structure.
void serializeLeafs(std::vector< LeafContainerT * > &leaf_container_vector_arg)
Outputs a vector of all LeafContainerT elements that are stored within the octree leaf nodes.
LeafContainerT * createLeaf(uindex_t idx_x_arg, uindex_t idx_y_arg, uindex_t idx_z_arg)
Create new leaf node at (idx_x_arg, idx_y_arg, idx_z_arg).
virtual ~OctreeBase()
Empty deconstructor.
Definition: octree_base.hpp:57
bool deleteLeafRecursive(const OctreeKey &key_arg, uindex_t depth_mask_arg, BranchNode *branch_arg)
Recursively search and delete leaf node.
uindex_t createLeafRecursive(const OctreeKey &key_arg, uindex_t depth_mask_arg, BranchNode *branch_arg, LeafNode *&return_leaf_arg, BranchNode *&parent_of_leaf_arg)
Create a leaf node at octree key.
void deserializeTree(std::vector< char > &binary_tree_input_arg)
Deserialize a binary octree description vector and create a corresponding octree structure.
void deleteTree()
Delete the octree structure and its leaf nodes.
void serializeTree(std::vector< char > &binary_tree_out_arg) const
Serialize octree into a binary output vector describing its branch node structure.
bool existLeaf(uindex_t idx_x_arg, uindex_t idx_y_arg, uindex_t idx_z_arg) const
idx_x_arg for the existence of leaf node at (idx_x_arg, idx_y_arg, idx_z_arg).
void serializeTreeRecursive(const BranchNode *branch_arg, OctreeKey &key_arg, std::vector< char > *binary_tree_out_arg, typename std::vector< LeafContainerT * > *leaf_container_vector_arg) const
Recursively explore the octree and output binary octree description together with a vector of leaf no...
LeafContainerT * findLeaf(uindex_t idx_x_arg, uindex_t idx_y_arg, uindex_t idx_z_arg) const
Find leaf node at (idx_x_arg, idx_y_arg, idx_z_arg).
void removeLeaf(uindex_t idx_x_arg, uindex_t idx_y_arg, uindex_t idx_z_arg)
Remove leaf node at (idx_x_arg, idx_y_arg, idx_z_arg).
void setMaxVoxelIndex(uindex_t max_voxel_index_arg)
Set the maximum amount of voxels per dimension.
Definition: octree_base.hpp:67
OctreeBase()
Empty constructor.
Definition: octree_base.hpp:51
Abstract octree branch class
Definition: octree_nodes.h:179
bool hasChild(unsigned char child_idx_arg) const
Check if branch is pointing to a particular child node.
Definition: octree_nodes.h:256
OctreeNode * getChildPtr(unsigned char child_idx_arg) const
Get pointer to child.
Definition: octree_nodes.h:234
Octree key class
Definition: octree_key.h:54
void popBranch()
pop child node from octree key
Definition: octree_key.h:122
void pushBranch(unsigned char childIndex)
push a child node to the octree key
Definition: octree_key.h:112
unsigned char getChildIdxWithDepthMask(uindex_t depthMask) const
get child node index using depthMask
Definition: octree_key.h:134
static unsigned char getMaxDepth()
Definition: octree_key.h:146
Abstract octree leaf class
Definition: octree_nodes.h:81
const ContainerT * getContainerPtr() const
Get const pointer to container.
Definition: octree_nodes.h:153
Abstract octree node class
Definition: octree_nodes.h:59
virtual node_type_t getNodeType() const =0
Pure virtual method for retrieving the type of octree node (branch or leaf)
detail::int_type_t< detail::index_type_size, false > uindex_t
Type used for an unsigned index in PCL.
Definition: types.h:120