31 #ifndef RTABMAP_FLANN_KDTREE_SINGLE_INDEX_H_ 32 #define RTABMAP_FLANN_KDTREE_SINGLE_INDEX_H_ 56 (*this)[
"leaf_max_size"] = leaf_max_size;
57 (*this)[
"reorder"] = reorder;
68 template <
typename Distance>
86 BaseClass(params,
d), root_node_(
NULL)
88 leaf_max_size_ =
get_param(params,
"leaf_max_size",10);
89 reorder_ =
get_param(params,
"reorder",
true);
100 Distance d = Distance() ) : BaseClass(params,
d), root_node_(
NULL)
102 leaf_max_size_ =
get_param(params,
"leaf_max_size",10);
103 reorder_ =
get_param(params,
"reorder",
true);
105 setDataset(inputData);
110 leaf_max_size_(other.leaf_max_size_),
111 reorder_(other.reorder_),
113 root_bbox_(other.root_bbox_)
117 std::copy(other.
data_[0], other.
data_[0]+size_*veclen_, data_[0]);
141 using BaseClass::buildIndex;
145 assert(points.
cols==veclen_);
146 extendDataset(points);
156 template<
typename Archive>
161 if (reorder_) index_params_[
"save_dataset"] =
false;
174 if (Archive::is_loading::value) {
175 root_node_ =
new(pool_)
Node();
180 if (Archive::is_loading::value) {
181 index_params_[
"algorithm"] = getType();
182 index_params_[
"leaf_max_size"] = leaf_max_size_;
183 index_params_[
"reorder"] = reorder_;
208 return pool_.usedMemory+pool_.wastedMemory+size_*
sizeof(int);
222 float epsError = 1+searchParams.
eps;
224 std::vector<DistanceType> dists(veclen_,0);
225 DistanceType distsq = computeInitialDistances(vec, dists);
227 searchLevel<true>(result, vec, root_node_, distsq, dists, epsError);
230 searchLevel<false>(result, vec, root_node_, distsq, dists, epsError);
243 for (
size_t i = 0; i < size_; i++) {
247 computeBoundingBox(root_bbox_);
248 root_node_ = divideTree(0, size_, root_bbox_ );
252 for (
size_t i=0; i<size_; ++i) {
253 std::copy(points_[vind_[i]], points_[vind_[i]]+veclen_, data_[i]);
283 if (child1) child1->
~Node();
284 if (child2) child2->
~Node();
288 template<
typename Archive>
292 Index* obj =
static_cast<Index*
>(ar.getObject());
300 bool leaf_node =
false;
301 if (Archive::is_saving::value) {
302 leaf_node = ((child1==
NULL) && (child2==
NULL));
307 if (Archive::is_loading::value) {
308 child1 =
new(obj->pool_)
Node();
309 child2 =
new(obj->pool_)
Node();
325 template <
typename Archive>
344 delete[] data_.ptr();
347 if (root_node_) root_node_->~Node();
353 dst =
new(pool_)
Node();
365 bbox.resize(veclen_);
366 for (
size_t i=0; i<veclen_; ++i) {
367 bbox[i].low = (DistanceType)points_[0][i];
368 bbox[i].high = (DistanceType)points_[0][i];
370 for (
size_t k=1; k<size_; ++k) {
371 for (
size_t i=0; i<veclen_; ++i) {
372 if (points_[k][i]<bbox[i].low) bbox[i].low = (DistanceType)points_[k][i];
373 if (points_[k][i]>bbox[i].high) bbox[i].high = (DistanceType)points_[k][i];
390 NodePtr node =
new (pool_)
Node();
393 if ( (right-left) <= leaf_max_size_) {
399 for (
size_t i=0; i<veclen_; ++i) {
400 bbox[i].low = (DistanceType)points_[vind_[left]][i];
401 bbox[i].high = (DistanceType)points_[vind_[left]][i];
403 for (
int k=left+1; k<right; ++k) {
404 for (
size_t i=0; i<veclen_; ++i) {
405 if (bbox[i].low>points_[vind_[k]][i]) bbox[i].low=(DistanceType)points_[vind_[k]][i];
406 if (bbox[i].high<points_[vind_[k]][i]) bbox[i].high=(DistanceType)points_[vind_[k]][i];
414 middleSplit(&vind_[0]+left, right-left, idx, cutfeat, cutval, bbox);
418 BoundingBox left_bbox(bbox);
419 left_bbox[cutfeat].high = cutval;
420 node->
child1 = divideTree(left, left+idx, left_bbox);
422 BoundingBox right_bbox(bbox);
423 right_bbox[cutfeat].low = cutval;
424 node->
child2 = divideTree(left+idx, right, right_bbox);
426 node->
divlow = left_bbox[cutfeat].high;
427 node->
divhigh = right_bbox[cutfeat].low;
429 for (
size_t i=0; i<veclen_; ++i) {
430 bbox[i].low =
std::min(left_bbox[i].low, right_bbox[i].low);
431 bbox[i].high =
std::max(left_bbox[i].high, right_bbox[i].high);
438 void computeMinMax(
int* ind,
int count,
int dim, ElementType& min_elem, ElementType& max_elem)
440 min_elem = points_[ind[0]][dim];
441 max_elem = points_[ind[0]][dim];
442 for (
int i=1; i<count; ++i) {
443 ElementType val = points_[ind[i]][dim];
444 if (val<min_elem) min_elem = val;
445 if (val>max_elem) max_elem = val;
449 void middleSplit(
int* ind,
int count,
int& index,
int& cutfeat, DistanceType& cutval,
const BoundingBox& bbox)
452 ElementType max_span = bbox[0].high-bbox[0].low;
454 cutval = (bbox[0].high+bbox[0].low)/2;
455 for (
size_t i=1; i<veclen_; ++i) {
456 ElementType span = bbox[i].high-bbox[i].low;
460 cutval = (bbox[i].high+bbox[i].low)/2;
465 ElementType min_elem, max_elem;
466 computeMinMax(ind, count, cutfeat, min_elem, max_elem);
467 cutval = (min_elem+max_elem)/2;
468 max_span = max_elem - min_elem;
472 for (
size_t i=0; i<veclen_; ++i) {
474 ElementType span = bbox[i].high-bbox[i].low;
476 computeMinMax(ind, count, i, min_elem, max_elem);
477 span = max_elem - min_elem;
481 cutval = (min_elem+max_elem)/2;
486 planeSplit(ind, count, cutfeat, cutval, lim1, lim2);
488 if (lim1>count/2) index = lim1;
489 else if (lim2<count/2) index = lim2;
490 else index = count/2;
492 assert(index > 0 && index < count);
496 void middleSplit_(
int* ind,
int count,
int& index,
int& cutfeat, DistanceType& cutval,
const BoundingBox& bbox)
498 const float eps_val=0.00001f;
499 DistanceType max_span = bbox[0].high-bbox[0].low;
500 for (
size_t i=1; i<veclen_; ++i) {
501 DistanceType span = bbox[i].high-bbox[i].low;
506 DistanceType max_spread = -1;
508 for (
size_t i=0; i<veclen_; ++i) {
509 DistanceType span = bbox[i].high-bbox[i].low;
510 if (span>(DistanceType)((1-eps_val)*max_span)) {
511 ElementType min_elem, max_elem;
512 computeMinMax(ind, count, cutfeat, min_elem, max_elem);
513 DistanceType spread = (DistanceType)(max_elem-min_elem);
514 if (spread>max_spread) {
521 DistanceType split_val = (bbox[cutfeat].low+bbox[cutfeat].high)/2;
522 ElementType min_elem, max_elem;
523 computeMinMax(ind, count, cutfeat, min_elem, max_elem);
525 if (split_val<min_elem) cutval = (DistanceType)min_elem;
526 else if (split_val>max_elem) cutval = (DistanceType)max_elem;
527 else cutval = split_val;
530 planeSplit(ind, count, cutfeat, cutval, lim1, lim2);
532 if (lim1>count/2) index = lim1;
533 else if (lim2<count/2) index = lim2;
534 else index = count/2;
536 assert(index > 0 && index < count);
549 void planeSplit(
int* ind,
int count,
int cutfeat, DistanceType cutval,
int& lim1,
int& lim2)
554 while (left<=right && points_[ind[left]][cutfeat]<cutval) ++left;
555 while (left<=right && points_[ind[right]][cutfeat]>=cutval) --right;
556 if (left>right)
break;
557 std::swap(ind[left], ind[right]); ++left; --right;
563 while (left<=right && points_[ind[left]][cutfeat]<=cutval) ++left;
564 while (left<=right && points_[ind[right]][cutfeat]>cutval) --right;
565 if (left>right)
break;
566 std::swap(ind[left], ind[right]); ++left; --right;
573 DistanceType distsq = 0.0;
575 for (
size_t i = 0; i < veclen_; ++i) {
576 if (vec[i] < root_bbox_[i].low) {
577 dists[i] = distance_.accum_dist(vec[i], root_bbox_[i].low, i);
580 if (vec[i] > root_bbox_[i].high) {
581 dists[i] = distance_.accum_dist(vec[i], root_bbox_[i].high, i);
592 template <
bool with_removed>
594 std::vector<DistanceType>& dists,
const float epsError)
const 598 DistanceType worst_dist = result_set.
worstDist();
599 for (
int i=node->
left; i<node->right; ++i) {
601 if (removed_points_.test(vind_[i]))
continue;
603 ElementType* point = reorder_ ? data_[i] : points_[vind_[i]];
604 DistanceType dist = distance_(vec, point, veclen_, worst_dist);
605 if (dist<worst_dist) {
614 ElementType val = vec[idx];
615 DistanceType diff1 = val - node->
divlow;
616 DistanceType diff2 = val - node->
divhigh;
620 DistanceType cut_dist;
621 if ((diff1+diff2)<0) {
623 otherChild = node->
child2;
624 cut_dist = distance_.accum_dist(val, node->
divhigh, idx);
628 otherChild = node->
child1;
629 cut_dist = distance_.accum_dist( val, node->
divlow, idx);
633 searchLevel<with_removed>(result_set, vec, bestChild, mindistsq, dists, epsError);
635 DistanceType
dst = dists[idx];
636 mindistsq = mindistsq + cut_dist -
dst;
637 dists[idx] = cut_dist;
638 if (mindistsq*epsError<=result_set.worstDist()) {
639 searchLevel<with_removed>(result_set, vec, otherChild, mindistsq, dists, epsError);
647 BaseClass::swap(other);
649 std::swap(reorder_, other.
reorder_);
650 std::swap(vind_, other.
vind_);
651 std::swap(data_, other.
data_);
654 std::swap(pool_, other.
pool_);
698 #endif //FLANN_KDTREE_SINGLE_INDEX_H_
std::map< std::string, any > IndexParams
void addPoints(const Matrix< ElementType > &points, float rebuild_threshold=2)
Incrementally add points to the index.
T get_param(const IndexParams ¶ms, std::string name, const T &default_value)
GLM_FUNC_DECL genType min(genType const &x, genType const &y)
Distance::ElementType ElementType
NNIndex< Distance > BaseClass
void serialize(Archive &ar)
void middleSplit(int *ind, int count, int &index, int &cutfeat, DistanceType &cutval, const BoundingBox &bbox)
DistanceType computeInitialDistances(const ElementType *vec, std::vector< DistanceType > &dists) const
NodePtr divideTree(int left, int right, BoundingBox &bbox)
#define USING_BASECLASS_SYMBOLS
BranchStruct< NodePtr, DistanceType > BranchSt
void copyTree(NodePtr &dst, const NodePtr &src)
void swap(KDTreeSingleIndex &other)
void middleSplit_(int *ind, int count, int &index, int &cutfeat, DistanceType &cutval, const BoundingBox &bbox)
void serialize(Archive &ar)
KDTreeSingleIndex(const Matrix< ElementType > &inputData, const IndexParams ¶ms=KDTreeSingleIndexParams(), Distance d=Distance())
KDTreeSingleIndex(const KDTreeSingleIndex &other)
void serialize(Archive &ar)
Distance::ResultType DistanceType
Matrix< ElementType > data_
bool needs_kdtree_distance
KDTreeSingleIndexParams(int leaf_max_size=10, bool reorder=true)
void searchLevel(ResultSet< DistanceType > &result_set, const ElementType *vec, const NodePtr node, DistanceType mindistsq, std::vector< DistanceType > &dists, const float epsError) const
void loadIndex(FILE *stream)
flann_algorithm_t getType() const
void computeMinMax(int *ind, int count, int dim, ElementType &min_elem, ElementType &max_elem)
KDTreeSingleIndex & operator=(KDTreeSingleIndex other)
virtual DistanceType worstDist() const =0
void findNeighbors(ResultSet< DistanceType > &result, const ElementType *vec, const SearchParams &searchParams) const
GLM_FUNC_DECL genType max(genType const &x, genType const &y)
void saveIndex(FILE *stream)
static void freeIndex(sqlite3 *db, Index *p)
KDTreeSingleIndex(const IndexParams ¶ms=KDTreeSingleIndexParams(), Distance d=Distance())
void computeBoundingBox(BoundingBox &bbox)
virtual ~KDTreeSingleIndex()
std::vector< Interval > BoundingBox
virtual void addPoint(DistanceType dist, size_t index)=0
BaseClass * clone() const
void planeSplit(int *ind, int count, int cutfeat, DistanceType cutval, int &lim1, int &lim2)