Point Cloud Library (PCL)  1.6.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
octree_iterator.hpp
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2010-2011, Willow Garage, Inc.
6  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  * * Neither the name of Willow Garage, Inc. nor the names of its
20  * contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  * $Id: octree_iterator.hpp 6119 2012-07-03 18:50:04Z aichim $
37  */
38 
39 #ifndef OCTREE_ITERATOR_HPP_
40 #define OCTREE_ITERATOR_HPP_
41 
42 #include <vector>
43 #include <assert.h>
44 
45 #include <pcl/common/common.h>
46 
47 namespace pcl
48 {
49  namespace octree
50  {
52  template<typename DataT, typename OctreeT>
54  OctreeT& octree_arg) :
55  OctreeIteratorBase<DataT, OctreeT> (octree_arg), currentChildIdx_ (0), stack_ ()
56  {
57  // allocate stack
58  stack_.reserve (this->octree_.getTreeDepth ());
59 
60  // initialize iterator
61  reset ();
62  }
63 
65  template<typename DataT, typename OctreeT>
67  {
68  }
69 
71  template<typename DataT, typename OctreeT>
73  {
75 
76  // empty stack
77  stack_.clear ();
78  }
79 
81  template<typename DataT, typename OctreeT>
83  {
84  if (!this->currentNode_)
85  return;
86 
87  // make sure, we are not at the root node
88  if (stack_.size () > 0)
89  {
90  // pop stack
91  std::pair<OctreeNode*, unsigned char>& stackEntry =
92  stack_.back ();
93  stack_.pop_back ();
94 
95  // assign parent node and child index
96  this->currentNode_ = stackEntry.first;
97  currentChildIdx_ = stackEntry.second;
98 
99  // update octree key
100  this->currentOctreeKey_.x = (this->currentOctreeKey_.x >> 1);
101  this->currentOctreeKey_.y = (this->currentOctreeKey_.y >> 1);
102  this->currentOctreeKey_.z = (this->currentOctreeKey_.z >> 1);
103 
104  // update octree depth
105  this->currentOctreeDepth_--;
106  }
107  else
108  // we are at root node level - finish
109  this->currentNode_ = NULL;
110  }
111 
113  template<typename DataT, typename OctreeT>
116  {
117  if (this->currentNode_)
118  {
119 
120  bool bTreeUp = false;
121  OctreeNode* itNode = 0;
122 
123  if (this->currentNode_->getNodeType () == BRANCH_NODE)
124  {
125  // current node is a branch node
126  BranchNode* currentBranch =
127  static_cast<BranchNode*> (this->currentNode_);
128 
129  if (currentChildIdx_ < 8)
130  {
131  itNode = this->octree_.getBranchChildPtr (*currentBranch,
132  currentChildIdx_);
133 
134  while ( (currentChildIdx_ < 7) && ! (itNode))
135  {
136 
137  // find next existing child node
138  currentChildIdx_++;
139  itNode = this->octree_.getBranchChildPtr (*currentBranch,
140  currentChildIdx_);
141  }
142 
143  if (!itNode)
144  {
145  // all childs traversed -> back to parent node
146  bTreeUp = true;
147  }
148  }
149  else
150  {
151  bTreeUp = true;
152  }
153 
154  }
155  else
156  {
157  // at leaf node level, we need to return to parent node
158  bTreeUp = true;
159  }
160 
161  if (bTreeUp)
162  {
163  // return to parent node
164 
165  if (stack_.size () > 0)
166  {
167  // pop the stack
168  std::pair<OctreeNode*, unsigned char>& stackEntry = stack_.back ();
169  stack_.pop_back ();
170 
171  // assign parent node and child index
172  this->currentNode_ = stackEntry.first;
173  currentChildIdx_ = stackEntry.second;
174 
175  // update octree key
176  this->currentOctreeKey_.x = (this->currentOctreeKey_.x >> 1);
177  this->currentOctreeKey_.y = (this->currentOctreeKey_.y >> 1);
178  this->currentOctreeKey_.z = (this->currentOctreeKey_.z >> 1);
179 
180  // update octree depth
181  this->currentOctreeDepth_--;
182  }
183  else
184  {
185  // root level -> finish
186  this->currentNode_ = NULL;
187  }
188 
189  }
190  else
191  {
192  // traverse child node
193 
194  // new stack entry
195  std::pair<OctreeNode*, unsigned char> newStackEntry;
196 
197  // assign current node and child index to stack entry
198  newStackEntry.first = this->currentNode_;
199  newStackEntry.second = static_cast<unsigned char> (currentChildIdx_
200  + 1);
201 
202  // push stack entry to stack
203  stack_.push_back (newStackEntry);
204 
205  // update octree key
206  this->currentOctreeKey_.x = (this->currentOctreeKey_.x << 1)
207  | (!! (currentChildIdx_ & (1 << 2)));
208  this->currentOctreeKey_.y = (this->currentOctreeKey_.y << 1)
209  | (!! (currentChildIdx_ & (1 << 1)));
210  this->currentOctreeKey_.z = (this->currentOctreeKey_.z << 1)
211  | (!! (currentChildIdx_ & (1 << 0)));
212 
213  // update octree depth
214  this->currentOctreeDepth_++;
215 
216  // traverse to child node
217  currentChildIdx_ = 0;
218  this->currentNode_ = itNode;
219  }
220  }
221 
222  return (*this);
223  }
224 
226  template<typename DataT, typename OctreeT>
228  OctreeT& octree_arg) :
229  OctreeIteratorBase<DataT, OctreeT> (octree_arg), FIFO_ ()
230  {
232 
233  // initialize iterator
234  reset ();
235  }
236 
238  template<typename DataT, typename OctreeT>
240  {
241  }
242 
244  template<typename DataT, typename OctreeT>
246  const OctreeNode* node)
247  {
248  unsigned char i;
249 
250  if (node && (node->getNodeType () == BRANCH_NODE))
251  {
252 
253  for (i = 0; i < 8; i++)
254  {
255  // current node is a branch node
256  BranchNode* currentBranch =
257  static_cast<BranchNode*> (this->currentNode_);
258 
259  OctreeNode* itNode =
260  static_cast<OctreeNode*> (this->octree_.getBranchChildPtr (
261  *currentBranch, i));
262 
263  // if node exist, push it to FIFO
264  if (itNode)
265  {
266  OctreeKey newKey;
267 
268  // generate octree key
269  newKey.x = (this->currentOctreeKey_.x << 1) | (!! (i & (1 << 2)));
270  newKey.y = (this->currentOctreeKey_.y << 1) | (!! (i & (1 << 1)));
271  newKey.z = (this->currentOctreeKey_.z << 1) | (!! (i & (1 << 0)));
272 
273  FIFOElement newListElement;
274  newListElement.node = itNode;
275  newListElement.key = newKey;
276  newListElement.depth = this->currentOctreeDepth_ + 1;
277 
278  FIFO_.push_back (newListElement);
279  }
280  }
281  }
282  }
283 
285  template<typename DataT, typename OctreeT>
287  {
289 
290  // init FIFO
291  FIFO_.clear ();
292  }
293 
295  template<typename DataT, typename OctreeT>
298  {
299  if (this->currentNode_)
300  {
301 
302  // add childs of current node to FIFO
303  addChildNodesToFIFO (this->currentNode_);
304 
305  if (FIFO_.size () > 0)
306  {
307  FIFOElement FIFOElement;
308 
309  // get FIFO front element
310  FIFOElement = FIFO_.front ();
311  FIFO_.pop_front ();
312 
313  // update iterator variables
314  this->currentNode_ = FIFOElement.node;
315  this->currentOctreeKey_ = FIFOElement.key;
316  this->currentOctreeDepth_ = FIFOElement.depth;
317  }
318  else
319  {
320  // last node reached
321  this->currentNode_ = NULL;
322  }
323  }
324 
325  return (*this);
326  }
327  }
328 }
329 
330 #endif