39 #ifndef PCL_KDTREE_KDTREE_IMPL_FLANN_H_
40 #define PCL_KDTREE_KDTREE_IMPL_FLANN_H_
42 #include <flann/flann.hpp>
44 #include <pcl/kdtree/kdtree_flann.h>
45 #include <pcl/console/print.h>
48 template <
typename Po
intT,
typename Dist>
53 param_k_ (::
flann::SearchParams (-1 , epsilon_))
54 , param_radius_ (::
flann::SearchParams (-1, epsilon_, sorted))
56 if (!std::is_same<std::size_t, pcl::index_t>::value) {
57 const auto message =
"FLANN is not optimized for current index type. Will incur "
58 "extra allocations and copy\n";
59 if (std::is_same<int, pcl::index_t>::value) {
69 template <
typename Po
intT,
typename Dist>
74 param_k_ (::
flann::SearchParams (-1 , epsilon_))
75 , param_radius_ (::
flann::SearchParams (-1, epsilon_, false))
81 template <
typename Po
intT,
typename Dist>
void
85 param_k_ = ::flann::SearchParams (-1 , epsilon_);
86 param_radius_ = ::flann::SearchParams (-1 , epsilon_, sorted_);
90 template <
typename Po
intT,
typename Dist>
void
94 param_k_ = ::flann::SearchParams (-1, epsilon_);
95 param_radius_ = ::flann::SearchParams (-1, epsilon_, sorted_);
99 template <
typename Po
intT,
typename Dist>
void
105 dim_ = point_representation_->getNumberOfDimensions ();
113 PCL_ERROR (
"[pcl::KdTreeFLANN::setInputCloud] Invalid input!\n");
116 if (indices !=
nullptr)
118 convertCloudToArray (*input_, *indices_);
122 convertCloudToArray (*input_);
124 total_nr_points_ =
static_cast<uindex_t> (index_mapping_.size ());
125 if (total_nr_points_ == 0)
127 PCL_ERROR (
"[pcl::KdTreeFLANN::setInputCloud] Cannot create a KDTree with an empty input cloud!\n");
132 index_mapping_.size (),
134 ::flann::KDTreeSingleIndexParams (15)));
135 flann_index_->buildIndex ();
142 template <
class IndexT,
148 CompatWithFlann<IndexT> =
true>
150 knn_search(A& index,
B& query, C& k_indices, D& dists,
unsigned int k, F& params)
154 return index.knnSearch(query, k_indices_mat, dists, k, params);
157 template <
class IndexT,
163 NotCompatWithFlann<IndexT> =
true>
165 knn_search(A& index,
B& query, C& k_indices, D& dists,
unsigned int k, F& params)
167 std::vector<std::size_t> indices(k);
171 auto ret = index.knnSearch(query, indices_mat, dists, k, params);
173 std::transform(indices.cbegin(),
176 [](
const auto& x) { return static_cast<pcl::index_t>(x); });
180 template <
class IndexT,
class A,
class B,
class F, CompatWithFlann<IndexT> = true>
184 std::vector<Indices>& k_indices,
185 std::vector<std::vector<float>>& dists,
189 return index.knnSearch(query, k_indices, dists, k, params);
192 template <
class IndexT,
class A,
class B,
class F, NotCompatWithFlann<IndexT> = true>
196 std::vector<Indices>& k_indices,
197 std::vector<std::vector<float>>& dists,
201 std::vector<std::vector<std::size_t>> indices;
203 auto ret = index.knnSearch(query, indices, dists, k, params);
205 k_indices.resize(indices.size());
207 auto it = indices.cbegin();
208 auto jt = k_indices.begin();
209 for (; it != indices.cend(); ++it, ++jt) {
210 jt->resize(it->size());
211 std::copy(it->cbegin(), it->cend(), jt->begin());
217 template <
class FlannIndex,
228 const SearchParams& params)
230 return detail::knn_search<pcl::index_t>(index, query, indices, dists, k, params);
234 template <
typename Po
intT,
typename Dist>
int
237 std::vector<float> &k_distances)
const
239 assert (point_representation_->isValid (point) &&
"Invalid (NaN, Inf) point coordinates given to nearestKSearch!");
241 if (k > total_nr_points_)
242 k = total_nr_points_;
244 k_indices.resize (k);
245 k_distances.resize (k);
250 std::vector<float> query (dim_);
251 point_representation_->vectorize (
static_cast<PointT> (point), query);
264 if (!identity_mapping_)
266 for (std::size_t i = 0; i < static_cast<std::size_t> (k); ++i)
268 auto& neighbor_index = k_indices[i];
269 neighbor_index = index_mapping_[neighbor_index];
280 template <
class IndexT,
286 CompatWithFlann<IndexT> =
true>
288 radius_search(A& index,
B& query, C& k_indices, D& dists,
float radius, F& params)
290 std::vector<pcl::Indices> indices(1);
291 int neighbors_in_radius = index.radiusSearch(query, indices, dists, radius, params);
292 k_indices = std::move(indices[0]);
293 return neighbors_in_radius;
296 template <
class IndexT,
302 NotCompatWithFlann<IndexT> =
true>
304 radius_search(A& index,
B& query, C& k_indices, D& dists,
float radius, F& params)
306 std::vector<std::vector<std::size_t>> indices(1);
307 int neighbors_in_radius = index.radiusSearch(query, indices, dists, radius, params);
308 k_indices.resize(indices[0].size());
310 std::transform(indices[0].cbegin(),
313 [](
const auto& x) { return static_cast<pcl::index_t>(x); });
314 return neighbors_in_radius;
317 template <
class IndexT,
class A,
class B,
class F, CompatWithFlann<IndexT> = true>
321 std::vector<Indices>& k_indices,
322 std::vector<std::vector<float>>& dists,
326 return index.radiusSearch(query, k_indices, dists, radius, params);
329 template <
class IndexT,
class A,
class B,
class F, NotCompatWithFlann<IndexT> = true>
333 std::vector<Indices>& k_indices,
334 std::vector<std::vector<float>>& dists,
338 std::vector<std::vector<std::size_t>> indices;
340 auto ret = index.radiusSearch(query, indices, dists, radius, params);
342 k_indices.resize(indices.size());
344 auto it = indices.cbegin();
345 auto jt = k_indices.begin();
346 for (; it != indices.cend(); ++it, ++jt) {
347 jt->resize(it->size());
348 std::copy(it->cbegin(), it->cend(), jt->begin());
354 template <
class FlannIndex,
365 const SearchParams& params)
367 return detail::radius_search<pcl::index_t>(
368 index, query, indices, dists, radius, params);
372 template <
typename Po
intT,
typename Dist>
int
374 std::vector<float> &k_sqr_dists,
unsigned int max_nn)
const
376 assert (point_representation_->isValid (point) &&
"Invalid (NaN, Inf) point coordinates given to radiusSearch!");
378 std::vector<float> query (dim_);
379 point_representation_->vectorize (
static_cast<PointT> (point), query);
382 if (max_nn == 0 || max_nn > total_nr_points_)
383 max_nn = total_nr_points_;
385 std::vector<std::vector<float> > dists(1);
387 ::flann::SearchParams params (param_radius_);
388 if (max_nn == total_nr_points_)
389 params.max_neighbors = -1;
391 params.max_neighbors = max_nn;
398 static_cast<float>(radius * radius),
401 k_sqr_dists = dists[0];
404 if (!identity_mapping_)
406 for (
int i = 0; i < neighbors_in_radius; ++i)
408 auto& neighbor_index = k_indices[i];
409 neighbor_index = index_mapping_[neighbor_index];
413 return (neighbors_in_radius);
417 template <
typename Po
intT,
typename Dist>
void
421 index_mapping_.clear ();
428 template <
typename Po
intT,
typename Dist>
void
438 const auto original_no_of_points = cloud.
size ();
440 cloud_.reset (
new float[original_no_of_points * dim_], std::default_delete<
float[]> ());
441 float* cloud_ptr = cloud_.get ();
442 index_mapping_.reserve (original_no_of_points);
443 identity_mapping_ =
true;
445 for (std::size_t cloud_index = 0; cloud_index < original_no_of_points; ++cloud_index)
448 if (!point_representation_->isValid (cloud[cloud_index]))
450 identity_mapping_ =
false;
454 index_mapping_.push_back (cloud_index);
456 point_representation_->vectorize (cloud[cloud_index], cloud_ptr);
462 template <
typename Po
intT,
typename Dist>
void
472 int original_no_of_points =
static_cast<int> (indices.size ());
474 cloud_.reset (
new float[original_no_of_points * dim_], std::default_delete<
float[]> ());
475 float* cloud_ptr = cloud_.get ();
476 index_mapping_.reserve (original_no_of_points);
484 identity_mapping_ =
false;
486 for (
const auto &index : indices)
489 if (!point_representation_->isValid (cloud[index]))
493 index_mapping_.push_back (index);
495 point_representation_->vectorize (cloud[index], cloud_ptr);
500 #define PCL_INSTANTIATE_KdTreeFLANN(T) template class PCL_EXPORTS pcl::KdTreeFLANN<T>;
KdTreeFLANN is a generic type of 3D spatial locator using kD-tree structures.
void setEpsilon(float eps) override
Set the search epsilon precision (error bound) for nearest neighbors searches.
int nearestKSearch(const PointT &point, unsigned int k, Indices &k_indices, std::vector< float > &k_sqr_distances) const override
Search for k-nearest neighbors for the given query point.
int radiusSearch(const PointT &point, double radius, Indices &k_indices, std::vector< float > &k_sqr_distances, unsigned int max_nn=0) const override
Search for all the nearest neighbors of the query point in a given radius.
void setSortedResults(bool sorted)
KdTreeFLANN(bool sorted=true)
Default Constructor for KdTreeFLANN.
void setInputCloud(const PointCloudConstPtr &cloud, const IndicesConstPtr &indices=IndicesConstPtr()) override
Provide a pointer to the input dataset.
KdTree represents the base spatial locator class for kd-tree implementations.
shared_ptr< const Indices > IndicesConstPtr
typename PointCloud::ConstPtr PointCloudConstPtr
PointCloud represents the base class in PCL for storing collections of 3D points.
int knn_search(A &index, B &query, C &k_indices, D &dists, unsigned int k, F ¶ms)
int radius_search(A &index, B &query, C &k_indices, D &dists, float radius, F ¶ms)
detail::int_type_t< detail::index_type_size, false > uindex_t
Type used for an unsigned index in PCL.
IndicesAllocator<> Indices
Type used for indices in PCL.
int radius_search(const FlannIndex &index, const Query &query, Indices &indices, Distances &dists, float radius, const SearchParams ¶ms)
Compatibility template function to allow use of various types of indices with FLANN.
int knn_search(const FlannIndex &index, const Query &query, Indices &indices, Distances &dists, unsigned int k, const SearchParams ¶ms)
Compatibility template function to allow use of various types of indices with FLANN.
A point structure representing Euclidean xyz coordinates, and the RGB color.