31 #ifndef RTABMAP_FLANN_NNINDEX_H 32 #define RTABMAP_FLANN_NNINDEX_H 46 #define KNN_HEAP_THRESHOLD 250 54 virtual size_t veclen()
const = 0;
56 virtual size_t size()
const = 0;
72 template <
typename Distance>
79 NNIndex(Distance d) : distance_(d), last_id_(0), size_(0), size_at_build_(0), veclen_(0),
80 removed_(
false), removed_count_(0), data_ptr_(
NULL)
84 NNIndex(
const IndexParams& params, Distance d) : distance_(d), last_id_(0), size_(0), size_at_build_(0), veclen_(0),
85 index_params_(params), removed_(
false), removed_count_(0), data_ptr_(
NULL)
90 distance_(other.distance_),
91 last_id_(other.last_id_),
93 size_at_build_(other.size_at_build_),
94 veclen_(other.veclen_),
95 index_params_(other.index_params_),
96 removed_(other.removed_),
97 removed_points_(other.removed_points_),
98 removed_count_(other.removed_count_),
100 points_(other.points_),
104 data_ptr_ =
new ElementType[size_*veclen_];
106 for (
size_t i=0;i<size_;++i) {
107 points_[i] = data_ptr_ + i*veclen_;
120 virtual NNIndex* clone()
const = 0;
128 cleanRemovedPoints();
133 size_at_build_ = size_;
154 throw FLANNException(
"Functionality not supported by this index");
165 for (
size_t i=0;i<size_;++i) {
168 removed_points_.resize(size_);
169 removed_points_.reset();
174 size_t point_index = id_to_index(
id);
175 if (point_index!=
size_t(-1) && !removed_points_.test(point_index)) {
176 removed_points_.set(point_index);
189 size_t index = id_to_index(
id);
190 if (index!=
size_t(-1)) {
191 return points_[index];
203 return size_ - removed_count_;
208 return removed_count_;
213 return size_at_build_;
231 return index_params_;
235 template<
typename Archive>
240 if (Archive::is_saving::value) {
243 header.
h.
rows = size_;
244 header.
h.
cols = veclen_;
249 if (Archive::is_loading::value) {
250 if (strncmp(header.h.signature,
257 throw FLANNException(
"Datatype of saved index is different than of the one to be created.");
260 if (header.h.index_type !=
getType()) {
261 throw FLANNException(
"Saved index type is different then the current index type.");
272 if (Archive::is_saving::value) {
273 save_dataset =
get_param(index_params_,
"save_dataset",
false);
278 if (Archive::is_loading::value) {
282 data_ptr_ =
new ElementType[size_*veclen_];
283 points_.resize(size_);
284 for (
size_t i=0;i<size_;++i) {
285 points_[i] = data_ptr_ + i*veclen_;
288 for (
size_t i=0;i<size_;++i) {
292 if (points_.size()!=size_) {
293 throw FLANNException(
"Saved index does not contain the dataset and no dataset was provided.");
301 ar & removed_points_;
322 assert(indices.
rows >= queries.
rows);
324 assert(indices.
cols >= knn);
325 assert(dists.
cols >= knn);
337 #pragma omp parallel num_threads(params.cores) 340 #pragma omp for schedule(static) reduction(+:count) 341 for (
int i = 0; i < (int)queries.
rows; i++) {
343 findNeighbors(resultSet, queries[i], params);
345 resultSet.
copy(indices[i], dists[i], n, params.
sorted);
346 indices_to_ids(indices[i], indices[i], n);
352 #pragma omp parallel num_threads(params.cores) 355 #pragma omp for schedule(static) reduction(+:count) 356 for (
int i = 0; i < (int)queries.
rows; i++) {
358 findNeighbors(resultSet, queries[i], params);
360 resultSet.
copy(indices[i], dists[i], n, params.
sorted);
361 indices_to_ids(indices[i], indices[i], n);
406 std::vector< std::vector<size_t> >& indices,
407 std::vector<std::vector<DistanceType> >& dists,
420 if (indices.size() < queries.
rows ) indices.resize(queries.
rows);
421 if (dists.size() < queries.
rows ) dists.resize(queries.
rows);
425 #pragma omp parallel num_threads(params.cores) 428 #pragma omp for schedule(static) reduction(+:count) 429 for (
int i = 0; i < (int)queries.
rows; i++) {
431 findNeighbors(resultSet, queries[i], params);
433 indices[i].resize(n);
436 resultSet.
copy(&indices[i][0], &dists[i][0], n, params.
sorted);
437 indices_to_ids(&indices[i][0], &indices[i][0], n);
444 #pragma omp parallel num_threads(params.cores) 447 #pragma omp for schedule(static) reduction(+:count) 448 for (
int i = 0; i < (int)queries.
rows; i++) {
450 findNeighbors(resultSet, queries[i], params);
452 indices[i].resize(n);
455 resultSet.
copy(&indices[i][0], &dists[i][0], n, params.
sorted);
456 indices_to_ids(&indices[i][0], &indices[i][0], n);
477 std::vector< std::vector<int> >& indices,
478 std::vector<std::vector<DistanceType> >& dists,
482 std::vector<std::vector<size_t> > indices_;
483 int result = knnSearch(queries, indices_, dists, knn, params);
485 indices.resize(indices_.size());
486 for (
size_t i=0;i<indices_.size();++i) {
487 indices[i].assign(indices_[i].begin(), indices_[i].end());
511 if (max_neighbors<0) max_neighbors = num_neighbors;
512 else max_neighbors =
std::min(max_neighbors,(
int)num_neighbors);
514 if (max_neighbors==0) {
515 #pragma omp parallel num_threads(params.cores) 518 #pragma omp for schedule(static) reduction(+:count) 519 for (
int i = 0; i < (int)queries.
rows; i++) {
521 findNeighbors(resultSet, queries[i], params);
522 count += resultSet.
size();
530 #pragma omp parallel num_threads(params.cores) 533 #pragma omp for schedule(static) reduction(+:count) 534 for (
int i = 0; i < (int)queries.
rows; i++) {
536 findNeighbors(resultSet, queries[i], params);
537 size_t n = resultSet.
size();
539 if (n>num_neighbors) n = num_neighbors;
540 resultSet.
copy(indices[i], dists[i], n, params.
sorted);
543 if (n<indices.
cols) indices[i][n] = size_t(-1);
544 if (n<dists.
cols) dists[i][n] = std::numeric_limits<DistanceType>::infinity();
545 indices_to_ids(indices[i], indices[i], n);
551 #pragma omp parallel num_threads(params.cores) 554 #pragma omp for schedule(static) reduction(+:count) 555 for (
int i = 0; i < (int)queries.
rows; i++) {
557 findNeighbors(resultSet, queries[i], params);
558 size_t n = resultSet.
size();
560 if ((
int)n>max_neighbors) n = max_neighbors;
561 resultSet.
copy(indices[i], dists[i], n, params.
sorted);
564 if (n<indices.
cols) indices[i][n] = size_t(-1);
565 if (n<dists.
cols) dists[i][n] = std::numeric_limits<DistanceType>::infinity();
566 indices_to_ids(indices[i], indices[i], n);
591 int result = radiusSearch(queries, indices_, dists, radius, params);
593 for (
size_t i=0;i<indices.
rows;++i) {
594 for (
size_t j=0;j<indices.
cols;++j) {
595 indices[i][j] = indices_[i][j];
598 delete[] indices_.
ptr();
612 std::vector< std::vector<size_t> >& indices,
613 std::vector<std::vector<DistanceType> >& dists,
621 #pragma omp parallel num_threads(params.cores) 624 #pragma omp for schedule(static) reduction(+:count) 625 for (
int i = 0; i < (int)queries.
rows; i++) {
627 findNeighbors(resultSet, queries[i], params);
628 count += resultSet.
size();
633 if (indices.size() < queries.
rows ) indices.resize(queries.
rows);
634 if (dists.size() < queries.
rows ) dists.resize(queries.
rows);
638 #pragma omp parallel num_threads(params.cores) 641 #pragma omp for schedule(static) reduction(+:count) 642 for (
int i = 0; i < (int)queries.
rows; i++) {
644 findNeighbors(resultSet, queries[i], params);
645 size_t n = resultSet.
size();
647 indices[i].resize(n);
650 resultSet.
copy(&indices[i][0], &dists[i][0], n, params.
sorted);
651 indices_to_ids(&indices[i][0], &indices[i][0], n);
658 #pragma omp parallel num_threads(params.cores) 661 #pragma omp for schedule(static) reduction(+:count) 662 for (
int i = 0; i < (int)queries.
rows; i++) {
664 findNeighbors(resultSet, queries[i], params);
665 size_t n = resultSet.
size();
668 indices[i].resize(n);
671 resultSet.
copy(&indices[i][0], &dists[i][0], n, params.
sorted);
672 indices_to_ids(&indices[i][0], &indices[i][0], n);
691 std::vector< std::vector<int> >& indices,
692 std::vector<std::vector<DistanceType> >& dists,
696 std::vector<std::vector<size_t> > indices_;
697 int result = radiusSearch(queries, indices_, dists, radius, params);
699 indices.resize(indices_.size());
700 for (
size_t i=0;i<indices_.size();++i) {
701 indices[i].assign(indices_[i].begin(), indices_[i].end());
713 virtual void buildIndexImpl() = 0;
717 if (ids_.size()==0) {
720 size_t point_index = size_t(-1);
721 if (
id < ids_.size() && ids_[id]==id) {
727 size_t end = ids_.size();
730 size_t mid = (start+end)/2;
735 else if (ids_[mid]<
id) {
750 for (
size_t i=0;i<
size;++i) {
751 out[i] = ids_[in[i]];
758 size_ = dataset.
rows;
759 veclen_ = dataset.
cols;
763 removed_points_.clear();
767 points_.resize(size_);
768 for (
size_t i=0;i<size_;++i) {
769 points_[i] = dataset[i];
775 size_t new_size = size_ + new_points.
rows;
777 removed_points_.resize(new_size);
778 ids_.resize(new_size);
780 points_.resize(new_size);
781 for (
size_t i=size_;i<new_size;++i) {
782 points_[i] = new_points[i-size_];
784 ids_[i] = last_id_++;
785 removed_points_.reset(i);
794 if (!removed_)
return;
797 for (
size_t i=0;i<size_;++i) {
798 if (!removed_points_.test(i)) {
799 points_[last_idx] = points_[i];
800 ids_[last_idx] = ids_[i];
801 removed_points_.reset(last_idx);
805 points_.resize(last_idx);
806 ids_.resize(last_idx);
807 removed_points_.resize(last_idx);
815 std::swap(last_id_, other.
last_id_);
816 std::swap(size_, other.
size_);
818 std::swap(veclen_, other.
veclen_);
820 std::swap(removed_, other.
removed_);
823 std::swap(ids_, other.
ids_);
824 std::swap(points_, other.
points_);
897 #define USING_BASECLASS_SYMBOLS \ 898 using NNIndex<Distance>::distance_;\ 899 using NNIndex<Distance>::size_;\ 900 using NNIndex<Distance>::size_at_build_;\ 901 using NNIndex<Distance>::veclen_;\ 902 using NNIndex<Distance>::index_params_;\ 903 using NNIndex<Distance>::removed_points_;\ 904 using NNIndex<Distance>::ids_;\ 905 using NNIndex<Distance>::removed_;\ 906 using NNIndex<Distance>::points_;\ 907 using NNIndex<Distance>::extendDataset;\ 908 using NNIndex<Distance>::setDataset;\ 909 using NNIndex<Distance>::cleanRemovedPoints;\ 910 using NNIndex<Distance>::indices_to_ids; 917 #endif //FLANN_NNINDEX_H
std::map< std::string, any > IndexParams
int radiusSearch(const Matrix< ElementType > &queries, Matrix< int > &indices, Matrix< DistanceType > &dists, float radius, const SearchParams ¶ms) const
void indices_to_ids(const size_t *in, size_t *out, size_t size) const
virtual size_t veclen() const =0
void copy(size_t *indices, DistanceType *dists, size_t num_elements, bool sorted=true)
void swap(NNIndex &other)
void copy(size_t *indices, DistanceType *dists, size_t num_elements, bool sorted=true)
T get_param(const IndexParams ¶ms, std::string name, const T &default_value)
GLM_FUNC_DECL genType min(genType const &x, genType const &y)
virtual void saveIndex(FILE *stream)=0
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.
Distance::ResultType DistanceType
IndexParams getParameters() const
virtual size_t size() const =0
virtual int usedMemory() const =0
std_msgs::Header * header(M &m)
virtual IndexParams getParameters() const =0
void extendDataset(const Matrix< ElementType > &new_points)
size_t id_to_index(size_t id)
virtual int radiusSearch(const Matrix< ElementType > &queries, Matrix< size_t > &indices, Matrix< DistanceType > &dists, float radius, const SearchParams ¶ms) const
Perform radius search.
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
void setDataset(const Matrix< ElementType > &dataset)
virtual void buildIndex()
virtual void buildIndex(const Matrix< ElementType > &dataset)
virtual 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.
#define KNN_HEAP_THRESHOLD
const binary_object make_binary_object(void *t, size_t size)
int radiusSearch(const Matrix< ElementType > &queries, std::vector< std::vector< int > > &indices, std::vector< std::vector< DistanceType > > &dists, float radius, const SearchParams ¶ms) const
virtual void addPoints(const Matrix< ElementType > &points, float rebuild_threshold=2)
Incrementally add points to the index.
virtual 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.
virtual void loadIndex(FILE *stream)=0
void copy(size_t *indices, DistanceType *dists, size_t num_elements, bool sorted=true)
virtual void removePoint(size_t id)
size_t sizeAtBuild() const
void cleanRemovedPoints()
void serialize(Archive &ar)
Distance::ElementType ElementType
IndexParams index_params_
static void freeIndex(sqlite3 *db, Index *p)
NNIndex(const NNIndex &other)
NNIndex(const IndexParams ¶ms, Distance d)
std::vector< ElementType * > points_
void copy(size_t *indices, DistanceType *dists, size_t num_elements, bool sorted=true)
virtual ElementType * getPoint(size_t id)
size_t removedCount() const
std::vector< size_t > ids_
virtual flann_algorithm_t getType() const =0
DynamicBitset removed_points_