Point Cloud Library (PCL)  1.6.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
kdtree_flann.hpp
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2009-2011, Willow Garage, Inc.
6  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  * * Neither the name of Willow Garage, Inc. nor the names of its
20  * contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  */
37 
38 #ifndef PCL_KDTREE_KDTREE_IMPL_FLANN_H_
39 #define PCL_KDTREE_KDTREE_IMPL_FLANN_H_
40 
42 #include <pcl/console/print.h>
43 
45 template <typename PointT, typename Dist> void
47 {
48  cleanup (); // Perform an automatic cleanup of structures
49 
50  epsilon_ = 0.0f; // default error bound value
51  dim_ = point_representation_->getNumberOfDimensions (); // Number of dimensions - default is 3 = xyz
52 
53  input_ = cloud;
54  indices_ = indices;
55 
56  // Allocate enough data
57  if (!input_)
58  {
59  PCL_ERROR ("[pcl::KdTreeFLANN::setInputCloud] Invalid input!\n");
60  return;
61  }
62  if (indices != NULL)
63  {
64  convertCloudToArray (*input_, *indices_);
65  }
66  else
67  {
68  convertCloudToArray (*input_);
69  }
70  total_nr_points_ = static_cast<int> (index_mapping_.size ());
71 
72  flann_index_ = new FLANNIndex (flann::Matrix<float> (cloud_, index_mapping_.size (), dim_),
73  flann::KDTreeSingleIndexParams (15)); // max 15 points/leaf
74  flann_index_->buildIndex ();
75 }
76 
78 template <typename PointT, typename Dist> int
80  std::vector<int> &k_indices,
81  std::vector<float> &k_distances) const
82 {
83  assert (point_representation_->isValid (point) && "Invalid (NaN, Inf) point coordinates given to nearestKSearch!");
84 
85  if (k > total_nr_points_)
86  k = total_nr_points_;
87 
88  k_indices.resize (k);
89  k_distances.resize (k);
90 
91  std::vector<float> query (dim_);
92  point_representation_->vectorize (static_cast<PointT> (point), query);
93 
94  flann::Matrix<int> k_indices_mat (&k_indices[0], 1, k);
95  flann::Matrix<float> k_distances_mat (&k_distances[0], 1, k);
96  // Wrap the k_indices and k_distances vectors (no data copy)
97  flann_index_->knnSearch (flann::Matrix<float> (&query[0], 1, dim_),
98  k_indices_mat, k_distances_mat,
99  k, param_k_);
100 
101  // Do mapping to original point cloud
102  if (!identity_mapping_)
103  {
104  for (size_t i = 0; i < static_cast<size_t> (k); ++i)
105  {
106  int& neighbor_index = k_indices[i];
107  neighbor_index = index_mapping_[neighbor_index];
108  }
109  }
110 
111  return (k);
112 }
113 
115 template <typename PointT, typename Dist> int
116 pcl::KdTreeFLANN<PointT, Dist>::radiusSearch (const PointT &point, double radius, std::vector<int> &k_indices,
117  std::vector<float> &k_sqr_dists, unsigned int max_nn) const
118 {
119  assert (point_representation_->isValid (point) && "Invalid (NaN, Inf) point coordinates given to radiusSearch!");
120 
121  std::vector<float> query (dim_);
122  point_representation_->vectorize (static_cast<PointT> (point), query);
123 
124  // Has max_nn been set properly?
125  if (max_nn == 0 || max_nn > static_cast<unsigned int> (total_nr_points_))
126  max_nn = total_nr_points_;
127 
128  std::vector<std::vector<int> > indices(1);
129  std::vector<std::vector<float> > dists(1);
130 
131  flann::SearchParams params(param_radius_);
132  if (max_nn == static_cast<unsigned int>(total_nr_points_))
133  params.max_neighbors = -1; // return all neighbors in radius
134  else
135  params.max_neighbors = max_nn;
136 
137  int neighbors_in_radius = flann_index_->radiusSearch (flann::Matrix<float> (&query[0], 1, dim_),
138  indices,
139  dists,
140  static_cast<float> (radius * radius),
141  params);
142 
143  k_indices = indices[0];
144  k_sqr_dists = dists[0];
145 
146  // Do mapping to original point cloud
147  if (!identity_mapping_)
148  {
149  for (int i = 0; i < neighbors_in_radius; ++i)
150  {
151  int& neighbor_index = k_indices[i];
152  neighbor_index = index_mapping_[neighbor_index];
153  }
154  }
155 
156  return (neighbors_in_radius);
157 }
158 
160 template <typename PointT, typename Dist> void
162 {
163  if (flann_index_)
164  delete flann_index_;
165 
166  // Data array cleanup
167  if (cloud_)
168  {
169  free (cloud_);
170  cloud_ = NULL;
171  }
172  index_mapping_.clear ();
173 
174  if (indices_)
175  indices_.reset ();
176 }
177 
179 template <typename PointT, typename Dist> void
181 {
182  // No point in doing anything if the array is empty
183  if (cloud.points.empty ())
184  {
185  cloud_ = NULL;
186  return;
187  }
188 
189  int original_no_of_points = static_cast<int> (cloud.points.size ());
190 
191  cloud_ = static_cast<float*> (malloc (original_no_of_points * dim_ * sizeof (float)));
192  float* cloud_ptr = cloud_;
193  index_mapping_.reserve (original_no_of_points);
194  identity_mapping_ = true;
195 
196  for (int cloud_index = 0; cloud_index < original_no_of_points; ++cloud_index)
197  {
198  // Check if the point is invalid
199  if (!point_representation_->isValid (cloud.points[cloud_index]))
200  {
201  identity_mapping_ = false;
202  continue;
203  }
204 
205  index_mapping_.push_back (cloud_index);
206 
207  point_representation_->vectorize (cloud.points[cloud_index], cloud_ptr);
208  cloud_ptr += dim_;
209  }
210 }
211 
213 template <typename PointT, typename Dist> void
214 pcl::KdTreeFLANN<PointT, Dist>::convertCloudToArray (const PointCloud &cloud, const std::vector<int> &indices)
215 {
216  // No point in doing anything if the array is empty
217  if (cloud.points.empty ())
218  {
219  cloud_ = NULL;
220  return;
221  }
222 
223  int original_no_of_points = static_cast<int> (indices.size ());
224 
225  cloud_ = static_cast<float*> (malloc (original_no_of_points * dim_ * sizeof (float)));
226  float* cloud_ptr = cloud_;
227  index_mapping_.reserve (original_no_of_points);
228  // its a subcloud -> false
229  // true only identity:
230  // - indices size equals cloud size
231  // - indices only contain values between 0 and cloud.size - 1
232  // - no index is multiple times in the list
233  // => index is complete
234  // But we can not guarantee that => identity_mapping_ = false
235  identity_mapping_ = false;
236 
237  for (std::vector<int>::const_iterator iIt = indices.begin (); iIt != indices.end (); ++iIt)
238  {
239  // Check if the point is invalid
240  if (!point_representation_->isValid (cloud.points[*iIt]))
241  continue;
242 
243  // map from 0 - N -> indices [0] - indices [N]
244  index_mapping_.push_back (*iIt); // If the returned index should be for the indices vector
245 
246  point_representation_->vectorize (cloud.points[*iIt], cloud_ptr);
247  cloud_ptr += dim_;
248  }
249 }
250 
251 #define PCL_INSTANTIATE_KdTreeFLANN(T) template class PCL_EXPORTS pcl::KdTreeFLANN<T>;
252 
253 #endif //#ifndef _PCL_KDTREE_KDTREE_IMPL_FLANN_H_
254