31 #ifndef FLANN_KDTREE_SINGLE_INDEX_H_
32 #define FLANN_KDTREE_SINGLE_INDEX_H_
56 (*this)[
"leaf_max_size"] = leaf_max_size;
57 (*this)[
"reorder"] = reorder;
68 template <
typename Distance>
110 leaf_max_size_(other.leaf_max_size_),
111 reorder_(other.reorder_),
113 root_bbox_(other.root_bbox_)
119 copyTree(root_node_, other.root_node_);
156 template<
typename Archive>
174 if (Archive::is_loading::value) {
175 root_node_ =
new(pool_) Node();
180 if (Archive::is_loading::value) {
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) {
279 Node* child1, * child2;
283 if (child1) child1->~Node();
284 if (child2) child2->~Node();
288 template<
typename Archive>
291 typedef KDTreeSingleIndex<Distance>
Index;
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();
315 friend struct serialization::access;
317 typedef Node* NodePtr;
325 template <
typename Archive>
331 friend struct serialization::access;
336 typedef BranchStruct<NodePtr, DistanceType> BranchSt;
337 typedef BranchSt* Branch;
344 delete[] data_.
ptr();
347 if (root_node_) root_node_->~Node();
351 void copyTree(NodePtr& dst,
const NodePtr& src)
353 dst =
new(pool_)
Node();
355 if (src->child1!=
NULL && src->child2!=
NULL) {
356 copyTree(dst->child1, src->child1);
357 copyTree(dst->child2, src->child2);
366 for (
size_t i=0; i<
veclen_; ++i) {
370 for (
size_t k=1; k<
size_; ++k) {
371 for (
size_t i=0; i<
veclen_; ++i) {
388 NodePtr divideTree(
int left,
int right,
BoundingBox& bbox)
390 NodePtr node =
new (pool_)
Node();
393 if ( (right-left) <= leaf_max_size_) {
394 node->child1 = node->child2 =
NULL;
399 for (
size_t i=0; i<
veclen_; ++i) {
403 for (
int k=left+1; k<right; ++k) {
404 for (
size_t i=0; i<
veclen_; ++i) {
414 middleSplit(&vind_[0]+left, right-left, idx, cutfeat, cutval, bbox);
416 node->divfeat = cutfeat;
419 left_bbox[cutfeat].high = cutval;
420 node->child1 = divideTree(left, left+idx, left_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);
440 min_elem =
points_[ind[0]][dim];
441 max_elem =
points_[ind[0]][dim];
442 for (
int i=1; i<
count; ++i) {
444 if (val<min_elem) min_elem = val;
445 if (val>max_elem) max_elem = val;
454 cutval = (bbox[0].high+bbox[0].low)/2;
455 for (
size_t i=1; i<
veclen_; ++i) {
460 cutval = (bbox[i].high+bbox[i].low)/2;
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) {
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);
498 const float eps_val=0.00001f;
500 for (
size_t i=1; i<
veclen_; ++i) {
508 for (
size_t i=0; i<
veclen_; ++i) {
512 computeMinMax(ind,
count, cutfeat, min_elem, max_elem);
514 if (spread>max_spread) {
521 DistanceType split_val = (bbox[cutfeat].low+bbox[cutfeat].high)/2;
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;
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>
593 void searchLevel(ResultSet<DistanceType>& result_set,
const ElementType* vec,
const NodePtr node,
DistanceType mindistsq,
594 std::vector<DistanceType>& dists,
const float epsError)
const
597 if ((node->child1 ==
NULL)&&(node->child2 ==
NULL)) {
599 for (
int i=node->left; i<node->right; ++i) {
605 if (
dist<worst_dist) {
606 result_set.addPoint(
dist,vind_[i]);
613 int idx = node->divfeat;
621 if ((diff1+diff2)<0) {
622 bestChild = node->child1;
623 otherChild = node->child2;
624 cut_dist =
distance_.accum_dist(val, node->divhigh, idx);
627 bestChild = node->child2;
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);
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);
648 std::swap(leaf_max_size_, other.leaf_max_size_);
669 std::vector<int> vind_;
671 Matrix<ElementType> data_;
690 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
void saveIndex(FILE *stream)
void findNeighbors(ResultSet< DistanceType > &result, const ElementType *vec, const SearchParams &searchParams) const
BaseClass * clone() const
flann_algorithm_t getType() const
KDTreeSingleIndex(const IndexParams ¶ms=KDTreeSingleIndexParams(), Distance d=Distance())
KDTreeSingleIndex & operator=(KDTreeSingleIndex other)
void addPoints(const Matrix< ElementType > &points, float rebuild_threshold=2)
Incrementally add points to the index.
virtual ~KDTreeSingleIndex()
NNIndex< Distance > BaseClass
KDTreeSingleIndex(const Matrix< ElementType > &inputData, const IndexParams ¶ms=KDTreeSingleIndexParams(), Distance d=Distance())
void serialize(Archive &ar)
bool needs_kdtree_distance
Distance::ResultType DistanceType
virtual void buildIndex()
Distance::ElementType ElementType
void loadIndex(FILE *stream)
KDTreeSingleIndex(const KDTreeSingleIndex &other)
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_
@ FLANN_INDEX_KDTREE_SINGLE
static double dist(double x1, double y1, double x2, double y2)
void swap(optional< T > &x, optional< T > &y) noexcept(noexcept(x.swap(y)))
BoundingBoxTpl< PointCoordinateType > BoundingBox
Default bounding-box type.
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 USING_BASECLASS_SYMBOLS
KDTreeSingleIndexParams(int leaf_max_size=10, bool reorder=true)