Point Cloud Library (PCL)  1.15.1-dev
octree2buf_base.h
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 <array>
48 #include <vector>
49 
50 namespace pcl {
51 namespace octree {
52 
53 template <typename ContainerT>
55 
56 public:
57  /** \brief Empty constructor. */
59 
60  /** \brief Copy constructor. */
62  {
63  *this = source;
64  }
65 
66  /** \brief Copy operator. */
67  inline BufferedBranchNode&
68  operator=(const BufferedBranchNode& source_arg)
69  {
70  child_node_array_ = {};
71  for (unsigned char b = 0; b < 2; ++b) {
72  for (unsigned char i = 0; i < 8; ++i) {
73  if (source_arg.child_node_array_[b][i]) {
74  child_node_array_[b][i] = source_arg.child_node_array_[b][i]->deepCopy();
75  }
76  }
77  }
78  return *this;
79  }
80 
81  /** \brief Empty constructor. */
82  ~BufferedBranchNode() override = default;
83 
84  /** \brief Method to perform a deep copy of the octree */
86  deepCopy() const override
87  {
88  return new BufferedBranchNode(*this);
89  }
90 
91  /** \brief Get child pointer in current branch node
92  * \param buffer_arg: buffer selector, must be less than 2
93  * \param index_arg: index of child in node, must be less than 8
94  * \return pointer to child node
95  */
96  inline OctreeNode*
97  getChildPtr(unsigned char buffer_arg, unsigned char index_arg) const
98  {
99  assert((buffer_arg < 2) && (index_arg < 8));
100  return child_node_array_[buffer_arg][index_arg];
101  }
102 
103  /** \brief Set child pointer in current branch node
104  * \param buffer_arg: buffer selector, must be less than 2
105  * \param index_arg: index of child in node, must be less than 8
106  * \param newNode_arg: pointer to new child node
107  */
108  inline void
109  setChildPtr(unsigned char buffer_arg,
110  unsigned char index_arg,
111  OctreeNode* newNode_arg)
112  {
113  assert((buffer_arg < 2) && (index_arg < 8));
114  child_node_array_[buffer_arg][index_arg] = newNode_arg;
115  }
116 
117  /** \brief Check if branch is pointing to a particular child node
118  * \param buffer_arg: buffer selector, must be less than 2
119  * \param index_arg: index of child in node, must be less than 8
120  * \return "true" if pointer to child node exists; "false" otherwise
121  */
122  inline bool
123  hasChild(unsigned char buffer_arg, unsigned char index_arg) const
124  {
125  assert((buffer_arg < 2) && (index_arg < 8));
126  return (child_node_array_[buffer_arg][index_arg] != nullptr);
127  }
128 
129  /** \brief Get the type of octree node. Returns LEAVE_NODE type */
131  getNodeType() const override
132  {
133  return BRANCH_NODE;
134  }
135 
136  /** \brief Reset branch node container for every branch buffer. */
137  inline void
139  {
140  child_node_array_ = {};
141  }
142 
143  /** \brief Get const pointer to container */
144  const ContainerT*
145  operator->() const
146  {
147  return &container_;
148  }
149 
150  /** \brief Get pointer to container */
151  ContainerT*
153  {
154  return &container_;
155  }
156 
157  /** \brief Get const reference to container */
158  const ContainerT&
159  operator*() const
160  {
161  return container_;
162  }
163 
164  /** \brief Get reference to container */
165  ContainerT&
167  {
168  return container_;
169  }
170 
171  /** \brief Get const reference to container */
172  const ContainerT&
173  getContainer() const
174  {
175  return container_;
176  }
177 
178  /** \brief Get reference to container */
179  ContainerT&
181  {
182  return container_;
183  }
184 
185  /** \brief Get const pointer to container */
186  const ContainerT*
188  {
189  return &container_;
190  }
191 
192  /** \brief Get pointer to container */
193  ContainerT*
195  {
196  return &container_;
197  }
198 
199 protected:
200  ContainerT container_;
201 
202  template <typename T, std::size_t ROW, std::size_t COL>
203  using OctreeMatrix = std::array<std::array<T, COL>, ROW>;
204 
206 };
207 
208 /** \brief @b Octree double buffer class
209  *
210  * This octree implementation keeps two separate octree structures in memory
211  * which allows for differentially comparison of the octree structures (change
212  * detection, differential encoding).
213  * \note The tree depth defines the maximum amount of octree voxels / leaf nodes (should
214  * be initially defined).
215  * \note All leaf nodes are addressed by integer indices.
216  * \note The tree depth equates to the bit length of the voxel indices.
217  * \ingroup octree
218  * \author Julius Kammerl (julius@kammerl.de)
219  */
220 template <typename LeafContainerT = index_t,
221  typename BranchContainerT = OctreeContainerEmpty>
223 
224 public:
226 
227  // iterators are friends
228  friend class OctreeIteratorBase<OctreeT>;
229  friend class OctreeDepthFirstIterator<OctreeT>;
230  friend class OctreeBreadthFirstIterator<OctreeT>;
233 
236 
237  using BranchContainer = BranchContainerT;
238  using LeafContainer = LeafContainerT;
239 
240  // Octree default iterators
243  Iterator
244  begin(uindex_t max_depth_arg = 0)
245  {
246  return Iterator(this, max_depth_arg);
247  };
248  const Iterator
249  end()
250  {
251  return Iterator();
252  };
253 
254  // Octree leaf node iterators
255  // The previous deprecated names
256  // LeafNodeIterator and ConstLeafNodeIterator are deprecated.
257  // Please use LeafNodeDepthFirstIterator and ConstLeafNodeDepthFirstIterator instead.
260 
261  // The currently valid names
266  leaf_depth_begin(uindex_t max_depth_arg = 0)
267  {
268  return LeafNodeDepthFirstIterator(this, max_depth_arg);
269  };
270 
273  {
275  };
276 
277  // Octree depth-first iterators
281  depth_begin(uindex_t maxDepth_arg = 0)
282  {
283  return DepthFirstIterator(this, maxDepth_arg);
284  };
285  const DepthFirstIterator
287  {
288  return DepthFirstIterator();
289  };
290 
291  // Octree breadth-first iterators
295  breadth_begin(uindex_t max_depth_arg = 0)
296  {
297  return BreadthFirstIterator(this, max_depth_arg);
298  };
301  {
302  return BreadthFirstIterator();
303  };
304 
305  // Octree leaf node iterators
309 
311  leaf_breadth_begin(uindex_t max_depth_arg = 0u)
312  {
313  return LeafNodeBreadthIterator(this,
314  max_depth_arg ? max_depth_arg : this->octree_depth_);
315  };
316 
319  {
320  return LeafNodeBreadthIterator(this, 0, nullptr);
321  };
322 
323  /** \brief Empty constructor. */
324  Octree2BufBase();
325 
326  /** \brief Empty deconstructor. */
327  virtual ~Octree2BufBase();
328 
329  /** \brief Copy constructor. */
331  : leaf_count_(source.leaf_count_)
332  , branch_count_(source.branch_count_)
333  , root_node_(new (BranchNode)(*(source.root_node_)))
334  , depth_mask_(source.depth_mask_)
335  , max_key_(source.max_key_)
338  , octree_depth_(source.octree_depth_)
340  {}
341 
342  /** \brief Copy constructor. */
343  inline Octree2BufBase&
344  operator=(const Octree2BufBase& source)
345  {
346  if (this == &source)
347  return *this;
348  leaf_count_ = source.leaf_count_;
349  branch_count_ = source.branch_count_;
350  root_node_ = new (BranchNode)(*(source.root_node_));
351  depth_mask_ = source.depth_mask_;
352  max_key_ = source.max_key_;
355  octree_depth_ = source.octree_depth_;
357  return *this;
358  }
359 
360  /** \brief Set the maximum amount of voxels per dimension.
361  * \param max_voxel_index_arg: maximum amount of voxels per dimension
362  */
363  void
364  setMaxVoxelIndex(uindex_t max_voxel_index_arg);
365 
366  /** \brief Set the maximum depth of the octree.
367  * \param depth_arg: maximum depth of octree
368  */
369  void
370  setTreeDepth(uindex_t depth_arg);
371 
372  /** \brief Get the maximum depth of the octree.
373  * \return depth_arg: maximum depth of octree
374  */
375  inline uindex_t
376  getTreeDepth() const
377  {
378  return this->octree_depth_;
379  }
380 
381  /** \brief Create new leaf node at (idx_x_arg, idx_y_arg, idx_z_arg).
382  * \note If leaf node already exist, this method returns the existing node
383  * \param idx_x_arg: index of leaf node in the X axis.
384  * \param idx_y_arg: index of leaf node in the Y axis.
385  * \param idx_z_arg: index of leaf node in the Z axis.
386  * \return pointer to new leaf node container.
387  */
388  LeafContainerT*
389  createLeaf(uindex_t idx_x_arg, uindex_t idx_y_arg, uindex_t idx_z_arg);
390 
391  /** \brief Find leaf node at (idx_x_arg, idx_y_arg, idx_z_arg).
392  * \note If leaf node already exist, this method returns the existing node
393  * \param idx_x_arg: index of leaf node in the X axis.
394  * \param idx_y_arg: index of leaf node in the Y axis.
395  * \param idx_z_arg: index of leaf node in the Z axis.
396  * \return pointer to leaf node container if found, null pointer otherwise.
397  */
398  LeafContainerT*
399  findLeaf(uindex_t idx_x_arg, uindex_t idx_y_arg, uindex_t idx_z_arg);
400 
401  /** \brief Check for the existence of leaf node at (idx_x_arg, idx_y_arg, idx_z_arg).
402  * \param idx_x_arg: index of leaf node in the X axis.
403  * \param idx_y_arg: index of leaf node in the Y axis.
404  * \param idx_z_arg: index of leaf node in the Z axis.
405  * \return "true" if leaf node search is successful, otherwise it returns "false".
406  */
407  bool
408  existLeaf(uindex_t idx_x_arg, uindex_t idx_y_arg, uindex_t idx_z_arg) const;
409 
410  /** \brief Remove leaf node at (idx_x_arg, idx_y_arg, idx_z_arg).
411  * \param idx_x_arg: index of leaf node in the X axis.
412  * \param idx_y_arg: index of leaf node in the Y axis.
413  * \param idx_z_arg: index of leaf node in the Z axis.
414  */
415  void
416  removeLeaf(uindex_t idx_x_arg, uindex_t idx_y_arg, uindex_t idx_z_arg);
417 
418  /** \brief Return the amount of existing leafs in the octree.
419  * \return amount of registered leaf nodes.
420  */
421  inline std::size_t
422  getLeafCount() const
423  {
424  return (leaf_count_);
425  }
426 
427  /** \brief Return the amount of existing branches in the octree.
428  * \return amount of branch nodes.
429  */
430  inline std::size_t
432  {
433  return (branch_count_);
434  }
435 
436  /** \brief Delete the octree structure and its leaf nodes.
437  */
438  void
439  deleteTree();
440 
441  /** \brief Delete octree structure of previous buffer. */
442  inline void
444  {
446  }
447 
448  /** \brief Delete the octree structure in the current buffer. */
449  inline void
451  {
454  leaf_count_ = 0;
455  }
456 
457  /** \brief Switch buffers and reset current octree structure. */
458  void
459  switchBuffers();
460 
461  /** \brief Serialize octree into a binary output vector describing its branch node
462  * structure.
463  * \param binary_tree_out_arg: reference to output vector for writing binary
464  * tree structure.
465  * \param do_XOR_encoding_arg: select if binary tree structure should be generated
466  * based on current octree (false) of based on a XOR comparison between current and
467  * previous octree
468  **/
469  void
470  serializeTree(std::vector<char>& binary_tree_out_arg,
471  bool do_XOR_encoding_arg = false);
472 
473  /** \brief Serialize octree into a binary output vector describing its branch node
474  * structure and and push all DataT elements stored in the octree to a vector.
475  * \param binary_tree_out_arg: reference to output vector for writing binary tree
476  * structure.
477  * \param leaf_container_vector_arg: pointer to all LeafContainerT objects in the
478  * octree
479  * \param do_XOR_encoding_arg: select if binary tree structure should be
480  * generated based on current octree (false) of based on a XOR comparison between
481  * current and previous octree
482  **/
483  void
484  serializeTree(std::vector<char>& binary_tree_out_arg,
485  std::vector<LeafContainerT*>& leaf_container_vector_arg,
486  bool do_XOR_encoding_arg = false);
487 
488  /** \brief Outputs a vector of all DataT elements that are stored within the octree
489  * leaf nodes.
490  * \param leaf_container_vector_arg: vector of pointers to all LeafContainerT objects
491  * in the octree
492  */
493  void
494  serializeLeafs(std::vector<LeafContainerT*>& leaf_container_vector_arg);
495 
496  /** \brief Outputs a vector of all DataT elements from leaf nodes, that do not exist
497  * in the previous octree buffer.
498  * \param leaf_container_vector_arg: vector of pointers to all LeafContainerT objects
499  * in the octree
500  */
501  void
502  serializeNewLeafs(std::vector<LeafContainerT*>& leaf_container_vector_arg);
503 
504  /** \brief Deserialize a binary octree description vector and create a corresponding
505  * octree structure. Leaf nodes are initialized with getDataTByKey(..).
506  * \param binary_tree_in_arg: reference to input vector for reading binary tree
507  * structure.
508  * \param do_XOR_decoding_arg: select if binary tree structure is based on current
509  * octree (false) of based on a XOR comparison between current and previous octree
510  */
511  void
512  deserializeTree(std::vector<char>& binary_tree_in_arg,
513  bool do_XOR_decoding_arg = false);
514 
515  /** \brief Deserialize a binary octree description and create a corresponding octree
516  * structure. Leaf nodes are initialized with DataT elements from the dataVector.
517  * \param binary_tree_in_arg: reference to inpvectoream for reading binary tree
518  * structure.
519  * \param leaf_container_vector_arg: vector of pointers to all LeafContainerT objects
520  * in the octree
521  * \param do_XOR_decoding_arg: select if binary tree structure is based on current
522  * octree (false) of based on a XOR comparison between current and previous octree
523  */
524  void
525  deserializeTree(std::vector<char>& binary_tree_in_arg,
526  std::vector<LeafContainerT*>& leaf_container_vector_arg,
527  bool do_XOR_decoding_arg = false);
528 
529 protected:
530  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
531  // Protected octree methods based on octree keys
532  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
533 
534  /** \brief Retrieve root node */
535  OctreeNode*
536  getRootNode() const
537  {
538  return (this->root_node_);
539  }
540 
541  /** \brief Find leaf node
542  * \param key_arg: octree key addressing a leaf node.
543  * \return pointer to leaf container. If leaf node is not found, this pointer returns
544  * 0.
545  */
546  inline LeafContainerT*
547  findLeaf(const OctreeKey& key_arg) const
548  {
549  LeafContainerT* result = nullptr;
550  findLeafRecursive(key_arg, depth_mask_, root_node_, result);
551  return result;
552  }
553 
554  /** \brief Create a leaf node.
555  * \note If the leaf node at the given octree node does not exist, it will be created
556  * and added to the tree.
557  * \param key_arg: octree key addressing a leaf node.
558  * \return pointer to an existing or created leaf container.
559  */
560  inline LeafContainerT*
561  createLeaf(const OctreeKey& key_arg)
562  {
563  LeafNode* leaf_node;
564  BranchNode* leaf_node_parent;
565 
567  key_arg, depth_mask_, root_node_, leaf_node, leaf_node_parent, false);
568 
569  LeafContainerT* ret = leaf_node->getContainerPtr();
570 
571  return ret;
572  }
573 
574  /** \brief Check if leaf doesn't exist in the octree
575  * \param key_arg: octree key addressing a leaf node.
576  * \return "true" if leaf node is found; "false" otherwise
577  */
578  inline bool
579  existLeaf(const OctreeKey& key_arg) const
580  {
581  return (findLeaf(key_arg) != nullptr);
582  }
583 
584  /** \brief Remove leaf node from octree
585  * \param key_arg: octree key addressing a leaf node.
586  */
587  inline void
588  removeLeaf(const OctreeKey& key_arg)
589  {
590  if (key_arg <= max_key_) {
592 
593  // we changed the octree structure -> dirty
594  tree_dirty_flag_ = true;
595  }
596  }
597 
598  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
599  // Branch node accessor inline functions
600  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
601 
602  /** \brief Check if branch is pointing to a particular child node
603  * \param branch_arg: reference to octree branch class
604  * \param child_idx_arg: index to child node
605  * \return "true" if pointer to child node exists; "false" otherwise
606  */
607  inline bool
608  branchHasChild(const BranchNode& branch_arg, unsigned char child_idx_arg) const
609  {
610  // test occupancyByte for child existence
611  return (branch_arg.getChildPtr(buffer_selector_, child_idx_arg) != nullptr);
612  }
613 
614  /** \brief Retrieve a child node pointer for child node at child_idx.
615  * \param branch_arg: reference to octree branch class
616  * \param child_idx_arg: index to child node
617  * \return pointer to octree child node class
618  */
619  inline OctreeNode*
620  getBranchChildPtr(const BranchNode& branch_arg, unsigned char child_idx_arg) const
621  {
622  return branch_arg.getChildPtr(buffer_selector_, child_idx_arg);
623  }
624 
625  /** \brief Assign new child node to branch
626  * \param branch_arg: reference to octree branch class
627  * \param child_idx_arg: index to child node
628  * \param new_child_arg: pointer to new child node
629  */
630  inline void
632  unsigned char child_idx_arg,
633  OctreeNode* new_child_arg)
634  {
635  branch_arg.setChildPtr(buffer_selector_, child_idx_arg, new_child_arg);
636  }
637 
638  /** \brief Generate bit pattern reflecting the existence of child node pointers for
639  * current buffer
640  * \param branch_arg: reference to octree branch class
641  * \return a single byte with 8 bits of child node information
642  */
643  inline char
644  getBranchBitPattern(const BranchNode& branch_arg) const
645  {
646  char node_bits;
647 
648  // create bit pattern
649  node_bits = 0;
650  for (unsigned char i = 0; i < 8; i++) {
651  const OctreeNode* child = branch_arg.getChildPtr(buffer_selector_, i);
652  node_bits |= static_cast<char>((!!child) << i);
653  }
654 
655  return (node_bits);
656  }
657 
658  /** \brief Generate bit pattern reflecting the existence of child node pointers in
659  * specific buffer
660  * \param branch_arg: reference to octree branch class
661  * \param bufferSelector_arg: buffer selector
662  * \return a single byte with 8 bits of child node information
663  */
664  inline char
665  getBranchBitPattern(const BranchNode& branch_arg,
666  unsigned char bufferSelector_arg) const
667  {
668  char node_bits;
669 
670  // create bit pattern
671  node_bits = 0;
672  for (unsigned char i = 0; i < 8; i++) {
673  const OctreeNode* child = branch_arg.getChildPtr(bufferSelector_arg, i);
674  node_bits |= static_cast<char>((!!child) << i);
675  }
676 
677  return (node_bits);
678  }
679 
680  /** \brief Generate XOR bit pattern reflecting differences between the two octree
681  * buffers
682  * \param branch_arg: reference to octree branch class
683  * \return a single byte with 8 bits of child node XOR difference information
684  */
685  inline char
686  getBranchXORBitPattern(const BranchNode& branch_arg) const
687  {
688  char node_bits[2];
689 
690  // create bit pattern for both buffers
691  node_bits[0] = node_bits[1] = 0;
692 
693  for (unsigned char i = 0; i < 8; i++) {
694  const OctreeNode* childA = branch_arg.getChildPtr(0, i);
695  const OctreeNode* childB = branch_arg.getChildPtr(1, i);
696 
697  node_bits[0] |= static_cast<char>((!!childA) << i);
698  node_bits[1] |= static_cast<char>((!!childB) << i);
699  }
700 
701  return node_bits[0] ^ node_bits[1];
702  }
703 
704  /** \brief Test if branch changed between previous and current buffer
705  * \param branch_arg: reference to octree branch class
706  * \return "true", if child node information differs between current and previous
707  * octree buffer
708  */
709  inline bool
710  hasBranchChanges(const BranchNode& branch_arg) const
711  {
712  return (getBranchXORBitPattern(branch_arg) > 0);
713  }
714 
715  /** \brief Delete child node and all its subchilds from octree in specific buffer
716  * \param branch_arg: reference to octree branch class
717  * \param buffer_selector_arg: buffer selector
718  * \param child_idx_arg: index to child node
719  */
720  inline void
722  unsigned char buffer_selector_arg,
723  unsigned char child_idx_arg)
724  {
725  if (branch_arg.hasChild(buffer_selector_arg, child_idx_arg)) {
726  OctreeNode* branchChild =
727  branch_arg.getChildPtr(buffer_selector_arg, child_idx_arg);
728 
729  switch (branchChild->getNodeType()) {
730  case BRANCH_NODE: {
731  // free child branch recursively
732  deleteBranch(*static_cast<BranchNode*>(branchChild));
733 
734  // delete unused branch
735  delete (branchChild);
736  break;
737  }
738 
739  case LEAF_NODE: {
740  // push unused leaf to branch pool
741  delete (branchChild);
742  break;
743  }
744  default:
745  break;
746  }
747 
748  // set branch child pointer to 0
749  branch_arg.setChildPtr(buffer_selector_arg, child_idx_arg, nullptr);
750  }
751  }
752 
753  /** \brief Delete child node and all its subchilds from octree in current buffer
754  * \param branch_arg: reference to octree branch class
755  * \param child_idx_arg: index to child node
756  */
757  inline void
758  deleteBranchChild(BranchNode& branch_arg, unsigned char child_idx_arg)
759  {
760  deleteBranchChild(branch_arg, buffer_selector_, child_idx_arg);
761  }
762 
763  /** \brief Delete branch and all its subchilds from octree (both buffers)
764  * \param branch_arg: reference to octree branch class
765  */
766  inline void
768  {
769  // delete all branch node children
770  for (char i = 0; i < 8; i++) {
771 
772  if (branch_arg.getChildPtr(0, i) == branch_arg.getChildPtr(1, i)) {
773  // reference was copied - there is only one child instance to be deleted
774  deleteBranchChild(branch_arg, 0, i);
775 
776  // remove pointers from both buffers
777  branch_arg.setChildPtr(0, i, nullptr);
778  branch_arg.setChildPtr(1, i, nullptr);
779  }
780  else {
781  deleteBranchChild(branch_arg, 0, i);
782  deleteBranchChild(branch_arg, 1, i);
783  }
784  }
785  }
786 
787  /** \brief Fetch and add a new branch child to a branch class in current buffer
788  * \param branch_arg: reference to octree branch class
789  * \param child_idx_arg: index to child node
790  * \return pointer of new branch child to this reference
791  */
792  inline BranchNode*
793  createBranchChild(BranchNode& branch_arg, unsigned char child_idx_arg)
794  {
795  auto* new_branch_child = new BranchNode();
796 
797  branch_arg.setChildPtr(
798  buffer_selector_, child_idx_arg, static_cast<OctreeNode*>(new_branch_child));
799 
800  return new_branch_child;
801  }
802 
803  /** \brief Fetch and add a new leaf child to a branch class
804  * \param branch_arg: reference to octree branch class
805  * \param child_idx_arg: index to child node
806  * \return pointer of new leaf child to this reference
807  */
808  inline LeafNode*
809  createLeafChild(BranchNode& branch_arg, unsigned char child_idx_arg)
810  {
811  auto* new_leaf_child = new LeafNode();
812 
813  branch_arg.setChildPtr(buffer_selector_, child_idx_arg, new_leaf_child);
814 
815  return new_leaf_child;
816  }
817 
818  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
819  // Recursive octree methods
820  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
821 
822  /** \brief Create a leaf node at octree key. If leaf node does already exist, it is
823  * returned.
824  * \param key_arg: reference to an octree key
825  * \param depth_mask_arg: depth mask used for octree key analysis and for branch depth
826  * indicator
827  * \param branch_arg: current branch node
828  * \param return_leaf_arg: return pointer to leaf container
829  * \param parent_of_leaf_arg: return pointer to parent of leaf node
830  * \param branch_reset_arg: Reset pointer array of current branch
831  * \return depth mask at which leaf node was created/found
832  **/
833  uindex_t
834  createLeafRecursive(const OctreeKey& key_arg,
835  uindex_t depth_mask_arg,
836  BranchNode* branch_arg,
837  LeafNode*& return_leaf_arg,
838  BranchNode*& parent_of_leaf_arg,
839  bool branch_reset_arg = false);
840 
841  /** \brief Recursively search for a given leaf node and return a pointer.
842  * \note If leaf node does not exist, a 0 pointer is returned.
843  * \param key_arg: reference to an octree key
844  * \param depth_mask_arg: depth mask used for octree key analysis and for branch
845  * depth indicator
846  * \param branch_arg: current branch node
847  * \param result_arg: pointer to leaf container class
848  **/
849  void
850  findLeafRecursive(const OctreeKey& key_arg,
851  uindex_t depth_mask_arg,
852  BranchNode* branch_arg,
853  LeafContainerT*& result_arg) const;
854 
855  /** \brief Recursively search and delete leaf node
856  * \param key_arg: reference to an octree key
857  * \param depth_mask_arg: depth mask used for octree key analysis and branch depth
858  * indicator
859  * \param branch_arg: current branch node
860  * \return "true" if branch does not contain any childs; "false" otherwise. This
861  * indicates if current branch can be deleted.
862  **/
863  bool
864  deleteLeafRecursive(const OctreeKey& key_arg,
865  uindex_t depth_mask_arg,
866  BranchNode* branch_arg);
867 
868  /** \brief Recursively explore the octree and output binary octree description
869  * together with a vector of leaf node DataT content.
870  * \param branch_arg: current branch node
871  * \param key_arg: reference to an octree key
872  * \param binary_tree_out_arg: binary output vector
873  * \param leaf_container_vector_arg: vector to return pointers to all leaf container
874  * in the tree.
875  * \param do_XOR_encoding_arg: select if binary tree structure should be generated
876  * based on current octree (false) of based on a XOR comparison between current and
877  * previous octree
878  * \param new_leafs_filter_arg: execute callback only for leaf nodes that did not
879  * exist in preceding buffer
880  **/
881  void
883  BranchNode* branch_arg,
884  OctreeKey& key_arg,
885  std::vector<char>* binary_tree_out_arg,
886  typename std::vector<LeafContainerT*>* leaf_container_vector_arg,
887  bool do_XOR_encoding_arg = false,
888  bool new_leafs_filter_arg = false);
889 
890  /** \brief Rebuild an octree based on binary XOR octree description and DataT objects
891  * for leaf node initialization.
892  * \param branch_arg: current branch node
893  * \param depth_mask_arg: depth mask used for octree key analysis and branch depth
894  * indicator
895  * \param key_arg: reference to an octree key
896  * \param binary_tree_in_it_arg iterator of binary input data
897  * \param binary_tree_in_it_end_arg
898  * \param leaf_container_vector_it_arg: iterator pointing to leaf container pointers
899  * to be added to a leaf node
900  * \param leaf_container_vector_it_end_arg: iterator pointing to leaf container
901  * pointers pointing to last object in input container.
902  * \param branch_reset_arg: Reset pointer array of current branch
903  * \param do_XOR_decoding_arg: select if binary tree structure is based on current
904  * octree (false) of based on a XOR comparison between current and previous octree
905  **/
906  void
908  BranchNode* branch_arg,
909  uindex_t depth_mask_arg,
910  OctreeKey& key_arg,
911  typename std::vector<char>::const_iterator& binary_tree_in_it_arg,
912  typename std::vector<char>::const_iterator& binary_tree_in_it_end_arg,
913  typename std::vector<LeafContainerT*>::const_iterator*
914  leaf_container_vector_it_arg,
915  typename std::vector<LeafContainerT*>::const_iterator*
916  leaf_container_vector_it_end_arg,
917  bool branch_reset_arg = false,
918  bool do_XOR_decoding_arg = false);
919 
920  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
921  // Serialization callbacks
922  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
923 
924  /** \brief Callback executed for every leaf node data during serialization
925  **/
926  virtual void
927  serializeTreeCallback(LeafContainerT&, const OctreeKey&)
928  {}
929 
930  /** \brief Callback executed for every leaf node data during deserialization
931  **/
932  virtual void
933  deserializeTreeCallback(LeafContainerT&, const OctreeKey&)
934  {}
935 
936  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
937  // Helpers
938  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
939 
940  /** \brief Recursively explore the octree and remove unused branch and leaf nodes
941  * \param branch_arg: current branch node
942  **/
943  void
944  treeCleanUpRecursive(BranchNode* branch_arg);
945 
946  /** \brief Test if octree is able to dynamically change its depth. This is required
947  * for adaptive bounding box adjustment.
948  * \return "false" - not resizeable due to XOR serialization
949  **/
950  inline bool
952  {
953  return (false);
954  }
955 
956  /** \brief Prints binary representation of a byte - used for debugging
957  * \param data_arg - byte to be printed to stdout
958  **/
959  inline void
960  printBinary(char data_arg)
961  {
962  unsigned char mask = 1; // Bit mask
963 
964  // Extract the bits
965  for (int i = 0; i < 8; i++) {
966  // Mask each bit in the byte and print it
967  std::cout << ((data_arg & (mask << i)) ? "1" : "0");
968  }
969  std::cout << std::endl;
970  }
971 
972  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
973  // Globals
974  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
975 
976  /** \brief Amount of leaf nodes **/
977  std::size_t leaf_count_{0};
978 
979  /** \brief Amount of branch nodes **/
980  std::size_t branch_count_{1};
981 
982  /** \brief Pointer to root branch node of octree **/
984 
985  /** \brief Depth mask based on octree depth **/
987 
988  /** \brief key range */
990 
991  /** \brief Currently active octree buffer **/
992  unsigned char buffer_selector_{0};
993 
994  /** \brief flags indicating if unused branches and leafs might exist in previous
995  * buffer **/
996  bool tree_dirty_flag_{false};
997 
998  /** \brief Octree depth */
1000 
1001  /** \brief Enable dynamic_depth
1002  * \note Note that this parameter is ignored in octree2buf! */
1004 };
1005 } // namespace octree
1006 } // namespace pcl
1007 
1008 #ifdef PCL_NO_PRECOMPILE
1009 #include <pcl/octree/impl/octree2buf_base.hpp>
1010 #endif
OctreeMatrix< OctreeNode *, 2, 8 > child_node_array_
BufferedBranchNode(const BufferedBranchNode &source)
Copy constructor.
ContainerT & getContainer()
Get reference to container.
const ContainerT * operator->() const
Get const pointer to container.
BufferedBranchNode * deepCopy() const override
Method to perform a deep copy of the octree.
const ContainerT & getContainer() const
Get const reference to container.
ContainerT * getContainerPtr()
Get pointer to container.
const ContainerT * getContainerPtr() const
Get const pointer to container.
std::array< std::array< T, COL >, ROW > OctreeMatrix
node_type_t getNodeType() const override
Get the type of octree node.
BufferedBranchNode & operator=(const BufferedBranchNode &source_arg)
Copy operator.
~BufferedBranchNode() override=default
Empty constructor.
ContainerT * operator->()
Get pointer to container.
const ContainerT & operator*() const
Get const reference to container.
void reset()
Reset branch node container for every branch buffer.
ContainerT & operator*()
Get reference to container.
void setChildPtr(unsigned char buffer_arg, unsigned char index_arg, OctreeNode *newNode_arg)
Set child pointer in current branch node.
BufferedBranchNode()
Empty constructor.
OctreeNode * getChildPtr(unsigned char buffer_arg, unsigned char index_arg) const
Get child pointer in current branch node.
bool hasChild(unsigned char buffer_arg, unsigned char index_arg) const
Check if branch is pointing to a particular child node.
Octree double buffer class
LeafNode * createLeafChild(BranchNode &branch_arg, unsigned char child_idx_arg)
Fetch and add a new leaf child to a branch class.
OctreeLeafNodeDepthFirstIterator< OctreeT > LeafNodeDepthFirstIterator
void deleteBranch(BranchNode &branch_arg)
Delete branch and all its subchilds from octree (both buffers)
bool hasBranchChanges(const BranchNode &branch_arg) const
Test if branch changed between previous and current buffer.
OctreeNode * getRootNode() const
Retrieve root node.
LeafContainerT * findLeaf(const OctreeKey &key_arg) const
Find leaf node.
void serializeLeafs(std::vector< LeafContainerT * > &leaf_container_vector_arg)
Outputs a vector of all DataT elements that are stored within the octree leaf nodes.
OctreeDepthFirstIterator< OctreeT > DepthFirstIterator
char getBranchBitPattern(const BranchNode &branch_arg) const
Generate bit pattern reflecting the existence of child node pointers for current buffer.
Octree2BufBase(const Octree2BufBase &source)
Copy constructor.
OctreeKey max_key_
key range
LeafNodeBreadthIterator leaf_breadth_begin(uindex_t max_depth_arg=0u)
Iterator begin(uindex_t max_depth_arg=0)
void switchBuffers()
Switch buffers and reset current octree structure.
OctreeLeafNode< LeafContainerT > LeafNode
const LeafNodeBreadthIterator leaf_breadth_end()
std::size_t getLeafCount() const
Return the amount of existing leafs in the octree.
BranchNode * createBranchChild(BranchNode &branch_arg, unsigned char child_idx_arg)
Fetch and add a new branch child to a branch class in current buffer.
uindex_t createLeafRecursive(const OctreeKey &key_arg, uindex_t depth_mask_arg, BranchNode *branch_arg, LeafNode *&return_leaf_arg, BranchNode *&parent_of_leaf_arg, bool branch_reset_arg=false)
Create a leaf node at octree key.
std::size_t leaf_count_
Amount of leaf nodes
uindex_t octree_depth_
Octree depth.
void serializeTree(std::vector< char > &binary_tree_out_arg, bool do_XOR_encoding_arg=false)
Serialize octree into a binary output vector describing its branch node structure.
void treeCleanUpRecursive(BranchNode *branch_arg)
Recursively explore the octree and remove unused branch and leaf nodes.
char getBranchBitPattern(const BranchNode &branch_arg, unsigned char bufferSelector_arg) const
Generate bit pattern reflecting the existence of child node pointers in specific buffer.
bool octreeCanResize()
Test if octree is able to dynamically change its depth.
void deleteTree()
Delete the octree structure and its leaf nodes.
void removeLeaf(const OctreeKey &key_arg)
Remove leaf node from octree.
unsigned char buffer_selector_
Currently active octree buffer
void deleteCurrentBuffer()
Delete the octree structure in the current buffer.
void deleteBranchChild(BranchNode &branch_arg, unsigned char child_idx_arg)
Delete child node and all its subchilds from octree in current buffer.
char getBranchXORBitPattern(const BranchNode &branch_arg) const
Generate XOR bit pattern reflecting differences between the two octree buffers.
virtual void deserializeTreeCallback(LeafContainerT &, const OctreeKey &)
Callback executed for every leaf node data during deserialization.
void serializeTreeRecursive(BranchNode *branch_arg, OctreeKey &key_arg, std::vector< char > *binary_tree_out_arg, typename std::vector< LeafContainerT * > *leaf_container_vector_arg, bool do_XOR_encoding_arg=false, bool new_leafs_filter_arg=false)
Recursively explore the octree and output binary octree description together with a vector of leaf no...
bool branchHasChild(const BranchNode &branch_arg, unsigned char child_idx_arg) const
Check if branch is pointing to a particular child node.
bool existLeaf(uindex_t idx_x_arg, uindex_t idx_y_arg, uindex_t idx_z_arg) const
Check for the existence of leaf node at (idx_x_arg, idx_y_arg, idx_z_arg).
void deserializeTree(std::vector< char > &binary_tree_in_arg, bool do_XOR_decoding_arg=false)
Deserialize a binary octree description vector and create a corresponding octree structure.
void deletePreviousBuffer()
Delete octree structure of previous buffer.
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).
void deleteBranchChild(BranchNode &branch_arg, unsigned char buffer_selector_arg, unsigned char child_idx_arg)
Delete child node and all its subchilds from octree in specific buffer.
OctreeLeafNodeBreadthFirstIterator< OctreeT > LeafNodeBreadthIterator
BranchNode * root_node_
Pointer to root branch node of octree
void setTreeDepth(uindex_t depth_arg)
Set the maximum depth of the octree.
BreadthFirstIterator breadth_begin(uindex_t max_depth_arg=0)
BranchContainerT BranchContainer
void printBinary(char data_arg)
Prints binary representation of a byte - used for debugging.
bool tree_dirty_flag_
flags indicating if unused branches and leafs might exist in previous buffer
void setBranchChildPtr(BranchNode &branch_arg, unsigned char child_idx_arg, OctreeNode *new_child_arg)
Assign new child node to branch.
std::size_t branch_count_
Amount of branch nodes
void setMaxVoxelIndex(uindex_t max_voxel_index_arg)
Set the maximum amount of voxels per dimension.
bool dynamic_depth_enabled_
Enable dynamic_depth.
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).
const DepthFirstIterator depth_end()
bool deleteLeafRecursive(const OctreeKey &key_arg, uindex_t depth_mask_arg, BranchNode *branch_arg)
Recursively search and delete leaf node.
const BreadthFirstIterator breadth_end()
OctreeNode * getBranchChildPtr(const BranchNode &branch_arg, unsigned char child_idx_arg) const
Retrieve a child node pointer for child node at child_idx.
DepthFirstIterator depth_begin(uindex_t maxDepth_arg=0)
LeafContainerT * findLeaf(uindex_t idx_x_arg, uindex_t idx_y_arg, uindex_t idx_z_arg)
Find leaf node at (idx_x_arg, idx_y_arg, idx_z_arg).
LeafContainerT * createLeaf(const OctreeKey &key_arg)
Create a leaf node.
bool existLeaf(const OctreeKey &key_arg) const
Check if leaf doesn't exist in the octree.
uindex_t depth_mask_
Depth mask based on octree depth
uindex_t getTreeDepth() const
Get the maximum depth of the octree.
std::size_t getBranchCount() const
Return the amount of existing branches in the octree.
void serializeNewLeafs(std::vector< LeafContainerT * > &leaf_container_vector_arg)
Outputs a vector of all DataT elements from leaf nodes, that do not exist in the previous octree buff...
OctreeBreadthFirstIterator< OctreeT > BreadthFirstIterator
virtual void serializeTreeCallback(LeafContainerT &, const OctreeKey &)
Callback executed for every leaf node data during serialization.
BufferedBranchNode< BranchContainerT > BranchNode
LeafNodeDepthFirstIterator leaf_depth_begin(uindex_t max_depth_arg=0)
Octree2BufBase()
Empty constructor.
Octree2BufBase & operator=(const Octree2BufBase &source)
Copy constructor.
const LeafNodeDepthFirstIterator leaf_depth_end()
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.
virtual ~Octree2BufBase()
Empty deconstructor.
void deserializeTreeRecursive(BranchNode *branch_arg, uindex_t depth_mask_arg, OctreeKey &key_arg, typename std::vector< char >::const_iterator &binary_tree_in_it_arg, typename std::vector< char >::const_iterator &binary_tree_in_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, bool branch_reset_arg=false, bool do_XOR_decoding_arg=false)
Rebuild an octree based on binary XOR octree description and DataT objects for leaf node initializati...
OctreeDepthFirstIterator< OctreeT > Iterator
Abstract octree iterator class
Octree key class
Definition: octree_key.h:54
Octree leaf node iterator class.
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
detail::int_type_t< detail::index_type_size, detail::index_type_signed > index_t
Type used for an index in PCL.
Definition: types.h:112
Defines all the PCL and non-PCL macros used.