octree_iterator.hpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Point Cloud Library (PCL) - www.pointclouds.org
00005  *  Copyright (c) 2010-2011, Willow Garage, Inc.
00006  *
00007  *  All rights reserved.
00008  *
00009  *  Redistribution and use in source and binary forms, with or without
00010  *  modification, are permitted provided that the following conditions
00011  *  are met:
00012  *
00013  *   * Redistributions of source code must retain the above copyright
00014  *     notice, this list of conditions and the following disclaimer.
00015  *   * Redistributions in binary form must reproduce the above
00016  *     copyright notice, this list of conditions and the following
00017  *     disclaimer in the documentation and/or other materials provided
00018  *     with the distribution.
00019  *   * Neither the name of Willow Garage, Inc. nor the names of its
00020  *     contributors may be used to endorse or promote products derived
00021  *     from this software without specific prior written permission.
00022  *
00023  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00026  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00027  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00028  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00029  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00032  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00033  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00034  *  POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  * $Id: octree_iterator.hpp 6119 2012-07-03 18:50:04Z aichim $
00037  */
00038 
00039 #ifndef OCTREE_ITERATOR_HPP_
00040 #define OCTREE_ITERATOR_HPP_
00041 
00042 #include <vector>
00043 #include <assert.h>
00044 
00045 #include <pcl/common/common.h>
00046 
00047 namespace pcl
00048 {
00049   namespace octree
00050   {
00052     template<typename DataT, typename OctreeT>
00053     OctreeDepthFirstIterator<DataT, OctreeT>::OctreeDepthFirstIterator (
00054         OctreeT& octree_arg) :
00055         OctreeIteratorBase<DataT, OctreeT> (octree_arg), currentChildIdx_ (0), stack_ ()
00056     {
00057       // allocate stack
00058       stack_.reserve (this->octree_.getTreeDepth ());
00059 
00060       // initialize iterator
00061       reset ();
00062     }
00063 
00065     template<typename DataT, typename OctreeT>
00066     OctreeDepthFirstIterator<DataT, OctreeT>::~OctreeDepthFirstIterator ()
00067     {
00068     }
00069 
00071     template<typename DataT, typename OctreeT>
00072     void OctreeDepthFirstIterator<DataT, OctreeT>::reset ()
00073     {
00074       OctreeIteratorBase<DataT, OctreeT>::reset ();
00075 
00076       // empty stack
00077       stack_.clear ();
00078     }
00079 
00081     template<typename DataT, typename OctreeT>
00082     void OctreeDepthFirstIterator<DataT, OctreeT>::skipChildVoxels ()
00083     {
00084       if (!this->currentNode_)
00085         return;
00086 
00087       // make sure, we are not at the root node
00088       if (stack_.size () > 0)
00089       {
00090         // pop stack
00091         std::pair<OctreeNode*, unsigned char>& stackEntry =
00092             stack_.back ();
00093         stack_.pop_back ();
00094 
00095         // assign parent node and child index
00096         this->currentNode_ = stackEntry.first;
00097         currentChildIdx_ = stackEntry.second;
00098 
00099         // update octree key
00100         this->currentOctreeKey_.x = (this->currentOctreeKey_.x >> 1);
00101         this->currentOctreeKey_.y = (this->currentOctreeKey_.y >> 1);
00102         this->currentOctreeKey_.z = (this->currentOctreeKey_.z >> 1);
00103 
00104         // update octree depth
00105         this->currentOctreeDepth_--;
00106       }
00107       else
00108         // we are at root node level - finish
00109         this->currentNode_ = NULL;
00110     }
00111 
00113     template<typename DataT, typename OctreeT>
00114     OctreeDepthFirstIterator<DataT, OctreeT>&
00115     OctreeDepthFirstIterator<DataT, OctreeT>::operator++ ()
00116     {
00117       if (this->currentNode_)
00118       {
00119 
00120         bool bTreeUp = false;
00121         OctreeNode* itNode = 0;
00122 
00123         if (this->currentNode_->getNodeType () == BRANCH_NODE)
00124         {
00125           // current node is a branch node
00126           BranchNode* currentBranch =
00127               static_cast<BranchNode*> (this->currentNode_);
00128 
00129           if (currentChildIdx_ < 8)
00130           {
00131             itNode = this->octree_.getBranchChildPtr (*currentBranch,
00132                 currentChildIdx_);
00133 
00134             while ( (currentChildIdx_ < 7) && ! (itNode))
00135             {
00136 
00137               // find next existing child node
00138               currentChildIdx_++;
00139               itNode = this->octree_.getBranchChildPtr (*currentBranch,
00140                   currentChildIdx_);
00141             }
00142 
00143             if (!itNode)
00144             {
00145               // all childs traversed -> back to parent node
00146               bTreeUp = true;
00147             }
00148           }
00149           else
00150           {
00151             bTreeUp = true;
00152           }
00153 
00154         }
00155         else
00156         {
00157           // at leaf node level, we need to return to parent node
00158           bTreeUp = true;
00159         }
00160 
00161         if (bTreeUp)
00162         {
00163           // return to parent node
00164 
00165           if (stack_.size () > 0)
00166           {
00167             // pop the stack
00168             std::pair<OctreeNode*, unsigned char>& stackEntry = stack_.back ();
00169             stack_.pop_back ();
00170 
00171             // assign parent node and child index
00172             this->currentNode_ = stackEntry.first;
00173             currentChildIdx_ = stackEntry.second;
00174 
00175             // update octree key
00176             this->currentOctreeKey_.x = (this->currentOctreeKey_.x >> 1);
00177             this->currentOctreeKey_.y = (this->currentOctreeKey_.y >> 1);
00178             this->currentOctreeKey_.z = (this->currentOctreeKey_.z >> 1);
00179 
00180             // update octree depth
00181             this->currentOctreeDepth_--;
00182           }
00183           else
00184           {
00185             // root level -> finish
00186             this->currentNode_ = NULL;
00187           }
00188 
00189         }
00190         else
00191         {
00192           // traverse child node
00193 
00194           // new stack entry
00195           std::pair<OctreeNode*, unsigned char> newStackEntry;
00196 
00197           // assign current node and child index to stack entry
00198           newStackEntry.first = this->currentNode_;
00199           newStackEntry.second = static_cast<unsigned char> (currentChildIdx_
00200               + 1);
00201 
00202           // push stack entry to stack
00203           stack_.push_back (newStackEntry);
00204 
00205           // update octree key
00206           this->currentOctreeKey_.x = (this->currentOctreeKey_.x << 1)
00207               | (!! (currentChildIdx_ & (1 << 2)));
00208           this->currentOctreeKey_.y = (this->currentOctreeKey_.y << 1)
00209               | (!! (currentChildIdx_ & (1 << 1)));
00210           this->currentOctreeKey_.z = (this->currentOctreeKey_.z << 1)
00211               | (!! (currentChildIdx_ & (1 << 0)));
00212 
00213           // update octree depth
00214           this->currentOctreeDepth_++;
00215 
00216           // traverse to child node
00217           currentChildIdx_ = 0;
00218           this->currentNode_ = itNode;
00219         }
00220       }
00221 
00222       return (*this);
00223     }
00224 
00226     template<typename DataT, typename OctreeT>
00227     OctreeBreadthFirstIterator<DataT, OctreeT>::OctreeBreadthFirstIterator (
00228         OctreeT& octree_arg) :
00229         OctreeIteratorBase<DataT, OctreeT> (octree_arg), FIFO_ ()
00230     {
00231       OctreeIteratorBase<DataT, OctreeT>::reset ();
00232 
00233       // initialize iterator
00234       reset ();
00235     }
00236 
00238     template<typename DataT, typename OctreeT>
00239     OctreeBreadthFirstIterator<DataT, OctreeT>::~OctreeBreadthFirstIterator ()
00240     {
00241     }
00242 
00244     template<typename DataT, typename OctreeT>
00245     void OctreeBreadthFirstIterator<DataT, OctreeT>::addChildNodesToFIFO (
00246         const OctreeNode* node)
00247     {
00248       unsigned char i;
00249 
00250       if (node && (node->getNodeType () == BRANCH_NODE))
00251       {
00252 
00253         for (i = 0; i < 8; i++)
00254         {
00255           // current node is a branch node
00256           BranchNode* currentBranch =
00257               static_cast<BranchNode*> (this->currentNode_);
00258 
00259           OctreeNode* itNode =
00260               static_cast<OctreeNode*> (this->octree_.getBranchChildPtr (
00261                   *currentBranch, i));
00262 
00263           // if node exist, push it to FIFO
00264           if (itNode)
00265           {
00266             OctreeKey newKey;
00267 
00268             // generate octree key
00269             newKey.x = (this->currentOctreeKey_.x << 1) | (!! (i & (1 << 2)));
00270             newKey.y = (this->currentOctreeKey_.y << 1) | (!! (i & (1 << 1)));
00271             newKey.z = (this->currentOctreeKey_.z << 1) | (!! (i & (1 << 0)));
00272 
00273             FIFOElement newListElement;
00274             newListElement.node = itNode;
00275             newListElement.key = newKey;
00276             newListElement.depth = this->currentOctreeDepth_ + 1;
00277 
00278             FIFO_.push_back (newListElement);
00279           }
00280         }
00281       }
00282     }
00283 
00285     template<typename DataT, typename OctreeT>
00286     void OctreeBreadthFirstIterator<DataT, OctreeT>::reset ()
00287     {
00288       OctreeIteratorBase<DataT, OctreeT>::reset ();
00289 
00290       // init FIFO
00291       FIFO_.clear ();
00292     }
00293 
00295     template<typename DataT, typename OctreeT>
00296     OctreeBreadthFirstIterator<DataT, OctreeT>&
00297     OctreeBreadthFirstIterator<DataT, OctreeT>::operator++ ()
00298     {
00299       if (this->currentNode_)
00300       {
00301 
00302         // add childs of current node to FIFO
00303         addChildNodesToFIFO (this->currentNode_);
00304 
00305         if (FIFO_.size () > 0)
00306         {
00307           FIFOElement FIFOElement;
00308 
00309           // get FIFO front element
00310           FIFOElement = FIFO_.front ();
00311           FIFO_.pop_front ();
00312 
00313           // update iterator variables
00314           this->currentNode_ = FIFOElement.node;
00315           this->currentOctreeKey_ = FIFOElement.key;
00316           this->currentOctreeDepth_ = FIFOElement.depth;
00317         }
00318         else
00319         {
00320           // last node reached
00321           this->currentNode_ = NULL;
00322         }
00323       }
00324 
00325       return (*this);
00326     }
00327   }
00328 }
00329 
00330 #endif


pcl
Author(s): Open Perception
autogenerated on Mon Oct 6 2014 03:15:57