Point Cloud Library (PCL) 1.15.1-dev
Loading...
Searching...
No Matches
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
47namespace pcl {
48namespace octree {
49//////////////////////////////////////////////////////////////////////////////////////////////
50template <typename LeafContainerT, typename BranchContainerT>
54
55//////////////////////////////////////////////////////////////////////////////////////////////
56template <typename LeafContainerT, typename BranchContainerT>
58{
59 // deallocate tree structure
60 deleteTree();
61 delete (root_node_);
62}
63
64//////////////////////////////////////////////////////////////////////////////////////////////
65template <typename LeafContainerT, typename BranchContainerT>
66void
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//////////////////////////////////////////////////////////////////////////////////////////////
88template <typename LeafContainerT, typename BranchContainerT>
89void
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//////////////////////////////////////////////////////////////////////////////////////////////
116template <typename LeafContainerT, typename BranchContainerT>
117LeafContainerT*
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//////////////////////////////////////////////////////////////////////////////////////////////
130template <typename LeafContainerT, typename BranchContainerT>
131LeafContainerT*
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//////////////////////////////////////////////////////////////////////////////////////////////
144template <typename LeafContainerT, typename BranchContainerT>
145bool
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//////////////////////////////////////////////////////////////////////////////////////////////
158template <typename LeafContainerT, typename BranchContainerT>
159void
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//////////////////////////////////////////////////////////////////////////////////////////////
172template <typename LeafContainerT, typename BranchContainerT>
173void
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//////////////////////////////////////////////////////////////////////////////////////////////
186template <typename LeafContainerT, typename BranchContainerT>
187void
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//////////////////////////////////////////////////////////////////////////////////////////////
202template <typename LeafContainerT, typename BranchContainerT>
203void
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//////////////////////////////////////////////////////////////////////////////////////////////
223template <typename LeafContainerT, typename BranchContainerT>
224void
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//////////////////////////////////////////////////////////////////////////////////////////////
239template <typename LeafContainerT, typename BranchContainerT>
240void
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//////////////////////////////////////////////////////////////////////////////////////////////
263template <typename LeafContainerT, typename BranchContainerT>
264void
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//////////////////////////////////////////////////////////////////////////////////////////////
294template <typename LeafContainerT, typename BranchContainerT>
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 }
350 return (depth_mask_arg >> 1);
351}
352
353//////////////////////////////////////////////////////////////////////////////////////////////
354template <typename LeafContainerT, typename BranchContainerT>
355void
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);
385 result_arg = child_leaf->getContainerPtr();
386 break;
387 }
388 }
389}
390
391//////////////////////////////////////////////////////////////////////////////////////////////
392template <typename LeafContainerT, typename BranchContainerT>
393bool
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 }
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//////////////////////////////////////////////////////////////////////////////////////////////
444template <typename LeafContainerT, typename BranchContainerT>
445void
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);
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//////////////////////////////////////////////////////////////////////////////////////////////
501template <typename LeafContainerT, typename BranchContainerT>
502void
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.
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.
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.
OctreeBase()
Empty constructor.
Abstract octree branch class
bool hasChild(unsigned char child_idx_arg) const
Check if branch is pointing to a particular child node.
OctreeNode * getChildPtr(unsigned char child_idx_arg) const
Get pointer to child.
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
Abstract octree node class
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