|
|
#pragma once |
|
|
#include <nanoflann.hpp> |
|
|
#include <vector> |
|
|
#include <Eigen/Dense> |
|
|
#include <iostream> |
|
|
#include "Types.h" |
|
|
|
|
|
|
|
|
|
|
|
namespace nanoflann { |
|
|
|
|
|
|
|
|
|
|
|
template <class MatrixType, int DIM = -1, class Distance = nanoflann::metric_L2, typename IndexType = int> |
|
|
struct KDTreeAdaptor { |
|
|
typedef KDTreeAdaptor<MatrixType, DIM, Distance> self_t; |
|
|
typedef typename MatrixType::Scalar num_t; |
|
|
typedef typename Distance::template traits<num_t, self_t>::distance_t metric_t; |
|
|
typedef KDTreeSingleIndexAdaptor< metric_t, self_t, DIM, IndexType> index_t; |
|
|
|
|
|
index_t* index; |
|
|
const MatrixType &m_data_matrix; |
|
|
|
|
|
KDTreeAdaptor(const MatrixType &mat, const int leaf_max_size = 10) : m_data_matrix(mat) { |
|
|
const size_t dims = mat.rows(); |
|
|
index = new index_t(dims, *this, nanoflann::KDTreeSingleIndexAdaptorParams(leaf_max_size, dims)); |
|
|
index->buildIndex(); |
|
|
} |
|
|
|
|
|
~KDTreeAdaptor() { delete index; } |
|
|
|
|
|
|
|
|
inline void query(const num_t *query_point, const size_t num_closest, IndexType *out_indices, num_t *out_distances_sq) const { |
|
|
nanoflann::KNNResultSet<num_t, IndexType> resultSet(num_closest); |
|
|
resultSet.init(out_indices, out_distances_sq); |
|
|
index->findNeighbors(resultSet, query_point, nanoflann::SearchParams()); |
|
|
} |
|
|
|
|
|
|
|
|
inline IndexType closest(const num_t *query_point, num_t& out_distance_sq) const { |
|
|
IndexType out_index; |
|
|
query(query_point, 1, &out_index, &out_distance_sq); |
|
|
return out_index; |
|
|
} |
|
|
|
|
|
|
|
|
inline IndexType closest(const num_t *query_point) const { |
|
|
num_t dummy; |
|
|
return closest(query_point, dummy); |
|
|
} |
|
|
|
|
|
|
|
|
inline size_t findInRadius(const num_t *query_point, const num_t radius, std::vector<std::pair<IndexType, num_t>>& out_idxdist) const { |
|
|
out_idxdist.clear(); |
|
|
index->radiusSearch(query_point, radius, out_idxdist, nanoflann::SearchParams()); |
|
|
return out_idxdist.size(); |
|
|
} |
|
|
|
|
|
const self_t & derived() const { return *this; } |
|
|
self_t & derived() { return *this; } |
|
|
|
|
|
inline size_t kdtree_get_point_count() const { return m_data_matrix.cols(); } |
|
|
|
|
|
|
|
|
inline num_t kdtree_distance(const num_t *p1, const size_t idx_p2, size_t size) const { |
|
|
num_t s = 0; |
|
|
for (size_t i = 0; i < size; i++) { |
|
|
num_t d = p1[i] - m_data_matrix.coeff(i, idx_p2); |
|
|
s += d * d; |
|
|
} |
|
|
return s; |
|
|
} |
|
|
|
|
|
|
|
|
inline num_t kdtree_get_pt(const size_t idx, int dim) const { |
|
|
return m_data_matrix.coeff(dim, idx); |
|
|
} |
|
|
|
|
|
|
|
|
template <class BBOX> bool kdtree_get_bbox(BBOX&) const { return false; } |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
struct StdVecOfEigenVector3dRefAdapter { |
|
|
public: |
|
|
typedef double Scalar; |
|
|
typedef Eigen::Vector3d Vector3; |
|
|
|
|
|
StdVecOfEigenVector3dRefAdapter(const std::vector<Vector3>& pps) : pts(pps) {}; |
|
|
const std::vector<Vector3>& pts; |
|
|
|
|
|
inline size_t kdtree_get_point_count() const { return pts.size(); } |
|
|
|
|
|
inline Scalar kdtree_get_pt(const size_t idx, int dim) const { |
|
|
if (dim == 0) return pts[idx].x(); |
|
|
else if (dim == 1) return pts[idx].y(); |
|
|
else return pts[idx].z(); |
|
|
} |
|
|
|
|
|
template <class BBOX> |
|
|
bool kdtree_get_bbox(BBOX&) const { return false; } |
|
|
}; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
typedef nanoflann::KDTreeAdaptor<Matrix3X, -1, nanoflann::metric_L2_Simple> KDtree; |
|
|
|