Point Cloud Library (PCL) 1.15.1-dev
Loading...
Searching...
No Matches
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
50namespace pcl {
51namespace octree {
52
53template <typename ContainerT>
55
56public:
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 {
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 {
141 }
142
143 /** \brief Get const pointer to container */
144 const ContainerT*
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&
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
199protected:
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 */
220template <typename LeafContainerT = index_t,
221 typename BranchContainerT = OctreeContainerEmpty>
223
224public:
226
227 // iterators are friends
228 friend class OctreeIteratorBase<OctreeT>;
229 friend class OctreeDepthFirstIterator<OctreeT>;
233
236
237 using BranchContainer = BranchContainerT;
238 using LeafContainer = LeafContainerT;
239
240 // Octree default iterators
244 begin(uindex_t max_depth_arg = 0)
245 {
246 return Iterator(this, max_depth_arg);
247 };
248 const Iterator
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 };
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. */
325
326 /** \brief Empty deconstructor. */
327 virtual ~Octree2BufBase();
328
329 /** \brief Copy constructor. */
341
342 /** \brief Copy constructor. */
343 inline Octree2BufBase&
345 {
346 if (this == &source)
347 return *this;
348 leaf_count_ = source.leaf_count_;
350 root_node_ = new (BranchNode)(*(source.root_node_));
351 depth_mask_ = source.depth_mask_;
352 max_key_ = source.max_key_;
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
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
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
447
448 /** \brief Delete the octree structure in the current buffer. */
449 inline void
456
457 /** \brief Switch buffers and reset current octree structure. */
458 void
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
529protected:
530 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
531 // Protected octree methods based on octree keys
532 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
533
534 /** \brief Retrieve root node */
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
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 **/
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
BufferedBranchNode * deepCopy() const override
Method to perform a deep copy of the octree.
OctreeMatrix< OctreeNode *, 2, 8 > child_node_array_
BufferedBranchNode & operator=(const BufferedBranchNode &source_arg)
Copy operator.
BufferedBranchNode(const BufferedBranchNode &source)
Copy constructor.
ContainerT & operator*()
Get reference to container.
const ContainerT & getContainer() const
Get const reference to container.
std::array< std::array< T, COL >, ROW > OctreeMatrix
ContainerT * getContainerPtr()
Get pointer to container.
ContainerT & getContainer()
Get reference to container.
node_type_t getNodeType() const override
Get the type of octree node.
OctreeNode * getChildPtr(unsigned char buffer_arg, unsigned char index_arg) const
Get child pointer in current branch node.
const ContainerT & operator*() const
Get const reference to container.
const ContainerT * operator->() const
Get const pointer to container.
~BufferedBranchNode() override=default
Empty constructor.
const ContainerT * getContainerPtr() const
Get const pointer to container.
void reset()
Reset branch node container for every branch buffer.
void setChildPtr(unsigned char buffer_arg, unsigned char index_arg, OctreeNode *newNode_arg)
Set child pointer in current branch node.
BufferedBranchNode()
Empty constructor.
ContainerT * operator->()
Get pointer to container.
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
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.
void serializeLeafs(std::vector< LeafContainerT * > &leaf_container_vector_arg)
Outputs a vector of all DataT elements that are stored within the octree leaf nodes.
BranchNode * createBranchChild(BranchNode &branch_arg, unsigned char child_idx_arg)
Fetch and add a new branch child to a branch class in current buffer.
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.
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.
LeafContainerT * findLeaf(const OctreeKey &key_arg) const
Find 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, 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.
LeafNode * createLeafChild(BranchNode &branch_arg, unsigned char child_idx_arg)
Fetch and add a new leaf child to a branch class.
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
OctreeNode * getBranchChildPtr(const BranchNode &branch_arg, unsigned char child_idx_arg) const
Retrieve a child node pointer for child node at child_idx.
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)
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
Octree2BufBase< LeafContainerT, BranchContainerT > OctreeT
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()
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).
bool existLeaf(const OctreeKey &key_arg) const
Check if leaf doesn't exist in the octree.
Octree2BufBase & operator=(const Octree2BufBase &source)
Copy constructor.
uindex_t depth_mask_
Depth mask based on octree depth
OctreeNode * getRootNode() const
Retrieve root node.
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.
LeafContainerT * createLeaf(const OctreeKey &key_arg)
Create a leaf node.
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
Abstract octree leaf class
const ContainerT * getContainerPtr() const
Get const pointer to container.
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
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.