FairRoot/PandaRoot
kdtree.h
Go to the documentation of this file.
1 #ifndef __KDTREE_HPP
2 #define __KDTREE_HPP
3 
4 // (c) Matthew B. Kennel, Institute for Nonlinear Science, UCSD (2004)
5 //
6 // Licensed under the Academic Free License version 1.1 found in file LICENSE
7 // with additional provisions in that same file.
8 //
9 // Implement a kd tree for fast searching of points in a fixed data base
10 // in k-dimensional Euclidean space.
11 
12 #include <vector>
13 #include <algorithm>
14 
15 #include <boost/multi_array.hpp>
16 #include <boost/array.hpp>
17 
18 namespace kdtree {
19 
20  typedef boost::multi_array<double, 2> KDTreeArray;
21  typedef boost::const_multi_array_ref<double, 2> KDTreeROArray;
22 
23  typedef struct {
24  double lower, upper;
25  } interval;
26 
27  // let the compiler know that this is a names of classes.
28  class KDTreeNode;
29  class SearchRecord;
30 
31  struct KDTreeResult {
32  public:
33  double dis; // square distance
34  int idx; // neighbor index
35  };
36 
37  class KDTreeResultVector : public std::vector<KDTreeResult> {
38  // inherit a std::vector<KDTreeResult>
39  // but, optionally maintain it in heap form as a priority
40  // queue.
41  public:
42 
43  //
44  // add one new element to the list of results, and
45  // keep it in heap order. To keep it in ordinary, as inserted,
46  // order, then simply use push_back() as inherited
47  // via std::vector<>
48 
51 
52  double max_value();
53  // return the distance which has the maximum value of all on list,
54  // assuming that ALL insertions were made by
55  // push_element_and_heapify()
56  };
57 
58  class KDTree {
59  public:
61  // "the_data" is a reference to the underlying multi_array of the
62  // data to be included in the tree.
63  //
64  // NOTE: this structure does *NOT* own the storage underlying this.
65  // Hence, it would be a very bad idea to change the underlying data
66  // during use of the search facilities of this tree.
67  // Also, the user must deallocate the memory underlying it.
68 
69 
70  const int N; // number of data points
71  int dim;
72  bool sort_results; // sorting result?
73  const bool rearrange; // are we rearranging?
74 
75  public:
76 
77  // constructor, has optional 'dim_in' feature, to use only
78  // first 'dim_in' components for definition of nearest neighbors.
79  KDTree(KDTreeArray& data_in, bool rearrange_in = true, int dim_in=-1);
80 
81  // destructor
82  ~KDTree();
83 
84 
85  public:
86 
87  void n_nearest_brute_force(std::vector<double>& qv, int nn, KDTreeResultVector& result);
88  // search for n nearest to a given query vector 'qv' usin
89  // exhaustive slow search. For debugging, usually.
90 
91  void n_nearest(std::vector<double>& qv, int nn, KDTreeResultVector& result);
92  // search for n nearest to a given query vector 'qv'.
93 
94  void n_nearest_around_point(int idxin, int correltime, int nn,
95  KDTreeResultVector& result);
96  // search for 'nn' nearest to point [idxin] of the input data, excluding
97  // neighbors within correltime
98 
99  void r_nearest(std::vector<double>& qv, double r2, KDTreeResultVector& result);
100  // search for all neighbors in ball of size (square Euclidean distance)
101  // r2. Return number of neighbors in 'result.size()',
102 
103  void r_nearest_around_point(int idxin, int correltime, double r2,
104  KDTreeResultVector& result);
105  // like 'r_nearest', but around existing point, with decorrelation
106  // interval.
107 
108  int r_count(std::vector<double>& qv, double r2);
109  // count number of neighbors within square distance r2.
110 
111  int r_count_around_point(int idxin, int correltime, double r2);
112  // like r_count, c
113 
114  friend class KDTreeNode;
115  friend class SearchRecord;
116 
117  private:
118 
119  KDTreeNode* root; // the root pointer
120 
122  // pointing either to the_data or an internal
123  // rearranged data as necessary
124 
125  std::vector<int> ind;
126  // the index for the tree leaves. Data in a leaf with bounds [l,u] are
127  // in 'the_data[ind[l],*] to the_data[ind[u],*]
128 
130  // if rearrange is true then this is the rearranged data storage.
131 
132  // no of points per node, standard was 12
133  static const int bucketsize = 120; // global constant.
134 
135  private:
136  void set_data(KDTreeArray& din);
137  void build_tree(); // builds the tree. Used upon construction.
138  KDTreeNode* build_tree_for_range(int l, int u, KDTreeNode* parent);
139  void select_on_coordinate(int c, int k, int l, int u);
140  int select_on_coordinate_value(int c, double alpha, int l, int u);
141  void spread_in_coordinate(int c, int l, int u, interval& interv);
142  };
143 
144  class KDTreeNode {
145  public:
146  KDTreeNode(int dim);
147  ~KDTreeNode();
148 
149  private:
150  // visible to self and KDTree.
151  friend class KDTree; // allow kdtree to access private data
152 
153  int cut_dim; // dimension to cut;
154  double cut_val, cut_val_left, cut_val_right; //cut value
155  int l, u; // extents in index array for searching
156 
157  std::vector<interval> box; // [min,max] of the box enclosing all points
158 
159  KDTreeNode *left, *right; // pointers to left and right nodes.
160 
161  void search(SearchRecord& sr);
162  // recursive innermost core routine for searching..
163 
164  bool box_in_search_range(SearchRecord& sr);
165  // return true if the bounding box for this node is within the
166  // search range given by the searchvector and maximum ballsize in 'sr'.
167 
168  void check_query_in_bound(SearchRecord& sr); // debugging only
169 
170  // for processing final buckets.
171  void process_terminal_node(SearchRecord& sr);
172  void process_terminal_node_fixedball(SearchRecord& sr);
173  };
174 
175 } // namespace kdtree
176 
177 #endif
boost::multi_array< double, 2 > KDTreeArray
Definition: kdtree.h:20
friend class SearchRecord
Definition: kdtree.h:115
void r_nearest_around_point(int idxin, int correltime, double r2, KDTreeResultVector &result)
std::vector< int > ind
Definition: kdtree.h:125
KDTree(KDTreeArray &data_in, bool rearrange_in=true, int dim_in=-1)
const int N
Definition: kdtree.h:70
KDTreeNode * build_tree_for_range(int l, int u, KDTreeNode *parent)
void n_nearest_brute_force(std::vector< double > &qv, int nn, KDTreeResultVector &result)
double upper
Definition: kdtree.h:24
KDTreeNode * left
Definition: kdtree.h:159
const KDTreeArray * data
Definition: kdtree.h:121
void n_nearest(std::vector< double > &qv, int nn, KDTreeResultVector &result)
const bool rearrange
Definition: kdtree.h:73
bool sort_results
Definition: kdtree.h:72
KDTreeArray rearranged_data
Definition: kdtree.h:129
void check_query_in_bound(SearchRecord &sr)
void spread_in_coordinate(int c, int l, int u, interval &interv)
KDTreeNode * right
Definition: kdtree.h:159
double cut_val_left
Definition: kdtree.h:154
double replace_maxpri_elt_return_new_maxpri(KDTreeResult &)
KDTreeNode * root
Definition: kdtree.h:119
bool box_in_search_range(SearchRecord &sr)
const KDTreeArray & the_data
Definition: kdtree.h:60
int r_count_around_point(int idxin, int correltime, double r2)
void select_on_coordinate(int c, int k, int l, int u)
void set_data(KDTreeArray &din)
static const int bucketsize
Definition: kdtree.h:133
void push_element_and_heapify(KDTreeResult &)
void search(SearchRecord &sr)
void n_nearest_around_point(int idxin, int correltime, int nn, KDTreeResultVector &result)
void process_terminal_node(SearchRecord &sr)
double cut_val
Definition: kdtree.h:154
double cut_val_right
Definition: kdtree.h:154
int select_on_coordinate_value(int c, double alpha, int l, int u)
void r_nearest(std::vector< double > &qv, double r2, KDTreeResultVector &result)
void process_terminal_node_fixedball(SearchRecord &sr)
int r_count(std::vector< double > &qv, double r2)
double alpha
Definition: f_Init.h:9
boost::const_multi_array_ref< double, 2 > KDTreeROArray
Definition: kdtree.h:21
std::vector< interval > box
Definition: kdtree.h:157
double r2