Point Cloud Library (PCL)  1.5.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
octree_pointcloud.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_pointcloud.hpp 4702 2012-02-23 09:39:33Z gedikli $
00037  */
00038 
00039 #ifndef OCTREE_POINTCLOUD_HPP_
00040 #define OCTREE_POINTCLOUD_HPP_
00041 
00042 #include <vector>
00043 #include <assert.h>
00044 
00045 #include "pcl/common/common.h"
00046 
00048 template<typename PointT, typename LeafT, typename OctreeT>
00049 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::OctreePointCloud (const double resolution) :
00050     OctreeT (), epsilon_ (0), resolution_ (resolution), minX_ (0.0f), maxX_ (resolution), minY_ (0.0f),
00051     maxY_ (resolution), minZ_ (0.0f), maxZ_ (resolution), maxKeys_ (1), boundingBoxDefined_ (false)
00052 {
00053   assert ( resolution > 0.0f );
00054   input_ = PointCloudConstPtr ();
00055 }
00056 
00058 template<typename PointT, typename LeafT, typename OctreeT>
00059 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::~OctreePointCloud ()
00060 {
00061 }
00062 
00064 template<typename PointT, typename LeafT, typename OctreeT> void
00065 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::addPointsFromInputCloud ()
00066 {
00067   size_t i;
00068 
00069   assert (this->leafCount_==0);
00070   if (indices_)
00071   {
00072     for (std::vector<int>::const_iterator current = indices_->begin (); current != indices_->end (); ++current)
00073     {
00074       if (isFinite (input_->points[*current]))
00075       {
00076         assert( (*current>=0) && (*current<(int)input_->points.size ()));
00077 
00078         // add points to octree
00079         this->addPointIdx (*current);
00080       }
00081     }
00082   }
00083   else
00084   {
00085     for (i = 0; i < input_->points.size (); i++)
00086     {
00087       if (isFinite (input_->points[i]))
00088       {
00089         // add points to octree
00090         this->addPointIdx ((unsigned int)i);
00091       }
00092     }
00093   }
00094 }
00095 
00097 template<typename PointT, typename LeafT, typename OctreeT> void
00098 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::addPointFromCloud (const int pointIdx_arg, IndicesPtr indices_arg)
00099 {
00100   this->addPointIdx (pointIdx_arg);
00101   if (indices_arg)
00102     indices_arg->push_back (pointIdx_arg);
00103 }
00104 
00106 template<typename PointT, typename LeafT, typename OctreeT> void
00107 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::addPointToCloud (const PointT& point_arg, PointCloudPtr cloud_arg)
00108 {
00109   assert (cloud_arg==input_);
00110 
00111   cloud_arg->points.push_back (point_arg);
00112 
00113   this->addPointIdx ((const int)cloud_arg->points.size () - 1);
00114 }
00115 
00117 template<typename PointT, typename LeafT, typename OctreeT> void
00118 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::addPointToCloud (const PointT& point_arg, PointCloudPtr cloud_arg,
00119                                                            IndicesPtr indices_arg)
00120 {
00121   assert (cloud_arg==input_);
00122   assert (indices_arg==indices_);
00123 
00124   cloud_arg->points.push_back (point_arg);
00125 
00126   this->addPointFromCloud ((const int)cloud_arg->points.size () - 1, indices_arg);
00127 }
00128 
00130 template<typename PointT, typename LeafT, typename OctreeT> bool
00131 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::isVoxelOccupiedAtPoint (const PointT& point_arg) const
00132 {
00133   OctreeKey key;
00134 
00135   // generate key for point
00136   this->genOctreeKeyforPoint (point_arg, key);
00137 
00138   // search for key in octree
00139   return (this->existLeaf (key));
00140 }
00141 
00143 template<typename PointT, typename LeafT, typename OctreeT> bool
00144 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::isVoxelOccupiedAtPoint (const int& pointIdx_arg) const
00145 {
00146   // retrieve point from input cloud
00147   const PointT& point = this->input_->points[pointIdx_arg];
00148 
00149   // search for voxel at point in octree
00150   return (this->isVoxelOccupiedAtPoint (point));
00151 }
00152 
00154 template<typename PointT, typename LeafT, typename OctreeT> bool
00155 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::isVoxelOccupiedAtPoint (
00156     const double pointX_arg, const double pointY_arg, const double pointZ_arg) const
00157 {
00158   OctreeKey key;
00159 
00160   // generate key for point
00161   this->genOctreeKeyforPoint (pointX_arg, pointY_arg, pointZ_arg, key);
00162 
00163   return (this->existLeaf (key));
00164 }
00165 
00167 template<typename PointT, typename LeafT, typename OctreeT> void
00168 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::deleteVoxelAtPoint (const PointT& point_arg)
00169 {
00170   OctreeKey key;
00171 
00172   // generate key for point
00173   this->genOctreeKeyforPoint (point_arg, key);
00174 
00175   this->removeLeaf (key);
00176 }
00177 
00179 template<typename PointT, typename LeafT, typename OctreeT> void
00180 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::deleteVoxelAtPoint (const int& pointIdx_arg)
00181 {
00182   // retrieve point from input cloud
00183   const PointT& point = this->input_->points[pointIdx_arg];
00184 
00185   // delete leaf at point
00186   this->deleteVoxelAtPoint (point);
00187 }
00188 
00190 template<typename PointT, typename LeafT, typename OctreeT> int
00191 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::getOccupiedVoxelCenters (
00192     std::vector<PointT, Eigen::aligned_allocator<PointT> > &voxelCenterList_arg) const
00193 {
00194   OctreeKey key;
00195   key.x = key.y = key.z = 0;
00196 
00197   voxelCenterList_arg.clear ();
00198 
00199   return getOccupiedVoxelCentersRecursive (this->rootNode_, key, voxelCenterList_arg);
00200 
00201 }
00202 
00204 template<typename PointT, typename LeafT, typename OctreeT> int
00205 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::getApproxIntersectedVoxelCentersBySegment (
00206     const Eigen::Vector3f& origin,
00207     const Eigen::Vector3f& end,
00208     AlignedPointTVector &voxel_center_list,
00209     float precision)
00210 {
00211   Eigen::Vector3f direction = end - origin;
00212   float norm = direction.norm ();
00213   direction.normalize ();
00214 
00215   const float step_size = (const float)resolution_ * precision;
00216   // Ensure we get at least one step for the first voxel.
00217   const int nsteps = std::max (1, (int) (norm / step_size));
00218 
00219   OctreeKey prev_key;
00220   prev_key.x = prev_key.y = prev_key.z = -1;
00221 
00222   // Walk along the line segment with small steps.
00223   for (int i = 0; i < nsteps; ++i)
00224   {
00225     Eigen::Vector3f p = origin + (direction * step_size * (const float)i);
00226 
00227     PointT octree_p;
00228     octree_p.x = p.x ();
00229     octree_p.y = p.y ();
00230     octree_p.z = p.z ();
00231 
00232     OctreeKey key;
00233     this->genOctreeKeyforPoint (octree_p, key);
00234 
00235     // Not a new key, still the same voxel.
00236     if (key == prev_key)
00237       continue;
00238 
00239     prev_key = key;
00240 
00241     PointT center;
00242     genLeafNodeCenterFromOctreeKey (key, center);
00243     voxel_center_list.push_back (center);
00244   }
00245 
00246   OctreeKey end_key;
00247   PointT end_p;
00248   end_p.x = end.x ();
00249   end_p.y = end.y ();
00250   end_p.z = end.z ();
00251   this->genOctreeKeyforPoint (end_p, end_key);
00252   if (!(end_key == prev_key))
00253   {
00254     PointT center;
00255     genLeafNodeCenterFromOctreeKey (end_key, center);
00256     voxel_center_list.push_back (center);
00257   }
00258 
00259   return ((int)voxel_center_list.size ());
00260 }
00261 
00263 template<typename PointT, typename LeafT, typename OctreeT> void
00264 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::defineBoundingBox ()
00265 {
00266 
00267   double minX, minY, minZ, maxX, maxY, maxZ;
00268 
00269   PointT min_pt;
00270   PointT max_pt;
00271 
00272   // bounding box cannot be changed once the octree contains elements
00273   assert (this->leafCount_ == 0);
00274 
00275   pcl::getMinMax3D (*input_, min_pt, max_pt);
00276 
00277   float minValue = std::numeric_limits<float>::epsilon () * 512.0f;
00278 
00279   minX = min_pt.x;
00280   minY = min_pt.y;
00281   minZ = min_pt.z;
00282 
00283   maxX = max_pt.x + minValue;
00284   maxY = max_pt.y + minValue;
00285   maxZ = max_pt.z + minValue;
00286 
00287   // generate bit masks for octree
00288   defineBoundingBox (minX, minY, minZ, maxX, maxY, maxZ);
00289 }
00290 
00292 template<typename PointT, typename LeafT, typename OctreeT> void
00293 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::defineBoundingBox (const double minX_arg,
00294                                                                           const double minY_arg,
00295                                                                           const double minZ_arg,
00296                                                                           const double maxX_arg,
00297     const double maxY_arg, const double maxZ_arg)
00298 {
00299   // bounding box cannot be changed once the octree contains elements
00300   assert (this->leafCount_ == 0);
00301 
00302   assert (maxX_arg >= minX_arg);
00303   assert (maxY_arg >= minY_arg);
00304   assert (maxZ_arg >= minZ_arg);
00305 
00306   minX_ = minX_arg;
00307   maxX_ = maxX_arg;
00308 
00309   minY_ = minY_arg;
00310   maxY_ = maxY_arg;
00311 
00312   minZ_ = minZ_arg;
00313   maxZ_ = maxZ_arg;
00314 
00315   minX_ = min (minX_, maxX_);
00316   minY_ = min (minY_, maxY_);
00317   minZ_ = min (minZ_, maxZ_);
00318 
00319   maxX_ = max (minX_, maxX_);
00320   maxY_ = max (minY_, maxY_);
00321   maxZ_ = max (minZ_, maxZ_);
00322 
00323   // generate bit masks for octree
00324   getKeyBitSize ();
00325 
00326   boundingBoxDefined_ = true;
00327 }
00328 
00330 template<typename PointT, typename LeafT, typename OctreeT> void
00331 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::defineBoundingBox (
00332     const double maxX_arg, const double maxY_arg, const double maxZ_arg)
00333 {
00334   // bounding box cannot be changed once the octree contains elements
00335   assert (this->leafCount_ == 0);
00336 
00337   assert (maxX_arg >= 0.0f);
00338   assert (maxY_arg >= 0.0f);
00339   assert (maxZ_arg >= 0.0f);
00340 
00341   minX_ = 0.0f;
00342   maxX_ = maxX_arg;
00343 
00344   minY_ = 0.0f;
00345   maxY_ = maxY_arg;
00346 
00347   minZ_ = 0.0f;
00348   maxZ_ = maxZ_arg;
00349 
00350   minX_ = min (minX_, maxX_);
00351   minY_ = min (minY_, maxY_);
00352   minZ_ = min (minZ_, maxZ_);
00353 
00354   maxX_ = max (minX_, maxX_);
00355   maxY_ = max (minY_, maxY_);
00356   maxZ_ = max (minZ_, maxZ_);
00357 
00358   // generate bit masks for octree
00359   getKeyBitSize ();
00360 
00361   boundingBoxDefined_ = true;
00362 }
00363 
00365 template<typename PointT, typename LeafT, typename OctreeT> void
00366 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::defineBoundingBox (const double cubeLen_arg)
00367 {
00368   // bounding box cannot be changed once the octree contains elements
00369   assert (this->leafCount_ == 0);
00370 
00371   assert (cubeLen_arg >= 0.0f);
00372 
00373   minX_ = 0.0f;
00374   maxX_ = cubeLen_arg;
00375 
00376   minY_ = 0.0f;
00377   maxY_ = cubeLen_arg;
00378 
00379   minZ_ = 0.0f;
00380   maxZ_ = cubeLen_arg;
00381 
00382   minX_ = min (minX_, maxX_);
00383   minY_ = min (minY_, maxY_);
00384   minZ_ = min (minZ_, maxZ_);
00385 
00386   maxX_ = max (minX_, maxX_);
00387   maxY_ = max (minY_, maxY_);
00388   maxZ_ = max (minZ_, maxZ_);
00389 
00390   // generate bit masks for octree
00391   getKeyBitSize ();
00392 
00393   boundingBoxDefined_ = true;
00394 }
00395 
00397 template<typename PointT, typename LeafT, typename OctreeT> void
00398 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::getBoundingBox (
00399     double& minX_arg, double& minY_arg, double& minZ_arg,
00400     double& maxX_arg, double& maxY_arg, double& maxZ_arg) const
00401 {
00402   minX_arg = minX_;
00403   minY_arg = minY_;
00404   minZ_arg = minZ_;
00405 
00406   maxX_arg = maxX_;
00407   maxY_arg = maxY_;
00408   maxZ_arg = maxZ_;
00409 }
00410 
00412 template<typename PointT, typename LeafT, typename OctreeT> void
00413 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::adoptBoundingBoxToPoint (const PointT& pointIdx_arg)
00414 {
00415 
00416   const float minValue = std::numeric_limits<float>::epsilon();
00417 
00418   // increase octree size until point fits into bounding box
00419   while (true)
00420   {
00421     bool bLowerBoundViolationX = (pointIdx_arg.x < minX_);
00422     bool bLowerBoundViolationY = (pointIdx_arg.y < minY_);
00423     bool bLowerBoundViolationZ = (pointIdx_arg.z < minZ_);
00424 
00425     bool bUpperBoundViolationX = (pointIdx_arg.x >= maxX_);
00426     bool bUpperBoundViolationY = (pointIdx_arg.y >= maxY_);
00427     bool bUpperBoundViolationZ = (pointIdx_arg.z >= maxZ_);
00428 
00429     // do we violate any bounds?
00430     if (bLowerBoundViolationX || bLowerBoundViolationY || bLowerBoundViolationZ || bUpperBoundViolationX
00431         || bUpperBoundViolationY || bUpperBoundViolationZ || (!boundingBoxDefined_))
00432     {
00433 
00434       double octreeSideLen;
00435       unsigned char childIdx;
00436 
00437       if (this->leafCount_ > 0)
00438       {
00439         // octree not empty - we add another tree level and thus increase its size by a factor of 2*2*2
00440         childIdx = ((!bUpperBoundViolationX) << 2) | ((!bUpperBoundViolationY) << 1) | ((!bUpperBoundViolationZ));
00441 
00442         OctreeBranch* newRootBranch;
00443 
00444         this->createBranch (newRootBranch);
00445         this->branchCount_++;
00446 
00447         this->setBranchChild (*newRootBranch, childIdx, this->rootNode_);
00448 
00449         this->rootNode_ = newRootBranch;
00450 
00451         octreeSideLen = (double)maxKeys_ * resolution_ ;
00452 
00453         if (!bUpperBoundViolationX)
00454           minX_ -= octreeSideLen;
00455 
00456         if (!bUpperBoundViolationY)
00457           minY_ -= octreeSideLen;
00458 
00459         if (!bUpperBoundViolationZ)
00460           minZ_ -= octreeSideLen;
00461 
00462        // configure tree depth of octree
00463         this->octreeDepth_ ++;
00464         this->setTreeDepth (this->octreeDepth_);
00465         maxKeys_ = (1 << this->octreeDepth_);
00466 
00467         // recalculate bounding box width
00468         octreeSideLen = (double)maxKeys_ * resolution_ - minValue;
00469 
00470         // increase octree bounding box
00471         maxX_ = minX_ + octreeSideLen;
00472         maxY_ = minY_ + octreeSideLen;
00473         maxZ_ = minZ_ + octreeSideLen;
00474 
00475       }
00476       else
00477       {
00478         // octree is empty - we set the center of the bounding box to our first pixel
00479         this->minX_ = pointIdx_arg.x - this->resolution_ / 2;
00480         this->minY_ = pointIdx_arg.y - this->resolution_ / 2;
00481         this->minZ_ = pointIdx_arg.z - this->resolution_ / 2;
00482 
00483         this->maxX_ = pointIdx_arg.x + this->resolution_ / 2;
00484         this->maxY_ = pointIdx_arg.y + this->resolution_ / 2;
00485         this->maxZ_ = pointIdx_arg.z + this->resolution_ / 2;
00486 
00487         getKeyBitSize();
00488       }
00489 
00490       boundingBoxDefined_ = true;
00491     }
00492     else
00493       // no bound violations anymore - leave while loop
00494       break;
00495   }
00496   
00497   
00498 
00499 }
00500 
00502 template<typename PointT, typename LeafT, typename OctreeT> void
00503 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::addPointIdx (const int pointIdx_arg)
00504 {
00505   OctreeKey key;
00506 
00507   assert (pointIdx_arg < (int) input_->points.size());
00508 
00509   const PointT& point = input_->points[pointIdx_arg];
00510 
00511   // make sure bounding box is big enough
00512   adoptBoundingBoxToPoint (point);
00513 
00514   // generate key
00515   genOctreeKeyforPoint (point, key);
00516 
00517   // add point to octree at key
00518   this->add (key, pointIdx_arg);
00519 }
00520 
00522 template<typename PointT, typename LeafT, typename OctreeT> const PointT&
00523 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::getPointByIndex (const unsigned int index_arg) const
00524 {
00525   // retrieve point from input cloud
00526   assert (index_arg < (unsigned int)input_->points.size ());
00527   return (this->input_->points[index_arg]);
00528 }
00529 
00531 template<typename PointT, typename LeafT, typename OctreeT> LeafT*
00532 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::findLeafAtPoint (const PointT& point) const
00533 {
00534   OctreeKey key;
00535 
00536   // generate key for point
00537   this->genOctreeKeyforPoint (point, key);
00538 
00539   return (this->findLeaf (key));
00540 }
00541 
00543 template<typename PointT, typename LeafT, typename OctreeT> void
00544 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::getKeyBitSize ()
00545 {
00546   unsigned int maxVoxels;
00547 
00548   unsigned int maxKeyX;
00549   unsigned int maxKeyY;
00550   unsigned int maxKeyZ;
00551 
00552   double octreeSideLen;
00553 
00554   const float minValue = std::numeric_limits<float>::epsilon();
00555 
00556   // find maximum key values for x, y, z
00557   maxKeyX = (unsigned int)((maxX_ - minX_) / resolution_);
00558   maxKeyY = (unsigned int)((maxY_ - minY_) / resolution_);
00559   maxKeyZ = (unsigned int)((maxZ_ - minZ_) / resolution_);
00560 
00561   // find maximum amount of keys
00562   maxVoxels = max (max (max (maxKeyX, maxKeyY), maxKeyZ), (unsigned int)2);
00563 
00564 
00565   // tree depth == amount of bits of maxVoxels
00566   this->octreeDepth_ = max ((min ((unsigned int)OCT_MAXTREEDEPTH, (unsigned int)ceil (this->Log2 (maxVoxels)-minValue))),
00567                             (unsigned int)0);
00568 
00569   maxKeys_ = (1 << this->octreeDepth_);
00570 
00571   octreeSideLen = (double)maxKeys_ * resolution_-minValue;
00572 
00573   if (this->leafCount_ == 0)
00574   {
00575     double octreeOversizeX;
00576     double octreeOversizeY;
00577     double octreeOversizeZ;
00578 
00579     octreeOversizeX = (octreeSideLen - (maxX_ - minX_)) / 2.0;
00580     octreeOversizeY = (octreeSideLen - (maxY_ - minY_)) / 2.0;
00581     octreeOversizeZ = (octreeSideLen - (maxZ_ - minZ_)) / 2.0;
00582 
00583     minX_ -= octreeOversizeX;
00584     minY_ -= octreeOversizeY;
00585     minZ_ -= octreeOversizeZ;
00586 
00587     maxX_ += octreeOversizeX;
00588     maxY_ += octreeOversizeY;
00589     maxZ_ += octreeOversizeZ;
00590   }
00591   else
00592   {
00593     maxX_ = minX_ + octreeSideLen;
00594     maxY_ = minY_ + octreeSideLen;
00595     maxZ_ = minZ_ + octreeSideLen;
00596   }
00597 
00598  // configure tree depth of octree
00599   this->setTreeDepth (this->octreeDepth_);
00600 
00601 }
00602 
00604 template<typename PointT, typename LeafT, typename OctreeT> void
00605 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::genOctreeKeyforPoint (const PointT& point_arg,
00606                                                                              OctreeKey & key_arg) const
00607   {
00608     // calculate integer key for point coordinates
00609     key_arg.x = min ((unsigned int)((point_arg.x - this->minX_) / this->resolution_), maxKeys_ - 1);
00610     key_arg.y = min ((unsigned int)((point_arg.y - this->minY_) / this->resolution_), maxKeys_ - 1);
00611     key_arg.z = min ((unsigned int)((point_arg.z - this->minZ_) / this->resolution_), maxKeys_ - 1);
00612   }
00613 
00615 template<typename PointT, typename LeafT, typename OctreeT> void
00616 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::genOctreeKeyforPoint (
00617     const double pointX_arg, const double pointY_arg,
00618     const double pointZ_arg, OctreeKey & key_arg) const
00619 {
00620   PointT tempPoint;
00621 
00622   tempPoint.x = (float)pointX_arg;
00623   tempPoint.y = (float)pointY_arg;
00624   tempPoint.z = (float)pointZ_arg;
00625 
00626   // generate key for point
00627   genOctreeKeyforPoint (tempPoint, key_arg);
00628 }
00629 
00631 template<typename PointT, typename LeafT, typename OctreeT> bool
00632 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::genOctreeKeyForDataT (const int& data_arg, OctreeKey & key_arg) const
00633 {
00634   const PointT tempPoint = getPointByIndex (data_arg);
00635 
00636   // generate key for point
00637   genOctreeKeyforPoint (tempPoint, key_arg);
00638 
00639   return (true);
00640 }
00641 
00643 template<typename PointT, typename LeafT, typename OctreeT> void
00644 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::genLeafNodeCenterFromOctreeKey (const OctreeKey & key, PointT & point) const
00645 {
00646   // define point to leaf node voxel center
00647   point.x = (float)(((double)key.x + 0.5f) * this->resolution_ + this->minX_);
00648   point.y = (float)(((double)key.y + 0.5f) * this->resolution_ + this->minY_);
00649   point.z = (float)(((double)key.z + 0.5f) * this->resolution_ + this->minZ_);
00650 }
00651 
00653 template<typename PointT, typename LeafT, typename OctreeT> void
00654 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::genVoxelCenterFromOctreeKey (
00655     const OctreeKey & key_arg,
00656     unsigned int treeDepth_arg,
00657     PointT& point_arg) const
00658 {
00659   // generate point for voxel center defined by treedepth (bitLen) and key
00660   point_arg.x = (float)(((double)(key_arg.x) + 0.5f) * (this->resolution_ * (double)(1 << (this->octreeDepth_
00661       - treeDepth_arg))) + this->minX_);
00662   point_arg.y = (float)(((double)(key_arg.y) + 0.5f) * (this->resolution_ * (double)(1 << (this->octreeDepth_
00663       - treeDepth_arg))) + this->minY_);
00664   point_arg.z = (float)(((double)(key_arg.z) + 0.5f) * (this->resolution_ * (double)(1 << (this->octreeDepth_
00665       - treeDepth_arg))) + this->minZ_);
00666 }
00667 
00669 template<typename PointT, typename LeafT, typename OctreeT> void
00670 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::genVoxelBoundsFromOctreeKey (
00671     const OctreeKey & key_arg,
00672     unsigned int treeDepth_arg,
00673     Eigen::Vector3f &min_pt,
00674     Eigen::Vector3f &max_pt) const
00675 {
00676   // calculate voxel size of current tree depth
00677   double voxel_side_len = this->resolution_ * (double)(1 << (this->octreeDepth_ - treeDepth_arg));
00678 
00679   // calculate voxel bounds
00680   min_pt (0) = (float)((double)(key_arg.x) * voxel_side_len + this->minX_);
00681   min_pt (1) = (float)((double)(key_arg.y) * voxel_side_len + this->minY_);
00682   min_pt (2) = (float)((double)(key_arg.z) * voxel_side_len + this->minZ_);
00683 
00684   max_pt (0) = (float)((double)(key_arg.x + 1) * voxel_side_len + this->minX_);
00685   max_pt (1) = (float)((double)(key_arg.y + 1) * voxel_side_len + this->minY_);
00686   max_pt (2) = (float)((double)(key_arg.z + 1) * voxel_side_len + this->minZ_);
00687 }
00688 
00690 template<typename PointT, typename LeafT, typename OctreeT> double
00691 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::getVoxelSquaredSideLen (unsigned int treeDepth_arg) const
00692 {
00693   double sideLen;
00694 
00695   // side length of the voxel cube increases exponentially with the octree depth
00696   sideLen = this->resolution_ * (double)(1 << (this->octreeDepth_ - treeDepth_arg));
00697 
00698   // squared voxel side length
00699   sideLen *= sideLen;
00700 
00701   return (sideLen);
00702 }
00703 
00705 template<typename PointT, typename LeafT, typename OctreeT> double
00706 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::getVoxelSquaredDiameter (unsigned int treeDepth_arg) const
00707 {
00708   // return the squared side length of the voxel cube as a function of the octree depth
00709   return (getVoxelSquaredSideLen (treeDepth_arg) * 3);
00710 }
00711 
00713 template<typename PointT, typename LeafT, typename OctreeT> int
00714 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::getOccupiedVoxelCentersRecursive (
00715     const OctreeBranch* node_arg,
00716     const OctreeKey& key_arg,
00717     std::vector<PointT,
00718     Eigen::aligned_allocator<PointT> > &voxelCenterList_arg) const
00719 {
00720   // child iterator
00721   unsigned char childIdx;
00722 
00723   int voxelCount = 0;
00724 
00725   // iterate over all children
00726   for (childIdx = 0; childIdx < 8; childIdx++)
00727   {
00728     if (!this->branchHasChild (*node_arg, childIdx))
00729       continue;
00730 
00731     const OctreeNode * childNode;
00732     childNode = this->getBranchChild (*node_arg, childIdx);
00733 
00734     // generate new key for current branch voxel
00735     OctreeKey newKey;
00736     newKey.x = (key_arg.x << 1) | (!!(childIdx & (1 << 2)));
00737     newKey.y = (key_arg.y << 1) | (!!(childIdx & (1 << 1)));
00738     newKey.z = (key_arg.z << 1) | (!!(childIdx & (1 << 0)));
00739 
00740     switch (childNode->getNodeType ())
00741     {
00742       case BRANCH_NODE:
00743       {
00744         // recursively proceed with indexed child branch
00745         voxelCount += getOccupiedVoxelCentersRecursive ((OctreeBranch*)childNode, newKey, voxelCenterList_arg);
00746         break;
00747       }
00748       case LEAF_NODE:
00749       {
00750         PointT newPoint;
00751 
00752         genLeafNodeCenterFromOctreeKey (newKey, newPoint);
00753         voxelCenterList_arg.push_back (newPoint);
00754 
00755         voxelCount++;
00756         break;
00757       }
00758       default:
00759   break;
00760     }
00761   }
00762   return (voxelCount);
00763 }
00764 
00765 #define PCL_INSTANTIATE_OctreePointCloudSingleBufferWithLeafDataTVector(T) template class PCL_EXPORTS pcl::octree::OctreePointCloud<T, pcl::octree::OctreeLeafDataTVector<int> , pcl::octree::OctreeBase<int, pcl::octree::OctreeLeafDataTVector<int> > >;
00766 #define PCL_INSTANTIATE_OctreePointCloudDoubleBufferWithLeafDataTVector(T) template class PCL_EXPORTS pcl::octree::OctreePointCloud<T, pcl::octree::OctreeLeafDataTVector<int> , pcl::octree::Octree2BufBase<int, pcl::octree::OctreeLeafDataTVector<int> > >;
00767 #define PCL_INSTANTIATE_OctreePointCloudLowMemWithLeafDataTVector(T)       template class PCL_EXPORTS pcl::octree::OctreePointCloud<T, pcl::octree::OctreeLeafDataTVector<int> , pcl::octree::OctreeLowMemBase<int, pcl::octree::OctreeLeafDataTVector<int> > >;
00768 
00769 #define PCL_INSTANTIATE_OctreePointCloudSingleBufferWithLeafDataT(T) template class PCL_EXPORTS pcl::octree::OctreePointCloud<T, pcl::octree::OctreeLeafDataT<int> , pcl::octree::OctreeBase<int, pcl::octree::OctreeLeafDataT<int> > >;
00770 #define PCL_INSTANTIATE_OctreePointCloudDoubleBufferWithLeafDataT(T) template class PCL_EXPORTS pcl::octree::OctreePointCloud<T, pcl::octree::OctreeLeafDataT<int> , pcl::octree::Octree2BufBase<int, pcl::octree::OctreeLeafDataT<int> > >;
00771 #define PCL_INSTANTIATE_OctreePointCloudLowMemWithLeafDataT(T)       template class PCL_EXPORTS pcl::octree::OctreePointCloud<T, pcl::octree::OctreeLeafDataT<int> , pcl::octree::OctreeLowMemBase<int, pcl::octree::OctreeLeafDataT<int> > >;
00772 
00773 #define PCL_INSTANTIATE_OctreePointCloudSingleBufferWithEmptyLeaf(T) template class PCL_EXPORTS pcl::octree::OctreePointCloud<T, pcl::octree::OctreeLeafEmpty<int> , pcl::octree::OctreeBase<int, pcl::octree::OctreeLeafEmpty<int> > >;
00774 #define PCL_INSTANTIATE_OctreePointCloudDoubleBufferWithEmptyLeaf(T) template class PCL_EXPORTS pcl::octree::OctreePointCloud<T, pcl::octree::OctreeLeafEmpty<int> , pcl::octree::Octree2BufBase<int, pcl::octree::OctreeLeafEmpty<int> > >;
00775 #define PCL_INSTANTIATE_OctreePointCloudLowMemWithEmptyLeaf(T)       template class PCL_EXPORTS pcl::octree::OctreePointCloud<T, pcl::octree::OctreeLeafEmpty<int> , pcl::octree::OctreeLowMemBase<int, pcl::octree::OctreeLeafEmpty<int> > >;
00776 
00777 #endif /* OCTREE_POINTCLOUD_HPP_ */