|
Point Cloud Library (PCL)
1.5.1
|
00001 /* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Point Cloud Library (PCL) - www.pointclouds.org 00005 * Copyright (c) 2009-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 */ 00037 00038 #ifndef PCL_KDTREE_KDTREE_IMPL_FLANN_H_ 00039 #define PCL_KDTREE_KDTREE_IMPL_FLANN_H_ 00040 00041 #include <pcl/kdtree/kdtree_flann.h> 00042 #include <pcl/console/print.h> 00043 00045 template <typename PointT, typename Dist> void 00046 pcl::KdTreeFLANN<PointT, Dist>::setInputCloud (const PointCloudConstPtr &cloud, const IndicesConstPtr &indices) 00047 { 00048 cleanup (); // Perform an automatic cleanup of structures 00049 00050 epsilon_ = 0.0; // default error bound value 00051 dim_ = point_representation_->getNumberOfDimensions (); // Number of dimensions - default is 3 = xyz 00052 00053 input_ = cloud; 00054 indices_ = indices; 00055 00056 // Allocate enough data 00057 if (!input_) 00058 { 00059 PCL_ERROR ("[pcl::KdTreeFLANN::setInputCloud] Invalid input!\n"); 00060 return; 00061 } 00062 if (indices != NULL) 00063 { 00064 total_nr_points_ = (int) indices_->size (); 00065 convertCloudToArray (*input_, *indices_); 00066 } 00067 else 00068 { 00069 total_nr_points_ = (int) input_->points.size (); 00070 convertCloudToArray (*input_); 00071 } 00072 00073 flann_index_ = new FLANNIndex (flann::Matrix<float> (cloud_, index_mapping_.size (), dim_), 00074 flann::KDTreeSingleIndexParams (15)); // max 15 points/leaf 00075 flann_index_->buildIndex (); 00076 } 00077 00079 template <typename PointT, typename Dist> int 00080 pcl::KdTreeFLANN<PointT, Dist>::nearestKSearch (const PointT &point, int k, 00081 std::vector<int> &k_indices, 00082 std::vector<float> &k_distances) const 00083 { 00084 assert (point_representation_->isValid (point) && "Invalid (NaN, Inf) point coordinates given to nearestKSearch!"); 00085 00086 if (k > total_nr_points_) 00087 { 00088 PCL_ERROR ("[pcl::KdTreeFLANN::nearestKSearch] An invalid number of nearest neighbors was requested! (k = %d out of %d total points).\n", k, total_nr_points_); 00089 k = total_nr_points_; 00090 } 00091 00092 k_indices.resize (k); 00093 k_distances.resize (k); 00094 00095 std::vector<float> query (dim_); 00096 point_representation_->vectorize ((PointT)point, query); 00097 00098 flann::Matrix<int> k_indices_mat (&k_indices[0], 1, k); 00099 flann::Matrix<float> k_distances_mat (&k_distances[0], 1, k); 00100 // Wrap the k_indices and k_distances vectors (no data copy) 00101 flann_index_->knnSearch (flann::Matrix<float> (&query[0], 1, dim_), 00102 k_indices_mat, k_distances_mat, 00103 k, param_k_); 00104 00105 // Do mapping to original point cloud 00106 if (!identity_mapping_) 00107 { 00108 for (size_t i = 0; i < (size_t)k; ++i) 00109 { 00110 int& neighbor_index = k_indices[i]; 00111 neighbor_index = index_mapping_[neighbor_index]; 00112 } 00113 } 00114 00115 return (k); 00116 } 00117 00119 template <typename PointT, typename Dist> int 00120 pcl::KdTreeFLANN<PointT, Dist>::radiusSearch (const PointT &point, double radius, std::vector<int> &k_indices, 00121 std::vector<float> &k_sqr_dists, unsigned int max_nn) const 00122 { 00123 assert (point_representation_->isValid (point) && "Invalid (NaN, Inf) point coordinates given to radiusSearch!"); 00124 00125 std::vector<float> query (dim_); 00126 point_representation_->vectorize ((PointT)point, query); 00127 00128 int neighbors_in_radius = 0; 00129 00130 // If the user pre-allocated the arrays, we are only going to 00131 if (k_indices.size () == (size_t)total_nr_points_ && k_sqr_dists.size () == (size_t)total_nr_points_) 00132 { 00133 flann::Matrix<int> k_indices_mat (&k_indices[0], 1, k_indices.size ()); 00134 flann::Matrix<float> k_distances_mat (&k_sqr_dists[0], 1, k_sqr_dists.size ()); 00135 neighbors_in_radius = flann_index_->radiusSearch (flann::Matrix<float> (&query[0], 1, dim_), 00136 k_indices_mat, 00137 k_distances_mat, 00138 (float) (radius * radius), 00139 param_radius_); 00140 } 00141 else 00142 { 00143 // Has max_nn been set properly? 00144 if (max_nn == 0 || max_nn > (unsigned int)total_nr_points_) 00145 max_nn = total_nr_points_; 00146 00147 static flann::Matrix<int> indices_empty; 00148 static flann::Matrix<float> dists_empty; 00149 neighbors_in_radius = flann_index_->radiusSearch (flann::Matrix<float> (&query[0], 1, dim_), 00150 indices_empty, 00151 dists_empty, 00152 (float) (radius * radius), 00153 param_radius_); 00154 neighbors_in_radius = std::min ((unsigned int)neighbors_in_radius, max_nn); 00155 00156 k_indices.resize (neighbors_in_radius); 00157 k_sqr_dists.resize (neighbors_in_radius); 00158 if(neighbors_in_radius != 0) 00159 { 00160 flann::Matrix<int> k_indices_mat (&k_indices[0], 1, k_indices.size ()); 00161 flann::Matrix<float> k_distances_mat (&k_sqr_dists[0], 1, k_sqr_dists.size ()); 00162 flann_index_->radiusSearch (flann::Matrix<float> (&query[0], 1, dim_), 00163 k_indices_mat, 00164 k_distances_mat, 00165 (float) (radius * radius), 00166 param_radius_); 00167 } 00168 } 00169 00170 // Do mapping to original point cloud 00171 if (!identity_mapping_) 00172 { 00173 for (int i = 0; i < neighbors_in_radius; ++i) 00174 { 00175 int& neighbor_index = k_indices[i]; 00176 neighbor_index = index_mapping_[neighbor_index]; 00177 } 00178 } 00179 00180 return (neighbors_in_radius); 00181 } 00182 00184 template <typename PointT, typename Dist> void 00185 pcl::KdTreeFLANN<PointT, Dist>::cleanup () 00186 { 00187 if (flann_index_) 00188 delete flann_index_; 00189 00190 // Data array cleanup 00191 if (cloud_) 00192 { 00193 free (cloud_); 00194 cloud_ = NULL; 00195 } 00196 index_mapping_.clear (); 00197 00198 if (indices_) 00199 indices_.reset (); 00200 } 00201 00203 template <typename PointT, typename Dist> void 00204 pcl::KdTreeFLANN<PointT, Dist>::convertCloudToArray (const PointCloud &cloud) 00205 { 00206 // No point in doing anything if the array is empty 00207 if (cloud.points.empty ()) 00208 { 00209 cloud_ = NULL; 00210 return; 00211 } 00212 00213 int original_no_of_points = (int) cloud.points.size (); 00214 00215 cloud_ = (float*)malloc (original_no_of_points * dim_ * sizeof(float)); 00216 float* cloud_ptr = cloud_; 00217 index_mapping_.reserve (original_no_of_points); 00218 identity_mapping_ = true; 00219 00220 for (int cloud_index = 0; cloud_index < original_no_of_points; ++cloud_index) 00221 { 00222 // Check if the point is invalid 00223 if (!point_representation_->isValid (cloud.points[cloud_index])) 00224 { 00225 identity_mapping_ = false; 00226 continue; 00227 } 00228 00229 index_mapping_.push_back (cloud_index); 00230 00231 point_representation_->vectorize (cloud.points[cloud_index], cloud_ptr); 00232 cloud_ptr += dim_; 00233 } 00234 } 00235 00237 template <typename PointT, typename Dist> void 00238 pcl::KdTreeFLANN<PointT, Dist>::convertCloudToArray (const PointCloud &cloud, const std::vector<int> &indices) 00239 { 00240 // No point in doing anything if the array is empty 00241 if (cloud.points.empty ()) 00242 { 00243 cloud_ = NULL; 00244 return; 00245 } 00246 00247 int original_no_of_points = (int) indices.size (); 00248 00249 cloud_ = (float*)malloc (original_no_of_points * dim_ * sizeof (float)); 00250 float* cloud_ptr = cloud_; 00251 index_mapping_.reserve (original_no_of_points); 00252 00253 // true only identity: 00254 // - indices size equals cloud size 00255 // - indices only contain values between 0 and cloud.size - 1 00256 // - no index is multiple times in the list 00257 // => index is complete 00258 // But we can not guarantee that => identity_mapping_ = false 00259 identity_mapping_ = false; 00260 00261 for (std::vector<int>::const_iterator iIt = indices.begin (); iIt != indices.end (); ++iIt) 00262 { 00263 // Check if the point is invalid 00264 if (!point_representation_->isValid (cloud.points[*iIt])) 00265 continue; 00266 00267 00268 index_mapping_.push_back (*iIt); // If the returned index should be for the indices vector 00269 00270 point_representation_->vectorize (cloud.points[*iIt], cloud_ptr); 00271 cloud_ptr += dim_; 00272 } 00273 } 00274 00275 #define PCL_INSTANTIATE_KdTreeFLANN(T) template class PCL_EXPORTS pcl::KdTreeFLANN<T>; 00276 00277 #endif //#ifndef _PCL_KDTREE_KDTREE_IMPL_FLANN_H_ 00278
1.8.0