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