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 #pragma once 40 41 #include <pcl/octree/octree_container.h> 42 #include <pcl/octree/octree_iterator.h> 43 #include <pcl/octree/octree_key.h> 44 #include <pcl/octree/octree_nodes.h> 45 #include <pcl/pcl_macros.h> 46 47 #include <vector> 48 49 namespace pcl { 50 namespace octree { 51 52 /** \brief Octree class 53 * \note The tree depth defines the maximum amount of octree voxels / leaf nodes (should 54 * be initially defined). 55 * \note All leaf nodes are addressed by integer indices. 56 * \note The tree depth equates to the bit length of the voxel indices. 57 * \ingroup octree 58 * \author Julius Kammerl (julius@kammerl.de) 59 */ 60 template <typename LeafContainerT = index_t, 61 typename BranchContainerT = OctreeContainerEmpty> 62 class OctreeBase { 63 public: 64 using OctreeT = OctreeBase<LeafContainerT, BranchContainerT>; 65 66 using BranchNode = OctreeBranchNode<BranchContainerT>; 67 using LeafNode = OctreeLeafNode<LeafContainerT>; 68 69 using BranchContainer = BranchContainerT; 70 using LeafContainer = LeafContainerT; 71 72 protected: 73 /////////////////////////////////////////////////////////////////////// 74 // Members 75 /////////////////////////////////////////////////////////////////////// 76 77 /** \brief Amount of leaf nodes **/ 78 std::size_t leaf_count_; 79 80 /** \brief Amount of branch nodes **/ 81 std::size_t branch_count_; 82 83 /** \brief Pointer to root branch node of octree **/ 84 BranchNode* root_node_; 85 86 /** \brief Depth mask based on octree depth **/ 87 uindex_t depth_mask_; 88 89 /** \brief Octree depth */ 90 uindex_t octree_depth_; 91 92 /** \brief Enable dynamic_depth **/ 93 bool dynamic_depth_enabled_; 94 95 /** \brief key range */ 96 OctreeKey max_key_; 97 98 public: 99 // iterators are friends 100 friend class OctreeIteratorBase<OctreeT>; 101 friend class OctreeDepthFirstIterator<OctreeT>; 102 friend class OctreeBreadthFirstIterator<OctreeT>; 103 friend class OctreeFixedDepthIterator<OctreeT>; 104 friend class OctreeLeafNodeDepthFirstIterator<OctreeT>; 105 friend class OctreeLeafNodeBreadthFirstIterator<OctreeT>; 106 107 // Octree default iterators 108 using Iterator = OctreeDepthFirstIterator<OctreeT>; 109 using ConstIterator = const OctreeDepthFirstIterator<OctreeT>; 110 111 Iterator 112 begin(uindex_t max_depth_arg = 0u) 113 { 114 return Iterator(this, max_depth_arg ? max_depth_arg : this->octree_depth_); 115 }; 116 117 const Iterator end()118 end() 119 { 120 return Iterator(this, 0, nullptr); 121 }; 122 123 // Octree leaf node iterators 124 // The previous deprecated names 125 // LeafNodeIterator and ConstLeafNodeIterator are deprecated. 126 // Please use LeafNodeDepthFirstIterator and ConstLeafNodeDepthFirstIterator instead. 127 using LeafNodeIterator = OctreeLeafNodeDepthFirstIterator<OctreeT>; 128 using ConstLeafNodeIterator = const OctreeLeafNodeDepthFirstIterator<OctreeT>; 129 130 // The currently valide names 131 using LeafNodeDepthFirstIterator = OctreeLeafNodeDepthFirstIterator<OctreeT>; 132 using ConstLeafNodeDepthFirstIterator = 133 const OctreeLeafNodeDepthFirstIterator<OctreeT>; 134 135 LeafNodeDepthFirstIterator 136 leaf_depth_begin(uindex_t max_depth_arg = 0u) 137 { 138 return LeafNodeDepthFirstIterator( 139 this, max_depth_arg ? max_depth_arg : this->octree_depth_); 140 }; 141 142 const LeafNodeDepthFirstIterator leaf_depth_end()143 leaf_depth_end() 144 { 145 return LeafNodeDepthFirstIterator(this, 0, nullptr); 146 }; 147 148 // Octree depth-first iterators 149 using DepthFirstIterator = OctreeDepthFirstIterator<OctreeT>; 150 using ConstDepthFirstIterator = const OctreeDepthFirstIterator<OctreeT>; 151 152 DepthFirstIterator 153 depth_begin(uindex_t max_depth_arg = 0u) 154 { 155 return DepthFirstIterator(this, 156 max_depth_arg ? max_depth_arg : this->octree_depth_); 157 }; 158 159 const DepthFirstIterator depth_end()160 depth_end() 161 { 162 return DepthFirstIterator(this, 0, nullptr); 163 }; 164 165 // Octree breadth-first iterators 166 using BreadthFirstIterator = OctreeBreadthFirstIterator<OctreeT>; 167 using ConstBreadthFirstIterator = const OctreeBreadthFirstIterator<OctreeT>; 168 169 BreadthFirstIterator 170 breadth_begin(uindex_t max_depth_arg = 0u) 171 { 172 return BreadthFirstIterator(this, 173 max_depth_arg ? max_depth_arg : this->octree_depth_); 174 }; 175 176 const BreadthFirstIterator breadth_end()177 breadth_end() 178 { 179 return BreadthFirstIterator(this, 0, nullptr); 180 }; 181 182 // Octree breadth iterators at a given depth 183 using FixedDepthIterator = OctreeFixedDepthIterator<OctreeT>; 184 using ConstFixedDepthIterator = const OctreeFixedDepthIterator<OctreeT>; 185 186 FixedDepthIterator 187 fixed_depth_begin(uindex_t fixed_depth_arg = 0u) 188 { 189 return FixedDepthIterator(this, fixed_depth_arg); 190 }; 191 192 const FixedDepthIterator fixed_depth_end()193 fixed_depth_end() 194 { 195 return FixedDepthIterator(this, 0, nullptr); 196 }; 197 198 // Octree leaf node iterators 199 using LeafNodeBreadthFirstIterator = OctreeLeafNodeBreadthFirstIterator<OctreeT>; 200 using ConstLeafNodeBreadthFirstIterator = 201 const OctreeLeafNodeBreadthFirstIterator<OctreeT>; 202 203 LeafNodeBreadthFirstIterator 204 leaf_breadth_begin(uindex_t max_depth_arg = 0u) 205 { 206 return LeafNodeBreadthFirstIterator( 207 this, max_depth_arg ? max_depth_arg : this->octree_depth_); 208 }; 209 210 const LeafNodeBreadthFirstIterator leaf_breadth_end()211 leaf_breadth_end() 212 { 213 return LeafNodeBreadthFirstIterator(this, 0, nullptr); 214 }; 215 216 /** \brief Empty constructor. */ 217 OctreeBase(); 218 219 /** \brief Empty deconstructor. */ 220 virtual ~OctreeBase(); 221 222 /** \brief Copy constructor. */ OctreeBase(const OctreeBase & source)223 OctreeBase(const OctreeBase& source) 224 : leaf_count_(source.leaf_count_) 225 , branch_count_(source.branch_count_) 226 , root_node_(new (BranchNode)(*(source.root_node_))) 227 , depth_mask_(source.depth_mask_) 228 , octree_depth_(source.octree_depth_) 229 , dynamic_depth_enabled_(source.dynamic_depth_enabled_) 230 , max_key_(source.max_key_) 231 {} 232 233 /** \brief Copy operator. */ 234 OctreeBase& 235 operator=(const OctreeBase& source) 236 { 237 leaf_count_ = source.leaf_count_; 238 branch_count_ = source.branch_count_; 239 delete root_node_; 240 241 root_node_ = new (BranchNode)(*(source.root_node_)); 242 depth_mask_ = source.depth_mask_; 243 max_key_ = source.max_key_; 244 octree_depth_ = source.octree_depth_; 245 return (*this); 246 } 247 248 /** \brief Set the maximum amount of voxels per dimension. 249 * \param[in] max_voxel_index_arg maximum amount of voxels per dimension 250 */ 251 void 252 setMaxVoxelIndex(uindex_t max_voxel_index_arg); 253 254 /** \brief Set the maximum depth of the octree. 255 * \param max_depth_arg: maximum depth of octree 256 */ 257 void 258 setTreeDepth(uindex_t max_depth_arg); 259 260 /** \brief Get the maximum depth of the octree. 261 * \return depth_arg: maximum depth of octree 262 */ 263 uindex_t getTreeDepth()264 getTreeDepth() const 265 { 266 return this->octree_depth_; 267 } 268 269 /** \brief Create new leaf node at (idx_x_arg, idx_y_arg, idx_z_arg). 270 * \note If leaf node already exist, this method returns the existing node 271 * \param idx_x_arg: index of leaf node in the X axis. 272 * \param idx_y_arg: index of leaf node in the Y axis. 273 * \param idx_z_arg: index of leaf node in the Z axis. 274 * \return pointer to new leaf node container. 275 */ 276 LeafContainerT* 277 createLeaf(uindex_t idx_x_arg, uindex_t idx_y_arg, uindex_t idx_z_arg); 278 279 /** \brief Find leaf node at (idx_x_arg, idx_y_arg, idx_z_arg). 280 * \note If leaf node already exist, this method returns the existing node 281 * \param idx_x_arg: index of leaf node in the X axis. 282 * \param idx_y_arg: index of leaf node in the Y axis. 283 * \param idx_z_arg: index of leaf node in the Z axis. 284 * \return pointer to leaf node container if found, null pointer otherwise. 285 */ 286 LeafContainerT* 287 findLeaf(uindex_t idx_x_arg, uindex_t idx_y_arg, uindex_t idx_z_arg); 288 289 /** \brief idx_x_arg for the existence of leaf node at (idx_x_arg, idx_y_arg, 290 * idx_z_arg). 291 * \param idx_x_arg: index of leaf node in the X axis. 292 * \param idx_y_arg: index of leaf node in the Y axis. 293 * \param idx_z_arg: index of leaf node in the Z axis. 294 * \return "true" if leaf node search is successful, otherwise it returns "false". 295 */ 296 bool 297 existLeaf(uindex_t idx_x_arg, uindex_t idx_y_arg, uindex_t idx_z_arg) const; 298 299 /** \brief Remove leaf node at (idx_x_arg, idx_y_arg, idx_z_arg). 300 * \param idx_x_arg: index of leaf node in the X axis. 301 * \param idx_y_arg: index of leaf node in the Y axis. 302 * \param idx_z_arg: index of leaf node in the Z axis. 303 */ 304 void 305 removeLeaf(uindex_t idx_x_arg, uindex_t idx_y_arg, uindex_t idx_z_arg); 306 307 /** \brief Return the amount of existing leafs in the octree. 308 * \return amount of registered leaf nodes. 309 */ 310 std::size_t getLeafCount()311 getLeafCount() const 312 { 313 return leaf_count_; 314 } 315 316 /** \brief Return the amount of existing branch nodes in the octree. 317 * \return amount of branch nodes. 318 */ 319 std::size_t getBranchCount()320 getBranchCount() const 321 { 322 return branch_count_; 323 } 324 325 /** \brief Delete the octree structure and its leaf nodes. 326 */ 327 void 328 deleteTree(); 329 330 /** \brief Serialize octree into a binary output vector describing its branch node 331 * structure. 332 * \param binary_tree_out_arg: reference to output vector for writing binary tree 333 * structure. 334 */ 335 void 336 serializeTree(std::vector<char>& binary_tree_out_arg); 337 338 /** \brief Serialize octree into a binary output vector describing its branch node 339 * structure and push all LeafContainerT elements stored in the octree to a vector. 340 * \param binary_tree_out_arg: reference to output vector for writing binary tree 341 * structure. 342 * \param leaf_container_vector_arg: pointer to all LeafContainerT objects in the 343 * octree 344 */ 345 void 346 serializeTree(std::vector<char>& binary_tree_out_arg, 347 std::vector<LeafContainerT*>& leaf_container_vector_arg); 348 349 /** \brief Outputs a vector of all LeafContainerT elements that are stored within the 350 * octree leaf nodes. 351 * \param leaf_container_vector_arg: pointers to LeafContainerT vector that receives a 352 * copy of all LeafContainerT objects in the octree. 353 */ 354 void 355 serializeLeafs(std::vector<LeafContainerT*>& leaf_container_vector_arg); 356 357 /** \brief Deserialize a binary octree description vector and create a corresponding 358 * octree structure. Leaf nodes are initialized with getDataTByKey(..). 359 * \param binary_tree_input_arg: reference to input vector for reading binary tree 360 * structure. 361 */ 362 void 363 deserializeTree(std::vector<char>& binary_tree_input_arg); 364 365 /** \brief Deserialize a binary octree description and create a corresponding octree 366 * structure. Leaf nodes are initialized with LeafContainerT elements from the 367 * dataVector. 368 * \param binary_tree_input_arg: reference to input vector for reading binary tree 369 * structure. \param leaf_container_vector_arg: pointer to container vector. 370 */ 371 void 372 deserializeTree(std::vector<char>& binary_tree_input_arg, 373 std::vector<LeafContainerT*>& leaf_container_vector_arg); 374 375 protected: 376 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 377 // Protected octree methods based on octree keys 378 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 379 380 /** \brief Create a leaf node 381 * \param key_arg: octree key addressing a leaf node. 382 * \return pointer to leaf node 383 */ 384 LeafContainerT* createLeaf(const OctreeKey & key_arg)385 createLeaf(const OctreeKey& key_arg) 386 { 387 388 LeafNode* leaf_node = nullptr; 389 BranchNode* leaf_node_parent; 390 391 createLeafRecursive(key_arg, depth_mask_, root_node_, leaf_node, leaf_node_parent); 392 393 LeafContainerT* ret = leaf_node->getContainerPtr(); 394 395 return ret; 396 } 397 398 /** \brief Find leaf node 399 * \param key_arg: octree key addressing a leaf node. 400 * \return pointer to leaf node. If leaf node is not found, this pointer returns 0. 401 */ 402 LeafContainerT* findLeaf(const OctreeKey & key_arg)403 findLeaf(const OctreeKey& key_arg) const 404 { 405 LeafContainerT* result = nullptr; 406 findLeafRecursive(key_arg, depth_mask_, root_node_, result); 407 return result; 408 } 409 410 /** \brief Check for existence of a leaf node in the octree 411 * \param key_arg: octree key addressing a leaf node. 412 * \return "true" if leaf node is found; "false" otherwise 413 */ 414 bool existLeaf(const OctreeKey & key_arg)415 existLeaf(const OctreeKey& key_arg) const 416 { 417 return (findLeaf(key_arg) != nullptr); 418 } 419 420 /** \brief Remove leaf node from octree 421 * \param key_arg: octree key addressing a leaf node. 422 */ 423 void removeLeaf(const OctreeKey & key_arg)424 removeLeaf(const OctreeKey& key_arg) 425 { 426 if (key_arg <= max_key_) 427 deleteLeafRecursive(key_arg, depth_mask_, root_node_); 428 } 429 430 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 431 // Branch node access functions 432 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 433 434 /** \brief Retrieve root node */ 435 OctreeNode* getRootNode()436 getRootNode() const 437 { 438 return this->root_node_; 439 } 440 441 /** \brief Check if branch is pointing to a particular child node 442 * \param branch_arg: reference to octree branch class 443 * \param child_idx_arg: index to child node 444 * \return "true" if pointer to child node exists; "false" otherwise 445 */ 446 bool branchHasChild(const BranchNode & branch_arg,unsigned char child_idx_arg)447 branchHasChild(const BranchNode& branch_arg, unsigned char child_idx_arg) const 448 { 449 // test occupancyByte for child existence 450 return (branch_arg.getChildPtr(child_idx_arg) != nullptr); 451 } 452 453 /** \brief Retrieve a child node pointer for child node at child_idx. 454 * \param branch_arg: reference to octree branch class 455 * \param child_idx_arg: index to child node 456 * \return pointer to octree child node class 457 */ 458 OctreeNode* getBranchChildPtr(const BranchNode & branch_arg,unsigned char child_idx_arg)459 getBranchChildPtr(const BranchNode& branch_arg, unsigned char child_idx_arg) const 460 { 461 return branch_arg.getChildPtr(child_idx_arg); 462 } 463 464 /** \brief Assign new child node to branch 465 * \param branch_arg: reference to octree branch class 466 * \param child_idx_arg: index to child node 467 * \param new_child_arg: pointer to new child node 468 */ 469 void setBranchChildPtr(BranchNode & branch_arg,unsigned char child_idx_arg,OctreeNode * new_child_arg)470 setBranchChildPtr(BranchNode& branch_arg, 471 unsigned char child_idx_arg, 472 OctreeNode* new_child_arg) 473 { 474 branch_arg[child_idx_arg] = new_child_arg; 475 } 476 477 /** \brief Generate bit pattern reflecting the existence of child node pointers 478 * \param branch_arg: reference to octree branch class 479 * \return a single byte with 8 bits of child node information 480 */ 481 char getBranchBitPattern(const BranchNode & branch_arg)482 getBranchBitPattern(const BranchNode& branch_arg) const 483 { 484 char node_bits; 485 486 // create bit pattern 487 node_bits = 0; 488 for (unsigned char i = 0; i < 8; i++) { 489 const OctreeNode* child = branch_arg.getChildPtr(i); 490 node_bits |= static_cast<char>((!!child) << i); 491 } 492 493 return (node_bits); 494 } 495 496 /** \brief Delete child node and all its subchilds from octree 497 * \param branch_arg: reference to octree branch class 498 * \param child_idx_arg: index to child node 499 */ 500 void deleteBranchChild(BranchNode & branch_arg,unsigned char child_idx_arg)501 deleteBranchChild(BranchNode& branch_arg, unsigned char child_idx_arg) 502 { 503 if (branch_arg.hasChild(child_idx_arg)) { 504 OctreeNode* branch_child = branch_arg[child_idx_arg]; 505 506 switch (branch_child->getNodeType()) { 507 case BRANCH_NODE: { 508 // free child branch recursively 509 deleteBranch(*static_cast<BranchNode*>(branch_child)); 510 // delete branch node 511 delete branch_child; 512 } break; 513 514 case LEAF_NODE: { 515 // delete leaf node 516 delete branch_child; 517 break; 518 } 519 default: 520 break; 521 } 522 523 // set branch child pointer to 0 524 branch_arg[child_idx_arg] = nullptr; 525 } 526 } 527 528 /** \brief Delete branch and all its subchilds from octree 529 * \param branch_arg: reference to octree branch class 530 */ 531 void deleteBranch(BranchNode & branch_arg)532 deleteBranch(BranchNode& branch_arg) 533 { 534 // delete all branch node children 535 for (char i = 0; i < 8; i++) 536 deleteBranchChild(branch_arg, i); 537 } 538 539 /** \brief Create and add a new branch child to a branch class 540 * \param branch_arg: reference to octree branch class 541 * \param child_idx_arg: index to child node 542 * \return pointer of new branch child to this reference 543 */ 544 BranchNode* createBranchChild(BranchNode & branch_arg,unsigned char child_idx_arg)545 createBranchChild(BranchNode& branch_arg, unsigned char child_idx_arg) 546 { 547 BranchNode* new_branch_child = new BranchNode(); 548 branch_arg[child_idx_arg] = static_cast<OctreeNode*>(new_branch_child); 549 550 return new_branch_child; 551 } 552 553 /** \brief Create and add a new leaf child to a branch class 554 * \param branch_arg: reference to octree branch class 555 * \param child_idx_arg: index to child node 556 * \return pointer of new leaf child to this reference 557 */ 558 LeafNode* createLeafChild(BranchNode & branch_arg,unsigned char child_idx_arg)559 createLeafChild(BranchNode& branch_arg, unsigned char child_idx_arg) 560 { 561 LeafNode* new_leaf_child = new LeafNode(); 562 branch_arg[child_idx_arg] = static_cast<OctreeNode*>(new_leaf_child); 563 564 return new_leaf_child; 565 } 566 567 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 568 // Recursive octree methods 569 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 570 571 /** \brief Create a leaf node at octree key. If leaf node does already exist, it is 572 * returned. 573 * \param key_arg: reference to an octree key 574 * \param depth_mask_arg: depth mask used for octree key analysis and for branch depth 575 * indicator 576 * \param branch_arg: current branch node 577 * \param return_leaf_arg: return pointer to leaf node 578 * \param parent_of_leaf_arg: return pointer to parent of leaf node 579 * \return depth mask at which leaf node was created 580 **/ 581 uindex_t 582 createLeafRecursive(const OctreeKey& key_arg, 583 uindex_t depth_mask_arg, 584 BranchNode* branch_arg, 585 LeafNode*& return_leaf_arg, 586 BranchNode*& parent_of_leaf_arg); 587 588 /** \brief Recursively search for a given leaf node and return a pointer. 589 * \note If leaf node does not exist, a 0 pointer is returned. 590 * \param key_arg: reference to an octree key 591 * \param depth_mask_arg: depth mask used for octree key analysis and for branch 592 * depth indicator 593 * \param branch_arg: current branch node 594 * \param result_arg: pointer to leaf node class 595 **/ 596 void 597 findLeafRecursive(const OctreeKey& key_arg, 598 uindex_t depth_mask_arg, 599 BranchNode* branch_arg, 600 LeafContainerT*& result_arg) const; 601 602 /** \brief Recursively search and delete leaf node 603 * \param key_arg: reference to an octree key 604 * \param depth_mask_arg: depth mask used for octree key analysis and branch depth 605 * indicator 606 * \param branch_arg: current branch node 607 * \return "true" if branch does not contain any childs; "false" otherwise. This 608 * indicates if current branch can be deleted, too. 609 **/ 610 bool 611 deleteLeafRecursive(const OctreeKey& key_arg, 612 uindex_t depth_mask_arg, 613 BranchNode* branch_arg); 614 615 /** \brief Recursively explore the octree and output binary octree description 616 * together with a vector of leaf node LeafContainerTs. 617 * \param branch_arg: current branch node 618 * \param key_arg: reference to an octree key 619 * \param binary_tree_out_arg: binary output vector 620 * \param leaf_container_vector_arg: writes LeafContainerT pointers to this 621 *LeafContainerT* vector. 622 **/ 623 void 624 serializeTreeRecursive( 625 const BranchNode* branch_arg, 626 OctreeKey& key_arg, 627 std::vector<char>* binary_tree_out_arg, 628 typename std::vector<LeafContainerT*>* leaf_container_vector_arg) const; 629 630 /** \brief Recursive method for deserializing octree structure 631 * \param branch_arg: current branch node 632 * \param depth_mask_arg: depth mask used for octree key analysis and branch depth 633 * indicator 634 * \param key_arg: reference to an octree key 635 * \param binary_tree_input_it_arg: iterator to binary input vector 636 * \param binary_tree_input_it_end_arg: end iterator of binary input vector 637 * \param leaf_container_vector_it_arg: iterator pointing to current LeafContainerT 638 * object to be added to a leaf node 639 * \param leaf_container_vector_it_end_arg: iterator pointing to last object in 640 * LeafContainerT input vector. 641 **/ 642 void 643 deserializeTreeRecursive( 644 BranchNode* branch_arg, 645 uindex_t depth_mask_arg, 646 OctreeKey& key_arg, 647 typename std::vector<char>::const_iterator& binary_tree_input_it_arg, 648 typename std::vector<char>::const_iterator& binary_tree_input_it_end_arg, 649 typename std::vector<LeafContainerT*>::const_iterator* 650 leaf_container_vector_it_arg, 651 typename std::vector<LeafContainerT*>::const_iterator* 652 leaf_container_vector_it_end_arg); 653 654 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 655 // Serialization callbacks 656 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 657 658 /** \brief Callback executed for every leaf node during serialization 659 **/ 660 virtual void serializeTreeCallback(LeafContainerT &,const OctreeKey &)661 serializeTreeCallback(LeafContainerT&, const OctreeKey&) const 662 {} 663 664 /** \brief Callback executed for every leaf node during deserialization 665 **/ 666 virtual void deserializeTreeCallback(LeafContainerT &,const OctreeKey &)667 deserializeTreeCallback(LeafContainerT&, const OctreeKey&) 668 {} 669 670 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 671 // Helpers 672 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 673 674 /** \brief Test if octree is able to dynamically change its depth. This is required 675 *for adaptive bounding box adjustment. 676 * \return "true" 677 **/ 678 bool octreeCanResize()679 octreeCanResize() 680 { 681 return (true); 682 } 683 }; 684 } // namespace octree 685 } // namespace pcl 686 687 #ifdef PCL_NO_PRECOMPILE 688 #include <pcl/octree/impl/octree_base.hpp> 689 #endif 690