octree_search.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_search.hpp 6119 2012-07-03 18:50:04Z aichim $
00037  */
00038 
00039 #ifndef PCL_OCTREE_SEARCH_IMPL_H_
00040 #define PCL_OCTREE_SEARCH_IMPL_H_
00041 
00042 #include <pcl/point_cloud.h>
00043 #include <pcl/point_types.h>
00044 
00045 #include <pcl/common/common.h>
00046 #include <assert.h>
00047 
00049 template<typename PointT, typename LeafT, typename BranchT> bool
00050 pcl::octree::OctreePointCloudSearch<PointT, LeafT, BranchT>::voxelSearch (const PointT& point,
00051                                                                           std::vector<int>& pointIdx_data)
00052 {
00053   assert (isFinite (point) && "Invalid (NaN, Inf) point coordinates given to nearestKSearch!");
00054   OctreeKey key;
00055   bool b_success = false;
00056 
00057   // generate key
00058   this->genOctreeKeyforPoint (point, key);
00059 
00060   LeafT* leaf = this->findLeaf (key);
00061 
00062   if (leaf)
00063   {
00064     leaf->getData (pointIdx_data);
00065     b_success = true;
00066   }
00067 
00068   return (b_success);
00069 }
00070 
00072 template<typename PointT, typename LeafT, typename BranchT> bool
00073 pcl::octree::OctreePointCloudSearch<PointT, LeafT, BranchT>::voxelSearch (const int index,
00074                                                                           std::vector<int>& pointIdx_data)
00075 {
00076   const PointT search_point = this->getPointByIndex (index);
00077   return (this->voxelSearch (search_point, pointIdx_data));
00078 }
00079 
00081 template<typename PointT, typename LeafT, typename BranchT> int
00082 pcl::octree::OctreePointCloudSearch<PointT, LeafT, BranchT>::nearestKSearch (const PointT &p_q, int k,
00083                                                                              std::vector<int> &k_indices,
00084                                                                              std::vector<float> &k_sqr_distances)
00085 {
00086   assert(this->leafCount_>0);
00087   assert (isFinite (p_q) && "Invalid (NaN, Inf) point coordinates given to nearestKSearch!");
00088 
00089   k_indices.clear ();
00090   k_sqr_distances.clear ();
00091 
00092   if (k < 1)
00093     return 0;
00094   
00095   unsigned int i;
00096   unsigned int resultCount;
00097 
00098   prioPointQueueEntry pointEntry;
00099   std::vector<prioPointQueueEntry> pointCandidates;
00100 
00101   OctreeKey key;
00102   key.x = key.y = key.z = 0;
00103 
00104   // initalize smallest point distance in search with high value
00105   double smallestDist = numeric_limits<double>::max ();
00106 
00107   getKNearestNeighborRecursive (p_q, k, this->rootNode_, key, 1, smallestDist, pointCandidates);
00108 
00109   resultCount = static_cast<unsigned int> (pointCandidates.size ());
00110 
00111   k_indices.resize (resultCount);
00112   k_sqr_distances.resize (resultCount);
00113   
00114   for (i = 0; i < resultCount; ++i)
00115   {
00116     k_indices [i] = pointCandidates [i].pointIdx_;
00117     k_sqr_distances [i] = pointCandidates [i].pointDistance_;
00118   }
00119 
00120   return static_cast<int> (k_indices.size ());
00121 }
00122 
00124 template<typename PointT, typename LeafT, typename BranchT> int
00125 pcl::octree::OctreePointCloudSearch<PointT, LeafT, BranchT>::nearestKSearch (int index, int k,
00126                                                                              std::vector<int> &k_indices,
00127                                                                              std::vector<float> &k_sqr_distances)
00128 {
00129   const PointT search_point = this->getPointByIndex (index);
00130   return (nearestKSearch (search_point, k, k_indices, k_sqr_distances));
00131 }
00132 
00134 template<typename PointT, typename LeafT, typename BranchT> void
00135 pcl::octree::OctreePointCloudSearch<PointT, LeafT, BranchT>::approxNearestSearch (const PointT &p_q,
00136                                                                                   int &result_index,
00137                                                                                   float &sqr_distance)
00138 {
00139   assert(this->leafCount_>0);
00140   assert (isFinite (p_q) && "Invalid (NaN, Inf) point coordinates given to nearestKSearch!");
00141   
00142   OctreeKey key;
00143   key.x = key.y = key.z = 0;
00144 
00145   approxNearestSearchRecursive (p_q, this->rootNode_, key, 1, result_index, sqr_distance);
00146 
00147   return;
00148 }
00149 
00151 template<typename PointT, typename LeafT, typename BranchT> void
00152 pcl::octree::OctreePointCloudSearch<PointT, LeafT, BranchT>::approxNearestSearch (int query_index, int &result_index,
00153                                                                                   float &sqr_distance)
00154 {
00155   const PointT searchPoint = this->getPointByIndex (query_index);
00156 
00157   return (approxNearestSearch (searchPoint, result_index, sqr_distance));
00158 }
00159 
00161 template<typename PointT, typename LeafT, typename BranchT> int
00162 pcl::octree::OctreePointCloudSearch<PointT, LeafT, BranchT>::radiusSearch (const PointT &p_q, const double radius,
00163                                                                            std::vector<int> &k_indices,
00164                                                                            std::vector<float> &k_sqr_distances,
00165                                                                            unsigned int max_nn) const
00166 {
00167   assert (isFinite (p_q) && "Invalid (NaN, Inf) point coordinates given to nearestKSearch!");
00168   OctreeKey key;
00169   key.x = key.y = key.z = 0;
00170 
00171   k_indices.clear ();
00172   k_sqr_distances.clear ();
00173 
00174   getNeighborsWithinRadiusRecursive (p_q, radius * radius, this->rootNode_, key, 1, k_indices, k_sqr_distances,
00175                                      max_nn);
00176 
00177   return (static_cast<int> (k_indices.size ()));
00178 }
00179 
00181 template<typename PointT, typename LeafT, typename BranchT> int
00182 pcl::octree::OctreePointCloudSearch<PointT, LeafT, BranchT>::radiusSearch (int index, const double radius,
00183                                                                            std::vector<int> &k_indices,
00184                                                                            std::vector<float> &k_sqr_distances,
00185                                                                            unsigned int max_nn) const
00186 {
00187   const PointT search_point = this->getPointByIndex (index);
00188 
00189   return (radiusSearch (search_point, radius, k_indices, k_sqr_distances, max_nn));
00190 }
00191 
00193 template<typename PointT, typename LeafT, typename BranchT> int
00194 pcl::octree::OctreePointCloudSearch<PointT, LeafT, BranchT>::boxSearch (const Eigen::Vector3f &min_pt,
00195                                                                         const Eigen::Vector3f &max_pt,
00196                                                                         std::vector<int> &k_indices) const
00197 {
00198 
00199   OctreeKey key;
00200   key.x = key.y = key.z = 0;
00201 
00202   k_indices.clear ();
00203 
00204   boxSearchRecursive (min_pt, max_pt, this->rootNode_, key, 1, k_indices);
00205 
00206   return (static_cast<int> (k_indices.size ()));
00207 
00208 }
00209 
00211 template<typename PointT, typename LeafT, typename BranchT> double
00212 pcl::octree::OctreePointCloudSearch<PointT, LeafT, BranchT>::getKNearestNeighborRecursive (
00213     const PointT & point, unsigned int K, const BranchNode* node, const OctreeKey& key, unsigned int treeDepth,
00214     const double squaredSearchRadius, std::vector<prioPointQueueEntry>& pointCandidates) const
00215 {
00216   std::vector<prioBranchQueueEntry> searchEntryHeap;
00217   searchEntryHeap.resize (8);
00218 
00219   unsigned char childIdx;
00220 
00221   OctreeKey newKey;
00222 
00223   double smallestSquaredDist = squaredSearchRadius;
00224 
00225   // get spatial voxel information
00226   double voxelSquaredDiameter = this->getVoxelSquaredDiameter (treeDepth);
00227 
00228   // iterate over all children
00229   for (childIdx = 0; childIdx < 8; childIdx++)
00230   {
00231     if (this->branchHasChild (*node, childIdx))
00232     {
00233       PointT voxelCenter;
00234 
00235       searchEntryHeap[childIdx].key.x = (key.x << 1) + (!!(childIdx & (1 << 2)));
00236       searchEntryHeap[childIdx].key.y = (key.y << 1) + (!!(childIdx & (1 << 1)));
00237       searchEntryHeap[childIdx].key.z = (key.z << 1) + (!!(childIdx & (1 << 0)));
00238 
00239       // generate voxel center point for voxel at key
00240       this->genVoxelCenterFromOctreeKey (searchEntryHeap[childIdx].key, treeDepth, voxelCenter);
00241 
00242       // generate new priority queue element
00243       searchEntryHeap[childIdx].node = this->getBranchChildPtr (*node, childIdx);
00244       searchEntryHeap[childIdx].pointDistance = pointSquaredDist (voxelCenter, point);
00245     }
00246     else
00247     {
00248       searchEntryHeap[childIdx].pointDistance = numeric_limits<float>::infinity ();
00249     }
00250   }
00251 
00252   std::sort (searchEntryHeap.begin (), searchEntryHeap.end ());
00253 
00254   // iterate over all children in priority queue
00255   // check if the distance to search candidate is smaller than the best point distance (smallestSquaredDist)
00256   while ((!searchEntryHeap.empty ())
00257       && (searchEntryHeap.back ().pointDistance
00258           < smallestSquaredDist + voxelSquaredDiameter / 4.0 + sqrt (smallestSquaredDist * voxelSquaredDiameter)
00259               - this->epsilon_))
00260   {
00261     const OctreeNode* childNode;
00262 
00263     // read from priority queue element
00264     childNode = searchEntryHeap.back ().node;
00265     newKey = searchEntryHeap.back ().key;
00266 
00267     if (treeDepth < this->octreeDepth_)
00268     {
00269       // we have not reached maximum tree depth
00270       smallestSquaredDist = getKNearestNeighborRecursive (point, K, static_cast<const BranchNode*> (childNode), newKey, treeDepth + 1,
00271                                                           smallestSquaredDist, pointCandidates);
00272     }
00273     else
00274     {
00275       // we reached leaf node level
00276 
00277       float squaredDist;
00278       size_t i;
00279       vector<int> decodedPointVector;
00280 
00281       const LeafNode* childLeaf = static_cast<const LeafNode*> (childNode);
00282 
00283       // decode leaf node into decodedPointVector
00284       childLeaf->getData (decodedPointVector);
00285 
00286       // Linearly iterate over all decoded (unsorted) points
00287       for (i = 0; i < decodedPointVector.size (); i++)
00288       {
00289 
00290         const PointT& candidatePoint = this->getPointByIndex (decodedPointVector[i]);
00291 
00292         // calculate point distance to search point
00293         squaredDist = pointSquaredDist (candidatePoint, point);
00294 
00295         // check if a closer match is found
00296         if (squaredDist < smallestSquaredDist)
00297         {
00298           prioPointQueueEntry pointEntry;
00299 
00300           pointEntry.pointDistance_ = squaredDist;
00301           pointEntry.pointIdx_ = decodedPointVector[i];
00302           pointCandidates.push_back (pointEntry);
00303         }
00304       }
00305 
00306       std::sort (pointCandidates.begin (), pointCandidates.end ());
00307 
00308       if (pointCandidates.size () > K)
00309         pointCandidates.resize (K);
00310 
00311       if (pointCandidates.size () == K)
00312         smallestSquaredDist = pointCandidates.back ().pointDistance_;
00313     }
00314     // pop element from priority queue
00315     searchEntryHeap.pop_back ();
00316   }
00317 
00318   return (smallestSquaredDist);
00319 }
00320 
00322 template<typename PointT, typename LeafT, typename BranchT> void
00323 pcl::octree::OctreePointCloudSearch<PointT, LeafT, BranchT>::getNeighborsWithinRadiusRecursive (
00324     const PointT & point, const double radiusSquared, const BranchNode* node, const OctreeKey& key,
00325     unsigned int treeDepth, std::vector<int>& k_indices, std::vector<float>& k_sqr_distances,
00326     unsigned int max_nn) const
00327 {
00328   // child iterator
00329   unsigned char childIdx;
00330 
00331   // get spatial voxel information
00332   double voxelSquaredDiameter = this->getVoxelSquaredDiameter (treeDepth);
00333 
00334   // iterate over all children
00335   for (childIdx = 0; childIdx < 8; childIdx++)
00336   {
00337     if (!this->branchHasChild (*node, childIdx))
00338       continue;
00339 
00340     const OctreeNode* childNode;
00341     childNode = this->getBranchChildPtr (*node, childIdx);
00342 
00343     OctreeKey newKey;
00344     PointT voxelCenter;
00345     float squaredDist;
00346 
00347     // generate new key for current branch voxel
00348     newKey.x = (key.x << 1) + (!!(childIdx & (1 << 2)));
00349     newKey.y = (key.y << 1) + (!!(childIdx & (1 << 1)));
00350     newKey.z = (key.z << 1) + (!!(childIdx & (1 << 0)));
00351 
00352     // generate voxel center point for voxel at key
00353     this->genVoxelCenterFromOctreeKey (newKey, treeDepth, voxelCenter);
00354 
00355     // calculate distance to search point
00356     squaredDist = pointSquaredDist (static_cast<const PointT&> (voxelCenter), point);
00357 
00358     // if distance is smaller than search radius
00359     if (squaredDist + this->epsilon_
00360         <= voxelSquaredDiameter / 4.0 + radiusSquared + sqrt (voxelSquaredDiameter * radiusSquared))
00361     {
00362 
00363       if (treeDepth < this->octreeDepth_)
00364       {
00365         // we have not reached maximum tree depth
00366         getNeighborsWithinRadiusRecursive (point, radiusSquared, static_cast<const BranchNode*> (childNode), newKey, treeDepth + 1,
00367                                            k_indices, k_sqr_distances, max_nn);
00368         if (max_nn != 0 && k_indices.size () == static_cast<unsigned int> (max_nn))
00369           return;
00370       }
00371       else
00372       {
00373         // we reached leaf node level
00374 
00375         size_t i;
00376         const LeafNode* childLeaf = static_cast<const LeafNode*> (childNode);
00377         vector<int> decodedPointVector;
00378 
00379         // decode leaf node into decodedPointVector
00380         childLeaf->getData (decodedPointVector);
00381 
00382         // Linearly iterate over all decoded (unsorted) points
00383         for (i = 0; i < decodedPointVector.size (); i++)
00384         {
00385           const PointT& candidatePoint = this->getPointByIndex (decodedPointVector[i]);
00386 
00387           // calculate point distance to search point
00388           squaredDist = pointSquaredDist (candidatePoint, point);
00389 
00390           // check if a match is found
00391           if (squaredDist > radiusSquared)
00392             continue;
00393 
00394           // add point to result vector
00395           k_indices.push_back (decodedPointVector[i]);
00396           k_sqr_distances.push_back (squaredDist);
00397 
00398           if (max_nn != 0 && k_indices.size () == static_cast<unsigned int> (max_nn))
00399             return;
00400         }
00401       }
00402     }
00403   }
00404 }
00405 
00407 template<typename PointT, typename LeafT, typename BranchT> void
00408 pcl::octree::OctreePointCloudSearch<PointT, LeafT, BranchT>::approxNearestSearchRecursive (const PointT & point,
00409                                                                                            const BranchNode* node,
00410                                                                                            const OctreeKey& key,
00411                                                                                            unsigned int treeDepth,
00412                                                                                            int& result_index,
00413                                                                                            float& sqr_distance)
00414 {
00415   unsigned char childIdx;
00416   unsigned char minChildIdx;
00417   double minVoxelCenterDistance;
00418 
00419   OctreeKey minChildKey;
00420   OctreeKey newKey;
00421 
00422   const OctreeNode* childNode;
00423 
00424   // set minimum voxel distance to maximum value
00425   minVoxelCenterDistance = numeric_limits<double>::max ();
00426 
00427   minChildIdx = 0xFF;
00428 
00429   // iterate over all children
00430   for (childIdx = 0; childIdx < 8; childIdx++)
00431   {
00432     if (!this->branchHasChild (*node, childIdx))
00433       continue;
00434 
00435     PointT voxelCenter;
00436     double voxelPointDist;
00437 
00438     newKey.x = (key.x << 1) + (!!(childIdx & (1 << 2)));
00439     newKey.y = (key.y << 1) + (!!(childIdx & (1 << 1)));
00440     newKey.z = (key.z << 1) + (!!(childIdx & (1 << 0)));
00441 
00442     // generate voxel center point for voxel at key
00443     this->genVoxelCenterFromOctreeKey (newKey, treeDepth, voxelCenter);
00444 
00445     voxelPointDist = pointSquaredDist (voxelCenter, point);
00446 
00447     // search for child voxel with shortest distance to search point
00448     if (voxelPointDist >= minVoxelCenterDistance)
00449       continue;
00450 
00451     minVoxelCenterDistance = voxelPointDist;
00452     minChildIdx = childIdx;
00453     minChildKey = newKey;
00454   }
00455 
00456   // make sure we found at least one branch child
00457   assert(minChildIdx<8);
00458 
00459   childNode = this->getBranchChildPtr (*node, minChildIdx);
00460 
00461   if (treeDepth < this->octreeDepth_)
00462   {
00463     // we have not reached maximum tree depth
00464     approxNearestSearchRecursive (point, static_cast<const BranchNode*> (childNode), minChildKey, treeDepth + 1, result_index,
00465                                   sqr_distance);
00466   }
00467   else
00468   {
00469     // we reached leaf node level
00470 
00471     double squaredDist;
00472     double smallestSquaredDist;
00473     size_t i;
00474     vector<int> decodedPointVector;
00475 
00476     const LeafNode* childLeaf = static_cast<const LeafNode*> (childNode);
00477 
00478     smallestSquaredDist = numeric_limits<double>::max ();
00479 
00480     // decode leaf node into decodedPointVector
00481     childLeaf->getData (decodedPointVector);
00482 
00483     // Linearly iterate over all decoded (unsorted) points
00484     for (i = 0; i < decodedPointVector.size (); i++)
00485     {
00486       const PointT& candidatePoint = this->getPointByIndex (decodedPointVector[i]);
00487 
00488       // calculate point distance to search point
00489       squaredDist = pointSquaredDist (candidatePoint, point);
00490 
00491       // check if a closer match is found
00492       if (squaredDist >= smallestSquaredDist)
00493         continue;
00494 
00495       result_index = decodedPointVector[i];
00496       smallestSquaredDist = squaredDist;
00497       sqr_distance = static_cast<float> (squaredDist);
00498     }
00499   }
00500 }
00501 
00503 template<typename PointT, typename LeafT, typename BranchT> float
00504 pcl::octree::OctreePointCloudSearch<PointT, LeafT, BranchT>::pointSquaredDist (const PointT & pointA,
00505                                                                                const PointT & pointB) const
00506 {
00507   return (pointA.getVector3fMap () - pointB.getVector3fMap ()).squaredNorm ();
00508 }
00509 
00511 template<typename PointT, typename LeafT, typename BranchT> void
00512 pcl::octree::OctreePointCloudSearch<PointT, LeafT, BranchT>::boxSearchRecursive (const Eigen::Vector3f &min_pt,
00513                                                                                  const Eigen::Vector3f &max_pt,
00514                                                                                  const BranchNode* node,
00515                                                                                  const OctreeKey& key,
00516                                                                                  unsigned int treeDepth,
00517                                                                                  std::vector<int>& k_indices) const
00518 {
00519   // child iterator
00520   unsigned char childIdx;
00521 
00522   // iterate over all children
00523   for (childIdx = 0; childIdx < 8; childIdx++)
00524   {
00525 
00526     const OctreeNode* childNode;
00527     childNode = this->getBranchChildPtr (*node, childIdx);
00528 
00529     if (!childNode)
00530       continue;
00531 
00532     OctreeKey newKey;
00533     // generate new key for current branch voxel
00534     newKey.x = (key.x << 1) + (!!(childIdx & (1 << 2)));
00535     newKey.y = (key.y << 1) + (!!(childIdx & (1 << 1)));
00536     newKey.z = (key.z << 1) + (!!(childIdx & (1 << 0)));
00537 
00538     // voxel corners
00539     Eigen::Vector3f lowerVoxelCorner;
00540     Eigen::Vector3f upperVoxelCorner;
00541     // get voxel coordinates
00542     this->genVoxelBoundsFromOctreeKey (newKey, treeDepth, lowerVoxelCorner, upperVoxelCorner);
00543 
00544     // test if search region overlap with voxel space
00545 
00546     if ( !( (lowerVoxelCorner (0) > max_pt (0)) || (min_pt (0) > upperVoxelCorner(0)) ||
00547             (lowerVoxelCorner (1) > max_pt (1)) || (min_pt (1) > upperVoxelCorner(1)) ||
00548             (lowerVoxelCorner (2) > max_pt (2)) || (min_pt (2) > upperVoxelCorner(2)) ) )
00549     {
00550 
00551       if (treeDepth < this->octreeDepth_)
00552       {
00553         // we have not reached maximum tree depth
00554         boxSearchRecursive (min_pt, max_pt, static_cast<const BranchNode*> (childNode), newKey, treeDepth + 1, k_indices);
00555       }
00556       else
00557       {
00558         // we reached leaf node level
00559         size_t i;
00560         vector<int> decodedPointVector;
00561         bool bInBox;
00562 
00563         const LeafNode* childLeaf = static_cast<const LeafNode*> (childNode);
00564 
00565         // decode leaf node into decodedPointVector
00566         childLeaf->getData (decodedPointVector);
00567 
00568         // Linearly iterate over all decoded (unsorted) points
00569         for (i = 0; i < decodedPointVector.size (); i++)
00570         {
00571           const PointT& candidatePoint = this->getPointByIndex (decodedPointVector[i]);
00572 
00573           // check if point falls within search box
00574           bInBox = ( (candidatePoint.x > min_pt (0)) && (candidatePoint.x < max_pt (0)) &&
00575                      (candidatePoint.y > min_pt (1)) && (candidatePoint.y < max_pt (1)) &&
00576                      (candidatePoint.z > min_pt (2)) && (candidatePoint.z < max_pt (2)) );
00577 
00578           if (bInBox)
00579             // add to result vector
00580             k_indices.push_back (decodedPointVector[i]);
00581         }
00582       }
00583     }
00584   }
00585 }
00586 
00588 template<typename PointT, typename LeafT, typename BranchT> int
00589 pcl::octree::OctreePointCloudSearch<PointT, LeafT, BranchT>::getIntersectedVoxelCenters (
00590     Eigen::Vector3f origin, Eigen::Vector3f direction, AlignedPointTVector &voxelCenterList,
00591     int maxVoxelCount) const
00592 {
00593   OctreeKey key;
00594   key.x = key.y = key.z = 0;
00595 
00596   voxelCenterList.clear ();
00597 
00598   // Voxel childIdx remapping
00599   unsigned char a = 0;
00600 
00601   double minX, minY, minZ, maxX, maxY, maxZ;
00602 
00603   initIntersectedVoxel (origin, direction, minX, minY, minZ, maxX, maxY, maxZ, a);
00604 
00605   if (max (max (minX, minY), minZ) < min (min (maxX, maxY), maxZ))
00606     return getIntersectedVoxelCentersRecursive (minX, minY, minZ, maxX, maxY, maxZ, a, this->rootNode_, key,
00607                                                 voxelCenterList, maxVoxelCount);
00608 
00609   return (0);
00610 }
00611 
00613 template<typename PointT, typename LeafT, typename BranchT> int
00614 pcl::octree::OctreePointCloudSearch<PointT, LeafT, BranchT>::getIntersectedVoxelIndices (
00615     Eigen::Vector3f origin, Eigen::Vector3f direction, std::vector<int> &k_indices,
00616     int maxVoxelCount) const
00617 {
00618   OctreeKey key;
00619   key.x = key.y = key.z = 0;
00620 
00621   k_indices.clear ();
00622 
00623   // Voxel childIdx remapping
00624   unsigned char a = 0;
00625   double minX, minY, minZ, maxX, maxY, maxZ;
00626 
00627   initIntersectedVoxel (origin, direction, minX, minY, minZ, maxX, maxY, maxZ, a);
00628 
00629   if (max (max (minX, minY), minZ) < min (min (maxX, maxY), maxZ))
00630     return getIntersectedVoxelIndicesRecursive (minX, minY, minZ, maxX, maxY, maxZ, a, this->rootNode_, key,
00631                                                 k_indices, maxVoxelCount);
00632   return (0);
00633 }
00634 
00636 template<typename PointT, typename LeafT, typename BranchT> int
00637 pcl::octree::OctreePointCloudSearch<PointT, LeafT, BranchT>::getIntersectedVoxelCentersRecursive (
00638     double minX, double minY, double minZ, double maxX, double maxY, double maxZ, unsigned char a,
00639     const OctreeNode* node, const OctreeKey& key, AlignedPointTVector &voxelCenterList, int maxVoxelCount) const
00640 {
00641   if (maxX < 0.0 || maxY < 0.0 || maxZ < 0.0)
00642     return (0);
00643 
00644   // If leaf node, get voxel center and increment intersection count
00645   if (node->getNodeType () == LEAF_NODE)
00646   {
00647     PointT newPoint;
00648 
00649     this->genLeafNodeCenterFromOctreeKey (key, newPoint);
00650 
00651     voxelCenterList.push_back (newPoint);
00652 
00653     return (1);
00654   }
00655 
00656   // Voxel intersection count for branches children
00657   int voxelCount = 0;
00658 
00659   // Voxel mid lines
00660   double midX = 0.5 * (minX + maxX);
00661   double midY = 0.5 * (minY + maxY);
00662   double midZ = 0.5 * (minZ + maxZ);
00663 
00664   // First voxel node ray will intersect
00665   int currNode = getFirstIntersectedNode (minX, minY, minZ, midX, midY, midZ);
00666 
00667   // Child index, node and key
00668   unsigned char childIdx;
00669   const OctreeNode *childNode;
00670   OctreeKey childKey;
00671 
00672   do
00673   {
00674     if (currNode != 0)
00675       childIdx = static_cast<unsigned char> (currNode ^ a);
00676     else
00677       childIdx = a;
00678 
00679     // childNode == 0 if childNode doesn't exist
00680     childNode = this->getBranchChildPtr (static_cast<const BranchNode&> (*node), childIdx);
00681 
00682     // Generate new key for current branch voxel
00683     childKey.x = (key.x << 1) | (!!(childIdx & (1 << 2)));
00684     childKey.y = (key.y << 1) | (!!(childIdx & (1 << 1)));
00685     childKey.z = (key.z << 1) | (!!(childIdx & (1 << 0)));
00686 
00687     // Recursively call each intersected child node, selecting the next
00688     //   node intersected by the ray.  Children that do not intersect will
00689     //   not be traversed.
00690 
00691     switch (currNode)
00692     {
00693       case 0:
00694         if (childNode)
00695           voxelCount += getIntersectedVoxelCentersRecursive (minX, minY, minZ, midX, midY, midZ, a, childNode,
00696                                                              childKey, voxelCenterList, maxVoxelCount);
00697         currNode = getNextIntersectedNode (midX, midY, midZ, 4, 2, 1);
00698         break;
00699 
00700       case 1:
00701         if (childNode)
00702           voxelCount += getIntersectedVoxelCentersRecursive (minX, minY, midZ, midX, midY, maxZ, a, childNode,
00703                                                              childKey, voxelCenterList, maxVoxelCount);
00704         currNode = getNextIntersectedNode (midX, midY, maxZ, 5, 3, 8);
00705         break;
00706 
00707       case 2:
00708         if (childNode)
00709           voxelCount += getIntersectedVoxelCentersRecursive (minX, midY, minZ, midX, maxY, midZ, a, childNode,
00710                                                              childKey, voxelCenterList, maxVoxelCount);
00711         currNode = getNextIntersectedNode (midX, maxY, midZ, 6, 8, 3);
00712         break;
00713 
00714       case 3:
00715         if (childNode)
00716           voxelCount += getIntersectedVoxelCentersRecursive (minX, midY, midZ, midX, maxY, maxZ, a, childNode,
00717                                                              childKey, voxelCenterList, maxVoxelCount);
00718         currNode = getNextIntersectedNode (midX, maxY, maxZ, 7, 8, 8);
00719         break;
00720 
00721       case 4:
00722         if (childNode)
00723           voxelCount += getIntersectedVoxelCentersRecursive (midX, minY, minZ, maxX, midY, midZ, a, childNode,
00724                                                              childKey, voxelCenterList, maxVoxelCount);
00725         currNode = getNextIntersectedNode (maxX, midY, midZ, 8, 6, 5);
00726         break;
00727 
00728       case 5:
00729         if (childNode)
00730           voxelCount += getIntersectedVoxelCentersRecursive (midX, minY, midZ, maxX, midY, maxZ, a, childNode,
00731                                                              childKey, voxelCenterList, maxVoxelCount);
00732         currNode = getNextIntersectedNode (maxX, midY, maxZ, 8, 7, 8);
00733         break;
00734 
00735       case 6:
00736         if (childNode)
00737           voxelCount += getIntersectedVoxelCentersRecursive (midX, midY, minZ, maxX, maxY, midZ, a, childNode,
00738                                                              childKey, voxelCenterList, maxVoxelCount);
00739         currNode = getNextIntersectedNode (maxX, maxY, midZ, 8, 8, 7);
00740         break;
00741 
00742       case 7:
00743         if (childNode)
00744           voxelCount += getIntersectedVoxelCentersRecursive (midX, midY, midZ, maxX, maxY, maxZ, a, childNode,
00745                                                              childKey, voxelCenterList, maxVoxelCount);
00746         currNode = 8;
00747         break;
00748     }
00749   } while ((currNode < 8) && (maxVoxelCount <= 0 || voxelCount < maxVoxelCount));
00750   return (voxelCount);
00751 }
00752 
00754 template<typename PointT, typename LeafT, typename BranchT> int
00755 pcl::octree::OctreePointCloudSearch<PointT, LeafT, BranchT>::getIntersectedVoxelIndicesRecursive (
00756     double minX, double minY, double minZ, double maxX, double maxY, double maxZ, unsigned char a,
00757     const OctreeNode* node, const OctreeKey& key, std::vector<int> &k_indices, int maxVoxelCount) const
00758 {
00759   if (maxX < 0.0 || maxY < 0.0 || maxZ < 0.0)
00760     return (0);
00761 
00762   // If leaf node, get voxel center and increment intersection count
00763   if (node->getNodeType () == LEAF_NODE)
00764   {
00765     const LeafNode* leaf = static_cast<const LeafNode*> (node);
00766 
00767     // decode leaf node into k_indices
00768     leaf->getData (k_indices);
00769 
00770     return (1);
00771   }
00772 
00773   // Voxel intersection count for branches children
00774   int voxelCount = 0;
00775 
00776   // Voxel mid lines
00777   double midX = 0.5 * (minX + maxX);
00778   double midY = 0.5 * (minY + maxY);
00779   double midZ = 0.5 * (minZ + maxZ);
00780 
00781   // First voxel node ray will intersect
00782   int currNode = getFirstIntersectedNode (minX, minY, minZ, midX, midY, midZ);
00783 
00784   // Child index, node and key
00785   unsigned char childIdx;
00786   const OctreeNode *childNode;
00787   OctreeKey childKey;
00788   do
00789   {
00790     if (currNode != 0)
00791       childIdx = static_cast<unsigned char> (currNode ^ a);
00792     else
00793       childIdx = a;
00794 
00795     // childNode == 0 if childNode doesn't exist
00796     childNode = this->getBranchChildPtr (static_cast<const BranchNode&> (*node), childIdx);
00797     // Generate new key for current branch voxel
00798     childKey.x = (key.x << 1) | (!!(childIdx & (1 << 2)));
00799     childKey.y = (key.y << 1) | (!!(childIdx & (1 << 1)));
00800     childKey.z = (key.z << 1) | (!!(childIdx & (1 << 0)));
00801 
00802     // Recursively call each intersected child node, selecting the next
00803     //   node intersected by the ray.  Children that do not intersect will
00804     //   not be traversed.
00805     switch (currNode)
00806     {
00807       case 0:
00808         if (childNode)
00809           voxelCount += getIntersectedVoxelIndicesRecursive (minX, minY, minZ, midX, midY, midZ, a, childNode,
00810                                                              childKey, k_indices, maxVoxelCount);
00811         currNode = getNextIntersectedNode (midX, midY, midZ, 4, 2, 1);
00812         break;
00813 
00814       case 1:
00815         if (childNode)
00816           voxelCount += getIntersectedVoxelIndicesRecursive (minX, minY, midZ, midX, midY, maxZ, a, childNode,
00817                                                              childKey, k_indices, maxVoxelCount);
00818         currNode = getNextIntersectedNode (midX, midY, maxZ, 5, 3, 8);
00819         break;
00820 
00821       case 2:
00822         if (childNode)
00823           voxelCount += getIntersectedVoxelIndicesRecursive (minX, midY, minZ, midX, maxY, midZ, a, childNode,
00824                                                              childKey, k_indices, maxVoxelCount);
00825         currNode = getNextIntersectedNode (midX, maxY, midZ, 6, 8, 3);
00826         break;
00827 
00828       case 3:
00829         if (childNode)
00830           voxelCount += getIntersectedVoxelIndicesRecursive (minX, midY, midZ, midX, maxY, maxZ, a, childNode,
00831                                                              childKey, k_indices, maxVoxelCount);
00832         currNode = getNextIntersectedNode (midX, maxY, maxZ, 7, 8, 8);
00833         break;
00834 
00835       case 4:
00836         if (childNode)
00837           voxelCount += getIntersectedVoxelIndicesRecursive (midX, minY, minZ, maxX, midY, midZ, a, childNode,
00838                                                              childKey, k_indices, maxVoxelCount);
00839         currNode = getNextIntersectedNode (maxX, midY, midZ, 8, 6, 5);
00840         break;
00841 
00842       case 5:
00843         if (childNode)
00844           voxelCount += getIntersectedVoxelIndicesRecursive (midX, minY, midZ, maxX, midY, maxZ, a, childNode,
00845                                                              childKey, k_indices, maxVoxelCount);
00846         currNode = getNextIntersectedNode (maxX, midY, maxZ, 8, 7, 8);
00847         break;
00848 
00849       case 6:
00850         if (childNode)
00851           voxelCount += getIntersectedVoxelIndicesRecursive (midX, midY, minZ, maxX, maxY, midZ, a, childNode,
00852                                                              childKey, k_indices, maxVoxelCount);
00853         currNode = getNextIntersectedNode (maxX, maxY, midZ, 8, 8, 7);
00854         break;
00855 
00856       case 7:
00857         if (childNode)
00858           voxelCount += getIntersectedVoxelIndicesRecursive (midX, midY, midZ, maxX, maxY, maxZ, a, childNode,
00859                                                              childKey, k_indices, maxVoxelCount);
00860         currNode = 8;
00861         break;
00862     }
00863   } while ((currNode < 8) && (maxVoxelCount <= 0 || voxelCount < maxVoxelCount));
00864 
00865   return (voxelCount);
00866 }
00867 
00868 #endif    // PCL_OCTREE_SEARCH_IMPL_H_


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