31 #ifndef FLANN_KDTREE_INDEX_H_
32 #define FLANN_KDTREE_INDEX_H_
60 (*this)[
"trees"] = trees;
71 template <
typename Distance>
115 tree_roots_.resize(other.tree_roots_.size());
116 for (
size_t i=0;i<tree_roots_.size();++i) {
117 copyTree(tree_roots_[i], other.tree_roots_[i]);
146 size_t old_size =
size_;
153 for (
size_t i=old_size;i<
size_;++i) {
154 for (
int j = 0; j < trees_; j++) {
155 addPointToTree(tree_roots_[j], i);
167 template<
typename Archive>
176 if (Archive::is_loading::value) {
177 tree_roots_.resize(trees_);
179 for (
size_t i=0;i<tree_roots_.size();++i) {
180 if (Archive::is_loading::value) {
181 tree_roots_[i] =
new(pool_) Node();
183 ar & *tree_roots_[i];
186 if (Archive::is_loading::value) {
227 int maxChecks = searchParams.
checks;
228 float epsError = 1+searchParams.
eps;
232 getExactNeighbors<true>(
result, vec, epsError);
235 getExactNeighbors<false>(
result, vec, epsError);
240 getNeighbors<true>(
result, vec, maxChecks, epsError);
243 getNeighbors<false>(
result, vec, maxChecks, epsError);
256 std::vector<int> ind(
size_);
257 for (
size_t i = 0; i <
size_; ++i) {
264 tree_roots_.resize(trees_);
266 for (
int i = 0; i < trees_; i++) {
268 auto rng = std::default_random_engine{};
269 std::shuffle(ind.begin(), ind.end(), rng);
270 tree_roots_[i] = divideTree(&ind[0],
int(
size_) );
278 for (
size_t i=0;i<tree_roots_.size();++i) {
280 if (tree_roots_[i]!=
NULL) tree_roots_[i]->~Node();
306 Node* child1, *child2;
312 if (child1 !=
NULL) { child1->~Node(); child1 =
NULL; }
314 if (child2 !=
NULL) { child2->~Node(); child2 =
NULL; }
318 template<
typename Archive>
321 typedef KDTreeIndex<Distance>
Index;
322 Index* obj =
static_cast<Index*
>(ar.getObject());
327 bool leaf_node =
false;
328 if (Archive::is_saving::value) {
329 leaf_node = ((child1==
NULL) && (child2==
NULL));
334 if (Archive::is_loading::value) {
335 point = obj->points_[divfeat];
340 if (Archive::is_loading::value) {
341 child1 =
new(obj->pool_)
Node();
342 child2 =
new(obj->pool_)
Node();
348 friend struct serialization::access;
350 typedef Node* NodePtr;
351 typedef BranchStruct<NodePtr, DistanceType> BranchSt;
352 typedef BranchSt* Branch;
355 void copyTree(NodePtr& dst,
const NodePtr& src)
357 dst =
new(pool_)
Node();
358 dst->divfeat = src->divfeat;
359 dst->divval = src->divval;
360 if (src->child1==
NULL && src->child2==
NULL) {
361 dst->point =
points_[dst->divfeat];
366 copyTree(dst->child1, src->child1);
367 copyTree(dst->child2, src->child2);
380 NodePtr divideTree(
int* ind,
int count)
382 NodePtr node =
new(pool_)
Node();
386 node->child1 = node->child2 =
NULL;
387 node->divfeat = *ind;
394 meanSplit(ind,
count, idx, cutfeat, cutval);
396 node->divfeat = cutfeat;
397 node->divval = cutval;
398 node->child1 = divideTree(ind, idx);
399 node->child2 = divideTree(ind+idx,
count-idx);
411 void meanSplit(
int* ind,
int count,
int& index,
int& cutfeat,
DistanceType& cutval)
420 for (
int j = 0; j < cnt; ++j) {
422 for (
size_t k=0; k<
veclen_; ++k) {
427 for (
size_t k=0; k<
veclen_; ++k) {
428 mean_[k] *= div_factor;
432 for (
int j = 0; j < cnt; ++j) {
434 for (
size_t k=0; k<
veclen_; ++k) {
440 cutfeat = selectDivision(var_);
441 cutval = mean_[cutfeat];
444 planeSplit(ind,
count, cutfeat, cutval, lim1, lim2);
446 if (lim1>
count/2) index = lim1;
447 else if (lim2<
count/2) index = lim2;
448 else index =
count/2;
453 if ((lim1==
count)||(lim2==0)) index =
count/2;
464 size_t topind[RAND_DIM];
467 for (
size_t i = 0; i <
veclen_; ++i) {
468 if ((num < RAND_DIM)||(v[i] > v[topind[num-1]])) {
470 if (num < RAND_DIM) {
478 while (j > 0 && v[topind[j]] > v[topind[j-1]]) {
486 return (
int)topind[rnd];
499 void planeSplit(
int* ind,
int count,
int cutfeat,
DistanceType cutval,
int& lim1,
int& lim2)
505 while (left<=right &&
points_[ind[left]][cutfeat]<cutval) ++left;
506 while (left<=right &&
points_[ind[right]][cutfeat]>=cutval) --right;
507 if (left>right)
break;
508 std::swap(ind[left], ind[right]); ++left; --right;
513 while (left<=right &&
points_[ind[left]][cutfeat]<=cutval) ++left;
514 while (left<=right &&
points_[ind[right]][cutfeat]>cutval) --right;
515 if (left>right)
break;
516 std::swap(ind[left], ind[right]); ++left; --right;
525 template<
bool with_removed>
526 void getExactNeighbors(ResultSet<DistanceType>&
result,
const ElementType* vec,
float epsError)
const
531 fprintf(stderr,
"It doesn't make any sense to use more than one tree for exact search");
534 searchLevelExact<with_removed>(
result, vec, tree_roots_[0], 0.0, epsError);
543 template<
bool with_removed>
544 void getNeighbors(ResultSet<DistanceType>&
result,
const ElementType* vec,
int maxCheck,
float epsError)
const
550 Heap<BranchSt>* heap =
new Heap<BranchSt>((
int)
size_);
551 DynamicBitset checked(
size_);
554 for (i = 0; i < trees_; ++i) {
555 searchLevel<with_removed>(
result, vec, tree_roots_[i], 0, checkCount, maxCheck, epsError, heap, checked);
559 while ( heap->popMin(branch) && (checkCount < maxCheck || !
result.full() )) {
560 searchLevel<with_removed>(
result, vec, branch.node, branch.mindist, checkCount, maxCheck, epsError, heap, checked);
572 template<
bool with_removed>
573 void searchLevel(ResultSet<DistanceType>& result_set,
const ElementType* vec, NodePtr node,
DistanceType mindist,
int& checkCount,
int maxCheck,
574 float epsError, Heap<BranchSt>* heap, DynamicBitset& checked)
const
576 if (result_set.worstDist()<mindist) {
582 if ((node->child1 ==
NULL)&&(node->child2 ==
NULL)) {
583 int index = node->divfeat;
588 if ( checked.test(index) || ((checkCount>=maxCheck)&& result_set.full()) )
return;
593 result_set.addPoint(
dist,index);
600 NodePtr bestChild = (diff < 0) ? node->child1 : node->child2;
601 NodePtr otherChild = (diff < 0) ? node->child2 : node->child1;
613 if ((new_distsq*epsError < result_set.worstDist())|| !result_set.full()) {
614 heap->insert( BranchSt(otherChild, new_distsq) );
618 searchLevel<with_removed>(result_set, vec, bestChild, mindist, checkCount, maxCheck, epsError, heap, checked);
624 template<
bool with_removed>
625 void searchLevelExact(ResultSet<DistanceType>& result_set,
const ElementType* vec,
const NodePtr node,
DistanceType mindist,
const float epsError)
const
628 if ((node->child1 ==
NULL)&&(node->child2 ==
NULL)) {
629 int index = node->divfeat;
634 result_set.addPoint(
dist,index);
642 NodePtr bestChild = (diff < 0) ? node->child1 : node->child2;
643 NodePtr otherChild = (diff < 0) ? node->child2 : node->child1;
656 searchLevelExact<with_removed>(result_set, vec, bestChild, mindist, epsError);
658 if (mindist*epsError<=result_set.worstDist()) {
659 searchLevelExact<with_removed>(result_set, vec, otherChild, new_distsq, epsError);
663 void addPointToTree(NodePtr node,
int ind)
667 if ((node->child1==
NULL) && (node->child2==
NULL)) {
671 for (
size_t i=0;i<
veclen_;++i) {
673 if (span > max_span) {
678 NodePtr left =
new(pool_)
Node();
679 left->child1 = left->child2 =
NULL;
680 NodePtr right =
new(pool_)
Node();
681 right->child1 = right->child2 =
NULL;
683 if (
point[div_feat]<leaf_point[div_feat]) {
686 right->divfeat = node->divfeat;
687 right->point = node->point;
690 left->divfeat = node->divfeat;
691 left->point = node->point;
692 right->divfeat = ind;
693 right->point =
point;
695 node->divfeat = div_feat;
696 node->divval = (
point[div_feat]+leaf_point[div_feat])/2;
698 node->child2 = right;
701 if (
point[node->divfeat]<node->divval) {
702 addPointToTree(node->child1,ind);
705 addPointToTree(node->child2,ind);
714 std::swap(tree_roots_, other.tree_roots_);
750 std::vector<NodePtr> tree_roots_;
759 PooledAllocator pool_;
double Distance(const Point3D< Real > &p1, const Point3D< Real > &p2)
cmdLineReadable * params[]
Generic handle to any of the 8 types of E57 element objects.
bool test(size_t index) const
Distance::ElementType ElementType
void addPoints(const Matrix< ElementType > &points, float rebuild_threshold=2)
Incrementally add points to the index.
KDTreeIndex(const Matrix< ElementType > &dataset, const IndexParams ¶ms=KDTreeIndexParams(), Distance d=Distance())
KDTreeIndex & operator=(KDTreeIndex other)
void findNeighbors(ResultSet< DistanceType > &result, const ElementType *vec, const SearchParams &searchParams) const
flann_algorithm_t getType() const
BaseClass * clone() const
Distance::ResultType DistanceType
void loadIndex(FILE *stream)
void saveIndex(FILE *stream)
KDTreeIndex(const IndexParams ¶ms=KDTreeIndexParams(), Distance d=Distance())
NNIndex< Distance > BaseClass
virtual void buildIndex()
void serialize(Archive &ar)
KDTreeIndex(const KDTreeIndex &other)
bool needs_kdtree_distance
std::vector< ElementType * > points_
void swap(NNIndex &other)
DynamicBitset removed_points_
void setDataset(const Matrix< ElementType > &dataset)
virtual void buildIndex()
void extendDataset(const Matrix< ElementType > &new_points)
IndexParams index_params_
__host__ __device__ int2 abs(int2 v)
static double dist(double x1, double y1, double x2, double y2)
void swap(optional< T > &x, optional< T > &y) noexcept(noexcept(x.swap(y)))
T get_param(const IndexParams ¶ms, std::string name, const T &default_value)
int rand_int(int high=RAND_MAX, int low=0)
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 USING_BASECLASS_SYMBOLS
KDTreeIndexParams(int trees=4)