31 #ifndef FLANN_NNINDEX_H
32 #define FLANN_NNINDEX_H
46 #define KNN_HEAP_THRESHOLD 250
56 virtual size_t size()
const = 0;
72 template <
typename Distance>
106 for (
size_t i=0;i<
size_;++i) {
154 throw FLANNException(
"Functionality not supported by this index");
165 for (
size_t i=0;i<
size_;++i) {
190 if (index!=
size_t(-1)) {
225 template<
typename Archive>
230 if (Archive::is_saving::value) {
239 if (Archive::is_loading::value) {
247 throw FLANNException(
"Datatype of saved index is different than of the one to be created.");
251 throw FLANNException(
"Saved index type is different then the current index type.");
262 if (Archive::is_saving::value) {
268 if (Archive::is_loading::value) {
274 for (
size_t i=0;i<
size_;++i) {
278 for (
size_t i=0;i<
size_;++i) {
283 throw FLANNException(
"Saved index does not contain the dataset and no dataset was provided.");
312 assert(indices.
rows >= queries.
rows);
314 assert(indices.
cols >= knn);
315 assert(dists.
cols >= knn);
327 #pragma omp parallel num_threads(params.cores)
330 #pragma omp for schedule(dynamic) reduction(+:count)
331 for (
int i = 0; i < (int)queries.
rows; i++) {
335 resultSet.
copy(indices[i], dists[i], n,
params.sorted);
342 #pragma omp parallel num_threads(params.cores)
345 #pragma omp for schedule(dynamic) reduction(+:count)
346 for (
int i = 0; i < (int)queries.
rows; i++) {
350 resultSet.
copy(indices[i], dists[i], n,
params.sorted);
377 for (
size_t i=0;i<indices.
rows;++i) {
378 for (
size_t j=0;j<indices.
cols;++j) {
379 indices[i][j] = indices_[i][j];
382 delete[] indices_.
ptr();
396 std::vector< std::vector<size_t> >& indices,
397 std::vector<std::vector<DistanceType> >& dists,
410 if (indices.size() < queries.
rows ) indices.resize(queries.
rows);
411 if (dists.size() < queries.
rows ) dists.resize(queries.
rows);
415 #pragma omp parallel num_threads(params.cores)
418 #pragma omp for schedule(dynamic) reduction(+:count)
419 for (
int i = 0; i < (int)queries.
rows; i++) {
423 indices[i].resize(n);
426 resultSet.
copy(&indices[i][0], &dists[i][0], n,
params.sorted);
434 #pragma omp parallel num_threads(params.cores)
437 #pragma omp for schedule(dynamic) reduction(+:count)
438 for (
int i = 0; i < (int)queries.
rows; i++) {
442 indices[i].resize(n);
445 resultSet.
copy(&indices[i][0], &dists[i][0], n,
params.sorted);
467 std::vector< std::vector<int> >& indices,
468 std::vector<std::vector<DistanceType> >& dists,
472 std::vector<std::vector<size_t> > indices_;
475 indices.resize(indices_.size());
476 for (
size_t i=0;i<indices_.size();++i) {
477 indices[i].assign(indices_[i].begin(), indices_[i].end());
500 int max_neighbors =
params.max_neighbors;
501 if (max_neighbors<0) max_neighbors = num_neighbors;
502 else max_neighbors =
std::min(max_neighbors,(
int)num_neighbors);
504 if (max_neighbors==0) {
505 #pragma omp parallel num_threads(params.cores)
508 #pragma omp for schedule(dynamic) reduction(+:count)
509 for (
int i = 0; i < (int)queries.
rows; i++) {
519 if (
params.max_neighbors<0 && (num_neighbors>=
size())) {
520 #pragma omp parallel num_threads(params.cores)
523 #pragma omp for schedule(dynamic) reduction(+:count)
524 for (
int i = 0; i < (int)queries.
rows; i++) {
527 size_t n = resultSet.
size();
529 if (n>num_neighbors) n = num_neighbors;
530 resultSet.
copy(indices[i], dists[i], n,
params.sorted);
533 if (n<indices.
cols) indices[i][n] = size_t(-1);
541 #pragma omp parallel num_threads(params.cores)
544 #pragma omp for schedule(dynamic) reduction(+:count)
545 for (
int i = 0; i < (int)queries.
rows; i++) {
548 size_t n = resultSet.
size();
550 if ((
int)n>max_neighbors) n = max_neighbors;
551 resultSet.
copy(indices[i], dists[i], n,
params.sorted);
554 if (n<indices.
cols) indices[i][n] = size_t(-1);
583 for (
size_t i=0;i<indices.
rows;++i) {
584 for (
size_t j=0;j<indices.
cols;++j) {
585 indices[i][j] = indices_[i][j];
588 delete[] indices_.
ptr();
602 std::vector< std::vector<size_t> >& indices,
603 std::vector<std::vector<DistanceType> >& dists,
610 if (
params.max_neighbors==0) {
611 #pragma omp parallel num_threads(params.cores)
614 #pragma omp for schedule(dynamic) reduction(+:count)
615 for (
int i = 0; i < (int)queries.
rows; i++) {
623 if (indices.size() < queries.
rows ) indices.resize(queries.
rows);
624 if (dists.size() < queries.
rows ) dists.resize(queries.
rows);
626 if (
params.max_neighbors<0) {
628 #pragma omp parallel num_threads(params.cores)
631 #pragma omp for schedule(dynamic) reduction(+:count)
632 for (
int i = 0; i < (int)queries.
rows; i++) {
635 size_t n = resultSet.
size();
637 indices[i].resize(n);
640 resultSet.
copy(&indices[i][0], &dists[i][0], n,
params.sorted);
648 #pragma omp parallel num_threads(params.cores)
651 #pragma omp for schedule(dynamic) reduction(+:count)
652 for (
int i = 0; i < (int)queries.
rows; i++) {
655 size_t n = resultSet.
size();
657 if ((
int)n>
params.max_neighbors) n =
params.max_neighbors;
658 indices[i].resize(n);
661 resultSet.
copy(&indices[i][0], &dists[i][0], n,
params.sorted);
681 std::vector< std::vector<int> >& indices,
682 std::vector<std::vector<DistanceType> >& dists,
686 std::vector<std::vector<size_t> > indices_;
689 indices.resize(indices_.size());
690 for (
size_t i=0;i<indices_.size();++i) {
691 indices[i].assign(indices_[i].begin(), indices_[i].end());
707 if (
ids_.size()==0) {
710 size_t point_index = size_t(-1);
711 if (
id <
ids_.size() &&
ids_[
id]==
id) {
717 size_t end =
ids_.size();
720 size_t mid = (start+end)/2;
725 else if (
ids_[mid]<
id) {
740 for (
size_t i=0;i<
size;++i) {
741 out[i] =
ids_[in[i]];
758 for (
size_t i=0;i<
size_;++i) {
765 size_t new_size =
size_ + new_points.
rows;
768 ids_.resize(new_size);
771 for (
size_t i=
size_;i<new_size;++i) {
787 for (
size_t i=0;i<
size_;++i) {
796 ids_.resize(last_idx);
887 #define USING_BASECLASS_SYMBOLS \
888 using NNIndex<Distance>::distance_;\
889 using NNIndex<Distance>::size_;\
890 using NNIndex<Distance>::size_at_build_;\
891 using NNIndex<Distance>::veclen_;\
892 using NNIndex<Distance>::index_params_;\
893 using NNIndex<Distance>::removed_points_;\
894 using NNIndex<Distance>::ids_;\
895 using NNIndex<Distance>::removed_;\
896 using NNIndex<Distance>::points_;\
897 using NNIndex<Distance>::extendDataset;\
898 using NNIndex<Distance>::setDataset;\
899 using NNIndex<Distance>::cleanRemovedPoints;\
900 using NNIndex<Distance>::indices_to_ids;
double Distance(const Point3D< Real > &p1, const Point3D< Real > &p2)
cmdLineReadable * params[]
bool test(size_t index) const
virtual size_t veclen() const =0
virtual int usedMemory() const =0
virtual IndexParams getParameters() const =0
virtual void saveIndex(FILE *stream)=0
virtual void loadIndex(FILE *stream)=0
virtual size_t size() const =0
virtual flann_algorithm_t getType() const =0
void copy(size_t *indices, DistanceType *dists, size_t num_elements, bool sorted=true)
void copy(size_t *indices, DistanceType *dists, size_t num_elements, bool sorted=true)
void copy(size_t *indices, DistanceType *dists, size_t num_elements, bool sorted=true)
virtual void buildIndexImpl()=0
std::vector< size_t > ids_
virtual int knnSearch(const Matrix< ElementType > &queries, Matrix< size_t > &indices, Matrix< DistanceType > &dists, size_t knn, const SearchParams ¶ms) const
Perform k-nearest neighbor search.
virtual void removePoint(size_t id)
void indices_to_ids(const size_t *in, size_t *out, size_t size) const
NNIndex(const NNIndex &other)
std::vector< ElementType * > points_
int radiusSearch(const Matrix< ElementType > &queries, Matrix< size_t > &indices, Matrix< DistanceType > &dists, float radius, const SearchParams ¶ms) const
Perform radius search.
int radiusSearch(const Matrix< ElementType > &queries, std::vector< std::vector< size_t > > &indices, std::vector< std::vector< DistanceType > > &dists, float radius, const SearchParams ¶ms) const
Perform radius search.
NNIndex(const IndexParams ¶ms, Distance d)
Distance::ElementType ElementType
virtual void addPoints(const Matrix< ElementType > &points, float rebuild_threshold=2)
Incrementally add points to the index.
virtual void buildIndex(const Matrix< ElementType > &dataset)
void serialize(Archive &ar)
void swap(NNIndex &other)
int radiusSearch(const Matrix< ElementType > &queries, Matrix< int > &indices, Matrix< DistanceType > &dists, float radius, const SearchParams ¶ms) const
int knnSearch(const Matrix< ElementType > &queries, std::vector< std::vector< size_t > > &indices, std::vector< std::vector< DistanceType > > &dists, size_t knn, const SearchParams ¶ms) const
Perform k-nearest neighbor search.
Distance::ResultType DistanceType
IndexParams getParameters() const
DynamicBitset removed_points_
virtual ElementType * getPoint(size_t id)
int radiusSearch(const Matrix< ElementType > &queries, std::vector< std::vector< int > > &indices, std::vector< std::vector< DistanceType > > &dists, float radius, const SearchParams ¶ms) const
void cleanRemovedPoints()
int knnSearch(const Matrix< ElementType > &queries, std::vector< std::vector< int > > &indices, std::vector< std::vector< DistanceType > > &dists, size_t knn, const SearchParams ¶ms) const
virtual void freeIndex()=0
void setDataset(const Matrix< ElementType > &dataset)
virtual void buildIndex()
int knnSearch(const Matrix< ElementType > &queries, Matrix< int > &indices, Matrix< DistanceType > &dists, size_t knn, const SearchParams ¶ms) const
void extendDataset(const Matrix< ElementType > &new_points)
virtual void findNeighbors(ResultSet< DistanceType > &result, const ElementType *vec, const SearchParams &searchParams) const =0
IndexParams index_params_
size_t id_to_index(size_t id)
virtual NNIndex * clone() const =0
void copy(size_t *indices, DistanceType *dists, size_t num_elements, bool sorted=true)
__device__ __forceinline__ float infinity()
const binary_object make_binary_object(void *t, size_t size)
T get_param(const IndexParams ¶ms, std::string name, const T &default_value)
std::map< std::string, any > IndexParams
void swap(cloudViewer::core::SmallVectorImpl< T > &LHS, cloudViewer::core::SmallVectorImpl< T > &RHS)
Implement std::swap in terms of SmallVector swap.
#define KNN_HEAP_THRESHOLD