00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifndef NANOFLANN_HPP_
00034 #define NANOFLANN_HPP_
00035
00036 #include <vector>
00037 #include <string>
00038 #include <cassert>
00039 #include <map>
00040 #include <algorithm>
00041 #include <stdexcept>
00042 #include <limits>
00043
00044 #include <cassert>
00045 #include <cstring>
00046 #include <cstdio>
00047 #include <cmath>
00048
00049
00050 namespace nanoflann
00051 {
00052
00053
00054
00055
00056 #define NANOFLANN_VERSION 0x101
00057
00058
00059
00060 template <typename DistanceType>
00061 class KNNResultSet
00062 {
00063 int* indices;
00064 DistanceType* dists;
00065 int capacity;
00066 int count;
00067
00068 public:
00069 inline KNNResultSet(int capacity_) : capacity(capacity_), count(0)
00070 {
00071 }
00072
00073 inline void init(int* indices_, DistanceType* dists_)
00074 {
00075 indices = indices_;
00076 dists = dists_;
00077 count = 0;
00078 dists[capacity-1] = (std::numeric_limits<DistanceType>::max)();
00079 }
00080
00081 inline size_t size() const
00082 {
00083 return count;
00084 }
00085
00086 inline bool full() const
00087 {
00088 return count == capacity;
00089 }
00090
00091
00092 inline void addPoint(DistanceType dist, int index)
00093 {
00094 int i;
00095 for (i=count; i>0; --i) {
00096 #ifdef NANOFLANN_FIRST_MATCH
00097 if ( (dists[i-1]>dist) || ((dist==dists[i-1])&&(indices[i-1]>index)) ) {
00098 #else
00099 if (dists[i-1]>dist) {
00100 #endif
00101 if (i<capacity) {
00102 dists[i] = dists[i-1];
00103 indices[i] = indices[i-1];
00104 }
00105 }
00106 else break;
00107 }
00108 if (i<capacity) {
00109 dists[i] = dist;
00110 indices[i] = index;
00111 }
00112 if (count<capacity) count++;
00113 }
00114
00115 inline DistanceType worstDist() const
00116 {
00117 return dists[capacity-1];
00118 }
00119 };
00120
00121
00122
00123
00124
00125 template <typename DistanceType>
00126 class RadiusResultSet
00127 {
00128 public:
00129 const DistanceType radius;
00130
00131 std::vector<std::pair<int,DistanceType> >& m_indices_dists;
00132
00133 inline RadiusResultSet(DistanceType radius_, std::vector<std::pair<int,DistanceType> >& indices_dists) : radius(radius_), m_indices_dists(indices_dists)
00134 {
00135 init();
00136 }
00137
00138 inline ~RadiusResultSet() { }
00139
00140 inline void init() { m_indices_dists.clear(); }
00141
00142 inline size_t size() const { return m_indices_dists.size(); }
00143
00144 inline bool full() const { return true; }
00145
00146 inline void addPoint(DistanceType dist, int index)
00147 {
00148 if (dist<radius)
00149 m_indices_dists.push_back(std::make_pair<int,DistanceType>(index,dist));
00150 }
00151
00152 inline DistanceType worstDist() const { return radius; }
00153 };
00154
00155
00156 template <typename DistanceType>
00157 struct IndexDist_Sorter
00158 {
00159 inline bool operator()(const std::pair<int,DistanceType> &p1, const std::pair<int,DistanceType> &p2) const
00160 {
00161 return p1.second < p2.second;
00162 }
00163 };
00164
00165
00166
00167
00168
00169
00170 template<typename T>
00171 void save_value(FILE* stream, const T& value, int count = 1)
00172 {
00173 fwrite(&value, sizeof(value),count, stream);
00174 }
00175
00176 template<typename T>
00177 void save_value(FILE* stream, const std::vector<T>& value)
00178 {
00179 size_t size = value.size();
00180 fwrite(&size, sizeof(size_t), 1, stream);
00181 fwrite(&value[0], sizeof(T), size, stream);
00182 }
00183
00184 template<typename T>
00185 void load_value(FILE* stream, T& value, int count = 1)
00186 {
00187 int read_cnt = fread(&value, sizeof(value), count, stream);
00188 if (read_cnt != count) {
00189 throw std::runtime_error("Cannot read from file");
00190 }
00191 }
00192
00193
00194 template<typename T>
00195 void load_value(FILE* stream, std::vector<T>& value)
00196 {
00197 size_t size;
00198 int read_cnt = fread(&size, sizeof(size_t), 1, stream);
00199 if (read_cnt!=1) {
00200 throw std::runtime_error("Cannot read from file");
00201 }
00202 value.resize(size);
00203 read_cnt = fread(&value[0], sizeof(T), size, stream);
00204 if (read_cnt!=int(size)) {
00205 throw std::runtime_error("Cannot read from file");
00206 }
00207 }
00208
00209
00210
00211
00212
00213
00214 template<typename T> inline T abs(T x) { return (x<0) ? -x : x; }
00215 template<> inline int abs<int>(int x) { return ::abs(x); }
00216 template<> inline float abs<float>(float x) { return fabsf(x); }
00217 template<> inline double abs<double>(double x) { return fabs(x); }
00218 template<> inline long double abs<long double>(long double x) { return fabsl(x); }
00219
00220
00221
00222
00223 template<class T, class DataSource>
00224 struct L1_Adaptor
00225 {
00226 typedef T ElementType;
00227 typedef T DistanceType;
00228 typedef T ResultType;
00229
00230 const DataSource &data_source;
00231
00232 L1_Adaptor(const DataSource &_data_source) : data_source(_data_source) { }
00233
00234 inline T operator()(const T* a, const size_t b_idx, size_t size, ResultType worst_dist = -1) const
00235 {
00236 ResultType result = ResultType();
00237 const T* last = a + size;
00238 const T* lastgroup = last - 3;
00239 size_t d = 0;
00240
00241
00242 while (a < lastgroup) {
00243 const ResultType diff0 = nanoflann::abs(a[0] - data_source.kdtree_get_pt(b_idx,d++));
00244 const ResultType diff1 = nanoflann::abs(a[1] - data_source.kdtree_get_pt(b_idx,d++));
00245 const ResultType diff2 = nanoflann::abs(a[2] - data_source.kdtree_get_pt(b_idx,d++));
00246 const ResultType diff3 = nanoflann::abs(a[3] - data_source.kdtree_get_pt(b_idx,d++));
00247 result += diff0 + diff1 + diff2 + diff3;
00248 a += 4;
00249 if ((worst_dist>0)&&(result>worst_dist)) {
00250 return result;
00251 }
00252 }
00253
00254 while (a < last) {
00255 result += nanoflann::abs( *a++ - data_source.kdtree_get_pt(b_idx,d++) );
00256 }
00257 return result;
00258 }
00259
00260 template <typename U, typename V>
00261 inline T accum_dist(const U a, const V b, int dim) const
00262 {
00263 return (a-b)*(a-b);
00264 }
00265 };
00266
00267
00268
00269
00270 template<class T, class DataSource>
00271 struct L2_Adaptor
00272 {
00273 typedef T ElementType;
00274 typedef T DistanceType;
00275 typedef T ResultType;
00276
00277 const DataSource &data_source;
00278
00279 L2_Adaptor(const DataSource &_data_source) : data_source(_data_source) { }
00280
00281 inline T operator()(const T* a, const size_t b_idx, size_t size, ResultType worst_dist = -1) const
00282 {
00283 ResultType result = ResultType();
00284 const T* last = a + size;
00285 const T* lastgroup = last - 3;
00286 size_t d = 0;
00287
00288
00289 while (a < lastgroup) {
00290 const ResultType diff0 = a[0] - data_source.kdtree_get_pt(b_idx,d++);
00291 const ResultType diff1 = a[1] - data_source.kdtree_get_pt(b_idx,d++);
00292 const ResultType diff2 = a[2] - data_source.kdtree_get_pt(b_idx,d++);
00293 const ResultType diff3 = a[3] - data_source.kdtree_get_pt(b_idx,d++);
00294 result += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3;
00295 a += 4;
00296 if ((worst_dist>0)&&(result>worst_dist)) {
00297 return result;
00298 }
00299 }
00300
00301 while (a < last) {
00302 const ResultType diff0 = *a++ - data_source.kdtree_get_pt(b_idx,d++);
00303 result += diff0 * diff0;
00304 }
00305 return result;
00306 }
00307
00308 template <typename U, typename V>
00309 inline T accum_dist(const U a, const V b, int dim) const
00310 {
00311 return (a-b)*(a-b);
00312 }
00313 };
00314
00315
00316
00317
00318 template<class T, class DataSource>
00319 struct L2_Simple_Adaptor
00320 {
00321 typedef T ElementType;
00322 typedef T DistanceType;
00323 typedef T ResultType;
00324
00325 const DataSource &data_source;
00326
00327 L2_Simple_Adaptor(const DataSource &_data_source) : data_source(_data_source) { }
00328
00329 inline T operator()(const T* a, const size_t b_idx, size_t size) const {
00330 return data_source.kdtree_distance(a,b_idx,size);
00331 }
00332
00333 template <typename U, typename V>
00334 inline T accum_dist(const U a, const V b, int dim) const
00335 {
00336 return (a-b)*(a-b);
00337 }
00338 };
00339
00340
00341 struct metric_L1 {
00342 template<class T, class DataSource>
00343 struct traits {
00344 typedef L1_Adaptor<T,DataSource> distance_t;
00345 };
00346 };
00347
00348 struct metric_L2 {
00349 template<class T, class DataSource>
00350 struct traits {
00351 typedef L2_Adaptor<T,DataSource> distance_t;
00352 };
00353 };
00354
00355 struct metric_L2_Simple {
00356 template<class T, class DataSource>
00357 struct traits {
00358 typedef L2_Simple_Adaptor<T,DataSource> distance_t;
00359 };
00360 };
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371 struct KDTreeSingleIndexAdaptorParams
00372 {
00373 KDTreeSingleIndexAdaptorParams(int leaf_max_size_ = 10, int dim_ = -1) :
00374 leaf_max_size(leaf_max_size_), dim(dim_)
00375 {}
00376
00377 int leaf_max_size;
00378 int dim;
00379 };
00380
00381
00382 struct SearchParams
00383 {
00384 SearchParams(int checks_ = 32, float eps_ = 0, bool sorted_ = true ) :
00385 checks(checks_), eps(eps_), sorted(sorted_) {}
00386
00387 int checks;
00388 float eps;
00389 bool sorted;
00390 };
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404 template <typename T>
00405 T* allocate(size_t count = 1)
00406 {
00407 T* mem = (T*) ::malloc(sizeof(T)*count);
00408 return mem;
00409 }
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427 const size_t WORDSIZE=16;
00428 const size_t BLOCKSIZE=8192;
00429
00430 class PooledAllocator
00431 {
00432
00433
00434
00435
00436
00437
00438 int remaining;
00439 void* base;
00440 void* loc;
00441 int blocksize;
00442
00443
00444 public:
00445 int usedMemory;
00446 int wastedMemory;
00447
00448
00449
00450
00451 PooledAllocator(int blocksize = BLOCKSIZE)
00452 {
00453 this->blocksize = blocksize;
00454 remaining = 0;
00455 base = NULL;
00456
00457 usedMemory = 0;
00458 wastedMemory = 0;
00459 }
00460
00461
00462
00463
00464 ~PooledAllocator()
00465 {
00466 void* prev;
00467
00468 while (base != NULL) {
00469 prev = *((void**) base);
00470 ::free(base);
00471 base = prev;
00472 }
00473 }
00474
00475
00476
00477
00478
00479 void* malloc(int size)
00480 {
00481 int blocksize;
00482
00483
00484
00485
00486
00487 size = (size + (WORDSIZE - 1)) & ~(WORDSIZE - 1);
00488
00489
00490
00491
00492 if (size > remaining) {
00493
00494 wastedMemory += remaining;
00495
00496
00497 blocksize = (size + sizeof(void*) + (WORDSIZE-1) > BLOCKSIZE) ?
00498 size + sizeof(void*) + (WORDSIZE-1) : BLOCKSIZE;
00499
00500
00501 void* m = ::malloc(blocksize);
00502 if (!m) {
00503 fprintf(stderr,"Failed to allocate memory.\n");
00504 return NULL;
00505 }
00506
00507
00508 ((void**) m)[0] = base;
00509 base = m;
00510
00511 int shift = 0;
00512
00513
00514 remaining = blocksize - sizeof(void*) - shift;
00515 loc = ((char*)m + sizeof(void*) + shift);
00516 }
00517 void* rloc = loc;
00518 loc = (char*)loc + size;
00519 remaining -= size;
00520
00521 usedMemory += size;
00522
00523 return rloc;
00524 }
00525
00526
00527
00528
00529
00530
00531
00532
00533 template <typename T>
00534 T* allocate(size_t count = 1)
00535 {
00536 T* mem = (T*) this->malloc(static_cast<int>( sizeof(T)*count ));
00537 return mem;
00538 }
00539
00540 };
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578 template <typename Distance, class DatasetAdaptor,int DIM = -1>
00579 class KDTreeSingleIndexAdaptor
00580 {
00581 typedef typename Distance::ElementType ElementType;
00582 typedef typename Distance::ResultType DistanceType;
00583
00584
00585
00586
00587 std::vector<int> vind;
00588
00589 int leaf_max_size_;
00590
00591
00592
00593
00594
00595 const DatasetAdaptor &dataset;
00596
00597 const KDTreeSingleIndexAdaptorParams index_params;
00598
00599 int size_;
00600 int dim;
00601
00602
00603
00604 struct Node
00605 {
00606 union {
00607 struct
00608 {
00609
00610
00611
00612 int left, right;
00613 } lr;
00614 struct
00615 {
00616
00617
00618
00619 int divfeat;
00620
00621
00622
00623 DistanceType divlow, divhigh;
00624 } sub;
00625 };
00626
00627
00628
00629 Node* child1, * child2;
00630 };
00631 typedef Node* NodePtr;
00632
00633
00634 struct Interval
00635 {
00636 ElementType low, high;
00637 };
00638
00639 typedef std::vector<Interval> BoundingBox;
00640
00641
00642
00643
00644
00645
00646 template <typename T, typename DistanceType>
00647 struct BranchStruct
00648 {
00649 T node;
00650 DistanceType mindist;
00651
00652 BranchStruct() {}
00653 BranchStruct(const T& aNode, DistanceType dist) : node(aNode), mindist(dist) {}
00654
00655 bool operator<(const BranchStruct<T, DistanceType>& rhs) const
00656 {
00657 return mindist<rhs.mindist;
00658 }
00659 };
00660
00661
00662
00663
00664 NodePtr root_node;
00665 typedef BranchStruct<NodePtr, DistanceType> BranchSt;
00666 typedef BranchSt* Branch;
00667
00668 BoundingBox root_bbox;
00669
00670
00671
00672
00673
00674
00675
00676
00677 PooledAllocator pool;
00678
00679 public:
00680
00681 Distance distance;
00682
00683
00684
00685
00686
00687
00688
00689
00690 KDTreeSingleIndexAdaptor(const int dimensionality, const DatasetAdaptor& inputData, const KDTreeSingleIndexAdaptorParams& params = KDTreeSingleIndexAdaptorParams() ) :
00691 dataset(inputData), index_params(params), distance(inputData)
00692 {
00693 size_ = static_cast<int>(dataset.kdtree_get_point_count());
00694 dim = dimensionality;
00695 if (DIM>0) dim=DIM;
00696 else {
00697 if (params.dim>0) dim = params.dim;
00698 }
00699 leaf_max_size_ = params.leaf_max_size;
00700
00701
00702 vind.resize(size_);
00703 for (int i = 0; i < size_; i++) {
00704 vind[i] = i;
00705 }
00706 }
00707
00708
00709
00710
00711 ~KDTreeSingleIndexAdaptor()
00712 {
00713 }
00714
00715
00716
00717
00718 void buildIndex()
00719 {
00720 computeBoundingBox(root_bbox);
00721 root_node = divideTree(0, size_, root_bbox );
00722 }
00723
00724
00725
00726
00727 size_t size() const
00728 {
00729 return size_;
00730 }
00731
00732
00733
00734
00735 size_t veclen() const
00736 {
00737 return (DIM>0 ? DIM : dim);
00738 }
00739
00740
00741
00742
00743
00744 int usedMemory() const
00745 {
00746 return pool.usedMemory+pool.wastedMemory+dataset.kdtree_get_point_count()*sizeof(int);
00747 }
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764 template <typename RESULTSET>
00765 void findNeighbors(RESULTSET& result, const ElementType* vec, const SearchParams& searchParams) const
00766 {
00767 float epsError = 1+searchParams.eps;
00768
00769 std::vector<DistanceType> dists( (DIM>0 ? DIM : dim) ,0);
00770 DistanceType distsq = computeInitialDistances(vec, dists);
00771 int count_leaf = 0;
00772 searchLevel(result, vec, root_node, distsq, dists, epsError,count_leaf);
00773 }
00774
00775
00776
00777
00778
00779
00780 inline void knnSearch(const ElementType *query_point, int num_closest, int *out_indices, ElementType *out_distances_sq, const int nChecks = 10) const
00781 {
00782 nanoflann::KNNResultSet<ElementType> resultSet(num_closest);
00783 resultSet.init(out_indices, out_distances_sq);
00784 this->findNeighbors(resultSet, query_point, nanoflann::SearchParams(nChecks));
00785 }
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799 size_t radiusSearch(const ElementType *query_point,const DistanceType radius, std::vector<std::pair<int,DistanceType> >& IndicesDists, const SearchParams& searchParams) const
00800 {
00801 RadiusResultSet<DistanceType> resultSet(radius,IndicesDists);
00802 this->findNeighbors(resultSet, query_point, searchParams);
00803
00804 if (searchParams.sorted)
00805 std::sort(IndicesDists.begin(),IndicesDists.end(), IndexDist_Sorter<DistanceType>() );
00806
00807 return resultSet.size();
00808 }
00809
00810
00811
00812 private:
00813
00814
00815 inline ElementType dataset_get(size_t idx, int component) const {
00816 return dataset.kdtree_get_pt(idx,component);
00817 }
00818
00819
00820 void save_tree(FILE* stream, NodePtr tree)
00821 {
00822 save_value(stream, *tree);
00823 if (tree->child1!=NULL) {
00824 save_tree(stream, tree->child1);
00825 }
00826 if (tree->child2!=NULL) {
00827 save_tree(stream, tree->child2);
00828 }
00829 }
00830
00831
00832 void load_tree(FILE* stream, NodePtr& tree)
00833 {
00834 tree = pool.allocate<Node>();
00835 load_value(stream, *tree);
00836 if (tree->child1!=NULL) {
00837 load_tree(stream, tree->child1);
00838 }
00839 if (tree->child2!=NULL) {
00840 load_tree(stream, tree->child2);
00841 }
00842 }
00843
00844
00845 void computeBoundingBox(BoundingBox& bbox)
00846 {
00847 bbox.resize((DIM>0 ? DIM : dim));
00848 if (dataset.kdtree_get_bbox(bbox))
00849 {
00850
00851 }
00852 else
00853 {
00854 for (int i=0; i<(DIM>0 ? DIM : dim); ++i) {
00855 bbox[i].low =
00856 bbox[i].high = dataset_get(0,i);
00857 }
00858 const size_t N = dataset.kdtree_get_point_count();
00859 for (size_t k=1; k<N; ++k) {
00860 for (int i=0; i<(DIM>0 ? DIM : dim); ++i) {
00861 if (dataset_get(k,i)<bbox[i].low) bbox[i].low = dataset_get(k,i);
00862 if (dataset_get(k,i)>bbox[i].high) bbox[i].high = dataset_get(k,i);
00863 }
00864 }
00865 }
00866 }
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878 NodePtr divideTree(int left, int right, BoundingBox& bbox)
00879 {
00880 NodePtr node = pool.allocate<Node>();
00881
00882
00883 if ( (right-left) <= leaf_max_size_) {
00884 node->child1 = node->child2 = NULL;
00885 node->lr.left = left;
00886 node->lr.right = right;
00887
00888
00889 for (int i=0; i<(DIM>0 ? DIM : dim); ++i) {
00890 bbox[i].low = dataset_get(vind[left],i);
00891 bbox[i].high = dataset_get(vind[left],i);
00892 }
00893 for (int k=left+1; k<right; ++k) {
00894 for (int i=0; i<(DIM>0 ? DIM : dim); ++i) {
00895 if (bbox[i].low>dataset_get(vind[k],i)) bbox[i].low=dataset_get(vind[k],i);
00896 if (bbox[i].high<dataset_get(vind[k],i)) bbox[i].high=dataset_get(vind[k],i);
00897 }
00898 }
00899 }
00900 else {
00901 int idx;
00902 int cutfeat;
00903 DistanceType cutval;
00904 middleSplit_(&vind[0]+left, right-left, idx, cutfeat, cutval, bbox);
00905
00906 node->sub.divfeat = cutfeat;
00907
00908 BoundingBox left_bbox(bbox);
00909 left_bbox[cutfeat].high = cutval;
00910 node->child1 = divideTree(left, left+idx, left_bbox);
00911
00912 BoundingBox right_bbox(bbox);
00913 right_bbox[cutfeat].low = cutval;
00914 node->child2 = divideTree(left+idx, right, right_bbox);
00915
00916 node->sub.divlow = left_bbox[cutfeat].high;
00917 node->sub.divhigh = right_bbox[cutfeat].low;
00918
00919 for (int i=0; i<(DIM>0 ? DIM : dim); ++i) {
00920 bbox[i].low = std::min(left_bbox[i].low, right_bbox[i].low);
00921 bbox[i].high = std::max(left_bbox[i].high, right_bbox[i].high);
00922 }
00923 }
00924
00925 return node;
00926 }
00927
00928 void computeMinMax(int* ind, int count, int element, ElementType& min_elem, ElementType& max_elem)
00929 {
00930 min_elem = dataset_get(ind[0],element);
00931 max_elem = dataset_get(ind[0],element);
00932 for (int i=1; i<count; ++i) {
00933 ElementType val = dataset_get(ind[i],element);
00934 if (val<min_elem) min_elem = val;
00935 if (val>max_elem) max_elem = val;
00936 }
00937 }
00938
00939 void middleSplit(int* ind, int count, int& index, int& cutfeat, DistanceType& cutval, const BoundingBox& bbox)
00940 {
00941
00942 ElementType max_span = bbox[0].high-bbox[0].low;
00943 cutfeat = 0;
00944 cutval = (bbox[0].high+bbox[0].low)/2;
00945 for (size_t i=1; i<(DIM>0 ? DIM : dim); ++i) {
00946 ElementType span = bbox[i].low-bbox[i].low;
00947 if (span>max_span) {
00948 max_span = span;
00949 cutfeat = i;
00950 cutval = (bbox[i].high+bbox[i].low)/2;
00951 }
00952 }
00953
00954
00955 ElementType min_elem, max_elem;
00956 computeMinMax(ind, count, cutfeat, min_elem, max_elem);
00957 cutval = (min_elem+max_elem)/2;
00958 max_span = max_elem - min_elem;
00959
00960
00961 size_t k = cutfeat;
00962 for (size_t i=0; i<(DIM>0 ? DIM : dim); ++i) {
00963 if (i==k) continue;
00964 ElementType span = bbox[i].high-bbox[i].low;
00965 if (span>max_span) {
00966 computeMinMax(ind, count, i, min_elem, max_elem);
00967 span = max_elem - min_elem;
00968 if (span>max_span) {
00969 max_span = span;
00970 cutfeat = i;
00971 cutval = (min_elem+max_elem)/2;
00972 }
00973 }
00974 }
00975 int lim1, lim2;
00976 planeSplit(ind, count, cutfeat, cutval, lim1, lim2);
00977
00978 if (lim1>count/2) index = lim1;
00979 else if (lim2<count/2) index = lim2;
00980 else index = count/2;
00981 }
00982
00983
00984 void middleSplit_(int* ind, int count, int& index, int& cutfeat, DistanceType& cutval, const BoundingBox& bbox)
00985 {
00986 const DistanceType EPS=static_cast<DistanceType>(0.00001);
00987 ElementType max_span = bbox[0].high-bbox[0].low;
00988 for (int i=1; i<(DIM>0 ? DIM : dim); ++i) {
00989 ElementType span = bbox[i].high-bbox[i].low;
00990 if (span>max_span) {
00991 max_span = span;
00992 }
00993 }
00994 ElementType max_spread = -1;
00995 cutfeat = 0;
00996 for (int i=0; i<(DIM>0 ? DIM : dim); ++i) {
00997 ElementType span = bbox[i].high-bbox[i].low;
00998 if (span>(1-EPS)*max_span) {
00999 ElementType min_elem, max_elem;
01000 computeMinMax(ind, count, cutfeat, min_elem, max_elem);
01001 ElementType spread = max_elem-min_elem;;
01002 if (spread>max_spread) {
01003 cutfeat = i;
01004 max_spread = spread;
01005 }
01006 }
01007 }
01008
01009 DistanceType split_val = (bbox[cutfeat].low+bbox[cutfeat].high)/2;
01010 ElementType min_elem, max_elem;
01011 computeMinMax(ind, count, cutfeat, min_elem, max_elem);
01012
01013 if (split_val<min_elem) cutval = min_elem;
01014 else if (split_val>max_elem) cutval = max_elem;
01015 else cutval = split_val;
01016
01017 int lim1, lim2;
01018 planeSplit(ind, count, cutfeat, cutval, lim1, lim2);
01019
01020 if (lim1>count/2) index = lim1;
01021 else if (lim2<count/2) index = lim2;
01022 else index = count/2;
01023 }
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035 void planeSplit(int* ind, int count, int cutfeat, DistanceType cutval, int& lim1, int& lim2)
01036 {
01037
01038 int left = 0;
01039 int right = count-1;
01040 for (;; ) {
01041 while (left<=right && dataset_get(ind[left],cutfeat)<cutval) ++left;
01042 while (left<=right && dataset_get(ind[right],cutfeat)>=cutval) --right;
01043 if (left>right) break;
01044 std::swap(ind[left], ind[right]);
01045 ++left;
01046 --right;
01047 }
01048
01049
01050
01051 lim1 = left;
01052 right = count-1;
01053 for (;; ) {
01054 while (left<=right && dataset_get(ind[left],cutfeat)<=cutval) ++left;
01055 while (left<=right && dataset_get(ind[right],cutfeat)>cutval) --right;
01056 if (left>right) break;
01057 std::swap(ind[left], ind[right]);
01058 ++left;
01059 --right;
01060 }
01061 lim2 = left;
01062 }
01063
01064 DistanceType computeInitialDistances(const ElementType* vec, std::vector<DistanceType>& dists) const
01065 {
01066 DistanceType distsq = 0.0;
01067
01068 for (int i = 0; i < (DIM>0 ? DIM : dim); ++i) {
01069 if (vec[i] < root_bbox[i].low) {
01070 dists[i] = distance.accum_dist(vec[i], root_bbox[i].low, i);
01071 distsq += dists[i];
01072 }
01073 if (vec[i] > root_bbox[i].high) {
01074 dists[i] = distance.accum_dist(vec[i], root_bbox[i].high, i);
01075 distsq += dists[i];
01076 }
01077 }
01078
01079 return distsq;
01080 }
01081
01082
01083
01084
01085
01086 template <class RESULTSET>
01087 void searchLevel(RESULTSET& result_set, const ElementType* vec, const NodePtr node, DistanceType mindistsq,
01088 std::vector<DistanceType>& dists, const float epsError, int &count_leaf) const
01089 {
01090
01091 if ((node->child1 == NULL)&&(node->child2 == NULL)) {
01092 count_leaf += (node->lr.right-node->lr.left);
01093 DistanceType worst_dist = result_set.worstDist();
01094 for (int i=node->lr.left; i<node->lr.right; ++i) {
01095 int index = vind[i];
01096 DistanceType dist = distance(vec, index, (DIM>0 ? DIM : dim));
01097 if (dist<worst_dist) {
01098 result_set.addPoint(dist,vind[i]);
01099 }
01100 }
01101 return;
01102 }
01103
01104
01105 int idx = node->sub.divfeat;
01106 ElementType val = vec[idx];
01107 DistanceType diff1 = val - node->sub.divlow;
01108 DistanceType diff2 = val - node->sub.divhigh;
01109
01110 NodePtr bestChild;
01111 NodePtr otherChild;
01112 DistanceType cut_dist;
01113 if ((diff1+diff2)<0) {
01114 bestChild = node->child1;
01115 otherChild = node->child2;
01116 cut_dist = distance.accum_dist(val, node->sub.divhigh, idx);
01117 }
01118 else {
01119 bestChild = node->child2;
01120 otherChild = node->child1;
01121 cut_dist = distance.accum_dist( val, node->sub.divlow, idx);
01122 }
01123
01124
01125 searchLevel(result_set, vec, bestChild, mindistsq, dists, epsError,count_leaf);
01126
01127 DistanceType dst = dists[idx];
01128 mindistsq = mindistsq + cut_dist - dst;
01129 dists[idx] = cut_dist;
01130 if (mindistsq*epsError<=result_set.worstDist()) {
01131 searchLevel(result_set, vec, otherChild, mindistsq, dists, epsError,count_leaf);
01132 }
01133 dists[idx] = dst;
01134 }
01135
01136
01137 void saveIndex(FILE* stream)
01138 {
01139 save_value(stream, size_);
01140 save_value(stream, dim);
01141 save_value(stream, root_bbox);
01142 save_value(stream, leaf_max_size_);
01143 save_value(stream, vind);
01144 save_tree(stream, root_node);
01145 }
01146
01147 void loadIndex(FILE* stream)
01148 {
01149 load_value(stream, size_);
01150 load_value(stream, dim);
01151 load_value(stream, root_bbox);
01152 load_value(stream, leaf_max_size_);
01153 load_value(stream, vind);
01154 load_tree(stream, root_node);
01155 }
01156
01157 };
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178 template <class MatrixType, int DIM = -1, class Distance = nanoflann::metric_L2>
01179 struct KDTreeEigenMatrixAdaptor
01180 {
01181 typedef KDTreeEigenMatrixAdaptor<MatrixType,DIM,Distance> self_t;
01182 typedef typename MatrixType::Scalar num_t;
01183 typedef typename Distance::template traits<num_t,self_t>::distance_t metric_t;
01184 typedef KDTreeSingleIndexAdaptor< metric_t,self_t,DIM> index_t;
01185
01186 index_t* index;
01187
01188
01189 KDTreeEigenMatrixAdaptor(const int dimensionality, const MatrixType &mat, const int leaf_max_size = 10) : m_data_matrix(mat)
01190 {
01191 const size_t dims = mat.cols();
01192 if (DIM>0 && static_cast<int>(dims)!=DIM)
01193 throw std::runtime_error("Data set dimensionality does not match the 'DIM' template argument");
01194 index = new index_t( dims, *this , nanoflann::KDTreeSingleIndexAdaptorParams(leaf_max_size, dims ) );
01195 index->buildIndex();
01196 }
01197
01198 ~KDTreeEigenMatrixAdaptor() {
01199 delete index;
01200 }
01201
01202 const MatrixType &m_data_matrix;
01203
01204
01205
01206
01207
01208 inline void query(const num_t *query_point, int num_closest, int *out_indices, num_t *out_distances_sq, const int nChecks = 10) const
01209 {
01210 nanoflann::KNNResultSet<typename MatrixType::Scalar> resultSet(num_closest);
01211 resultSet.init(out_indices, out_distances_sq);
01212 index->findNeighbors(resultSet, query_point, nanoflann::SearchParams(nChecks));
01213 }
01214
01215
01216
01217
01218 const self_t & derived() const {
01219 return *this;
01220 }
01221 self_t & derived() {
01222 return *this;
01223 }
01224
01225
01226 inline size_t kdtree_get_point_count() const {
01227 return m_data_matrix.rows();
01228 }
01229
01230
01231 inline num_t kdtree_distance(const num_t *p1, const size_t idx_p2,size_t size) const
01232 {
01233 num_t s=0;
01234 for (size_t i=0; i<size; i++) {
01235 const num_t d= p1[i]-m_data_matrix.coeff(idx_p2,i);
01236 s+=d*d;
01237 }
01238 return s;
01239 }
01240
01241
01242 inline num_t kdtree_get_pt(const size_t idx, int dim) const {
01243 return m_data_matrix.coeff(idx,dim);
01244 }
01245
01246
01247
01248
01249 template <class BBOX>
01250 bool kdtree_get_bbox(BBOX &bb) const {
01251 return false;
01252 }
01253
01254
01255
01256 };
01257
01258
01259
01260 }
01261
01262
01263 #endif