Point Cloud Library (PCL)  1.5.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
octree_search.h
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.h 4702 2012-02-23 09:39:33Z gedikli $
00037  */
00038 
00039 #ifndef PCL_OCTREE_SEARCH_H_
00040 #define PCL_OCTREE_SEARCH_H_
00041 
00042 #include <pcl/point_cloud.h>
00043 #include <pcl/point_types.h>
00044 
00045 #include "octree_pointcloud.h"
00046 
00047 #include "octree_base.h"
00048 #include "octree2buf_base.h"
00049 
00050 #include "octree_nodes.h"
00051 
00052 namespace pcl
00053 {
00054   namespace octree
00055   {
00062     template<typename PointT, typename LeafT = OctreeLeafDataTVector<int> , typename OctreeT = OctreeBase<int, LeafT> >
00063     class OctreePointCloudSearch : public OctreePointCloud<PointT, LeafT, OctreeT>
00064     {
00065       public:
00066         // public typedefs
00067         typedef boost::shared_ptr<std::vector<int> > IndicesPtr;
00068         typedef boost::shared_ptr<const std::vector<int> > IndicesConstPtr;
00069 
00070         typedef pcl::PointCloud<PointT> PointCloud;
00071         typedef boost::shared_ptr<PointCloud> PointCloudPtr;
00072         typedef boost::shared_ptr<const PointCloud> PointCloudConstPtr;
00073 
00074         // public typedefs for single/double buffering
00075         typedef OctreePointCloudSearch<PointT, LeafT, OctreeBase<int, LeafT> > SingleBuffer;
00076         typedef OctreePointCloudSearch<PointT, LeafT, Octree2BufBase<int, LeafT> > DoubleBuffer;
00077         typedef OctreePointCloudSearch<PointT, LeafT, OctreeLowMemBase<int, LeafT> > LowMem;
00078 
00079         // Boost shared pointers
00080         typedef boost::shared_ptr<OctreePointCloudSearch<PointT, LeafT, OctreeT> > Ptr;
00081         typedef boost::shared_ptr<const OctreePointCloudSearch<PointT, LeafT, OctreeT> > ConstPtr;
00082 
00083         // Eigen aligned allocator
00084         typedef std::vector<PointT, Eigen::aligned_allocator<PointT> > AlignedPointTVector;
00085 
00086         typedef typename OctreeT::OctreeBranch OctreeBranch;
00087         typedef typename OctreeT::OctreeKey OctreeKey;
00088         typedef typename OctreeT::OctreeLeaf OctreeLeaf;
00089 
00093         OctreePointCloudSearch (const double resolution) :
00094           OctreePointCloud<PointT, LeafT, OctreeT> (resolution)
00095         {
00096         }
00097 
00099         virtual
00100         ~OctreePointCloudSearch ()
00101         {
00102         }
00103 
00109         bool
00110         voxelSearch (const PointT& point, std::vector<int>& pointIdx_data);
00111 
00117         bool
00118         voxelSearch (const int index, std::vector<int>& pointIdx_data);
00119 
00129         inline int
00130         nearestKSearch (const PointCloud &cloud, int index, int k, std::vector<int> &k_indices,
00131                         std::vector<float> &k_sqr_distances)
00132         {
00133           return (nearestKSearch (cloud[index], k, k_indices, k_sqr_distances));
00134         }
00135 
00143         int
00144         nearestKSearch (const PointT &p_q, int k, std::vector<int> &k_indices,
00145                         std::vector<float> &k_sqr_distances);
00146 
00156         int
00157         nearestKSearch (int index, int k, std::vector<int> &k_indices,
00158                         std::vector<float> &k_sqr_distances);
00159 
00167         inline void
00168         approxNearestSearch (const PointCloud &cloud, int query_index, int &result_index,
00169                              float &sqr_distance)
00170         {
00171           return (approxNearestSearch (cloud.points[query_index], result_index, sqr_distance));
00172         }
00173 
00179         void
00180         approxNearestSearch (const PointT &p_q, int &result_index, float &sqr_distance);
00181 
00189         void
00190         approxNearestSearch (int query_index, int &result_index, float &sqr_distance);
00191 
00201         int
00202         radiusSearch (const PointCloud &cloud, int index, double radius,
00203                       std::vector<int> &k_indices, std::vector<float> &k_sqr_distances,
00204                       unsigned int max_nn = 0)
00205         {
00206           return (radiusSearch (cloud.points[index], radius, k_indices, k_sqr_distances, max_nn));
00207         }
00208 
00217         int
00218         radiusSearch (const PointT &p_q, const double radius, std::vector<int> &k_indices,
00219                       std::vector<float> &k_sqr_distances, unsigned int max_nn = 0) const;
00220 
00230         int
00231         radiusSearch (int index, const double radius, std::vector<int> &k_indices,
00232                       std::vector<float> &k_sqr_distances, unsigned int max_nn = 0) const;
00233 
00240         int
00241         getIntersectedVoxelCenters (Eigen::Vector3f origin, Eigen::Vector3f direction,
00242                                     AlignedPointTVector &voxelCenterList) const;
00243 
00250         int
00251         getIntersectedVoxelIndices (Eigen::Vector3f origin, Eigen::Vector3f direction,
00252                                     std::vector<int> &k_indices) const;
00253 
00254 
00261         int
00262         boxSearch (const Eigen::Vector3f &min_pt, const Eigen::Vector3f &max_pt, std::vector<int> &k_indices) const;
00263 
00264       protected:
00266         // Octree-based search routines & helpers
00268 
00272         class prioBranchQueueEntry
00273         {
00274           public:
00276             prioBranchQueueEntry ()
00277             {
00278             }
00279 
00285             prioBranchQueueEntry (OctreeNode* node, OctreeKey& key, float pointDistance)
00286             {
00287               node = node;
00288               pointDistance = pointDistance;
00289               key = key;
00290             }
00291 
00295             bool
00296             operator< (const prioBranchQueueEntry rhs) const
00297             {
00298               return (this->pointDistance > rhs.pointDistance);
00299             }
00300 
00302             const OctreeNode* node;
00303 
00305             float pointDistance;
00306 
00308             OctreeKey key;
00309         };
00310 
00312 
00316         class prioPointQueueEntry
00317         {
00318           public:
00319 
00321             prioPointQueueEntry ()
00322             {
00323             }
00324 
00329             prioPointQueueEntry (unsigned int& pointIdx, float pointDistance)
00330             {
00331               pointIdx_ = pointIdx;
00332               pointDistance_ = pointDistance;
00333             }
00334 
00338             bool
00339             operator< (const prioPointQueueEntry& rhs) const
00340             {
00341               return (this->pointDistance_ < rhs.pointDistance_);
00342             }
00343 
00345             int pointIdx_;
00346 
00348             float pointDistance_;
00349         };
00350 
00356         float
00357         pointSquaredDist (const PointT& pointA, const PointT& pointB) const;
00358 
00360         // Recursive search routine methods
00362 
00373         void
00374         getNeighborsWithinRadiusRecursive (const PointT& point, const double radiusSquared,
00375                                            const OctreeBranch* node, const OctreeKey& key,
00376                                            unsigned int treeDepth, std::vector<int>& k_indices,
00377                                            std::vector<float>& k_sqr_distances, unsigned int max_nn) const;
00378 
00389         double
00390         getKNearestNeighborRecursive (const PointT& point, unsigned int K, const OctreeBranch* node,
00391                                       const OctreeKey& key, unsigned int treeDepth,
00392                                       const double squaredSearchRadius,
00393                                       std::vector<prioPointQueueEntry>& pointCandidates) const;
00394 
00403         void
00404         approxNearestSearchRecursive (const PointT& point, const OctreeBranch* node, const OctreeKey& key,
00405                                       unsigned int treeDepth, int& result_index, float& sqr_distance);
00406 
00422         int
00423         getIntersectedVoxelCentersRecursive (double minX, double minY, double minZ, double maxX, double maxY,
00424                                              double maxZ, unsigned char a, const OctreeNode* node,
00425                                              const OctreeKey& key, AlignedPointTVector &voxelCenterList) const;
00426 
00427 
00436         void
00437         boxSearchRecursive (const Eigen::Vector3f &min_pt, const Eigen::Vector3f &max_pt, const OctreeBranch* node,
00438                             const OctreeKey& key, unsigned int treeDepth, std::vector<int>& k_indices) const;
00439 
00455         int
00456         getIntersectedVoxelIndicesRecursive (double minX, double minY, double minZ,
00457                                              double maxX, double maxY, double maxZ,
00458                                              unsigned char a, const OctreeNode* node, const OctreeKey& key,
00459                                              std::vector<int> &k_indices) const;
00460 
00472         inline void
00473         initIntersectedVoxel (Eigen::Vector3f &origin, Eigen::Vector3f &direction,
00474                               double &minX, double &minY, double &minZ,
00475                               double &maxX, double &maxY, double &maxZ,
00476                               unsigned char &a) const
00477         {
00478           // Account for division by zero when direction vector is 0.0
00479           const float epsilon = 1e-10;
00480           if (direction.x () == 0.0)
00481             direction.x () = epsilon;
00482           if (direction.y () == 0.0)
00483             direction.y () = epsilon;
00484           if (direction.z () == 0.0)
00485             direction.z () = epsilon;
00486 
00487           // Voxel childIdx remapping
00488           a = 0;
00489 
00490           // Handle negative axis direction vector
00491           if (direction.x () < 0.0)
00492           {
00493             origin.x () = (float)this->minX_ + (float)this->maxX_ - origin.x ();
00494             direction.x () = -direction.x ();
00495             a |= 4;
00496           }
00497           if (direction.y () < 0.0)
00498           {
00499             origin.y () = (float)this->minY_ + (float)this->maxY_ - origin.y ();
00500             direction.y () = -direction.y ();
00501             a |= 2;
00502           }
00503           if (direction.z () < 0.0)
00504           {
00505             origin.z () = (float)this->minZ_ + (float)this->maxZ_ - origin.z ();
00506             direction.z () = -direction.z ();
00507             a |= 1;
00508           }
00509           minX = (this->minX_ - origin.x ()) / direction.x ();
00510           maxX = (this->maxX_ - origin.x ()) / direction.x ();
00511           minY = (this->minY_ - origin.y ()) / direction.y ();
00512           maxY = (this->maxY_ - origin.y ()) / direction.y ();
00513           minZ = (this->minZ_ - origin.z ()) / direction.z ();
00514           maxZ = (this->maxZ_ - origin.z ()) / direction.z ();
00515         }
00516 
00526         inline int
00527         getFirstIntersectedNode (double minX, double minY, double minZ, double midX, double midY, double midZ) const
00528         {
00529           int currNode = 0;
00530 
00531           if (minX > minY)
00532           {
00533             if (minX > minZ)
00534             {
00535               // max(minX, minY, minZ) is minX. Entry plane is YZ.
00536               if (midY < minX)
00537                 currNode |= 2;
00538               if (midZ < minX)
00539                 currNode |= 1;
00540             }
00541             else
00542             {
00543               // max(minX, minY, minZ) is minZ. Entry plane is XY.
00544               if (midX < minZ)
00545                 currNode |= 4;
00546               if (midY < minZ)
00547                 currNode |= 2;
00548             }
00549           }
00550           else
00551           {
00552             if (minY > minZ)
00553             {
00554               // max(minX, minY, minZ) is minY. Entry plane is XZ.
00555               if (midX < minY)
00556                 currNode |= 4;
00557               if (midZ < minY)
00558                 currNode |= 1;
00559             }
00560             else
00561             {
00562               // max(minX, minY, minZ) is minZ. Entry plane is XY.
00563               if (midX < minZ)
00564                 currNode |= 4;
00565               if (midY < minZ)
00566                 currNode |= 2;
00567             }
00568           }
00569 
00570           return currNode;
00571         }
00572 
00585         inline int
00586         getNextIntersectedNode (double x, double y, double z, int a, int b, int c) const
00587         {
00588           if (x < y)
00589           {
00590             if (x < z)
00591               return a;
00592             else
00593               return c;
00594           }
00595           else
00596           {
00597             if (y < z)
00598               return b;
00599             else
00600               return c;
00601           }
00602 
00603           return 0;
00604         }
00605 
00606       };
00607   }
00608 }
00609 
00610 #define PCL_INSTANTIATE_OctreePointCloudSearch(T) template class PCL_EXPORTS pcl::octree::OctreePointCloudSearch<T>;
00611 
00612 #endif    // PCL_OCTREE_SEARCH_H_