aimstil  5.0.5
kdtree.h
Go to the documentation of this file.
1 #ifndef _KDTREE_H_
2 #define _KDTREE_H_
3 
4 // include from STL
5 #include <ostream>
6 
7 // include from BOOST
8 #include <boost/shared_ptr.hpp>
9 #include <boost/type_traits.hpp>
10 
11 // includes from TIL
12 #include "til/numeric_array.h"
13 
14 // includes from TIL
15 #include "binary_tree.h"
16 #include "index_collection.h"
17 
18 namespace til
19 {
20  //---------------------------------------------------------------------------
21 
22  // technical details to initialize result array to -1 only if index type
23  // is integer
24  template < typename _TIndex >
25  inline _TIndex kdtreeDefaultValue() { return _TIndex(); }
26  template < >
27  inline std::size_t kdtreeDefaultValue<std::size_t>()
28  { return std::size_t(-1); }
29 
30  //---------------------------------------------------------------------------
31 
32  namespace
33  {
38  template < typename T >
39  class KDNode
40  {
41  public: // set & get ------------------------------------------------------
42 
43  int dim() const { return m_dim; }
44  int & dim() { return m_dim; }
45 
46  T const & value() const { return m_value; }
47  T & value() { return m_value; }
48 
49  const T & operator()() { return m_value; }
50 
51  operator T () const { return m_value; }
52 
53  private: // data ----------------------------------------------------------
54 
55  T m_value;
56  // The dimension along which the split is done
57  int m_dim;
58  };
59  }
60 
61  //---------------------------------------------------------------------------
62 
63  template < typename T >
64  inline std::ostream & operator<<(std::ostream & os, const KDNode<T> & n)
65  {
66  return os << n.value();
67  }
68 
69  //---------------------------------------------------------------------------
70 
71  //----------//
72  // KDTree //
73  //----------//
74 
75  template < typename TIndex, typename TContainer >
76  class KDTree
77  : public NaryTree< KDNode< TIndex >, 2 >
78  , public index_collection< const TContainer, TIndex >
79  {
80  public: // typedefs ---------------------------------------------------------
81 
83  // For safety reasons, because of multiple inheritance.
84  typedef void Base;
85  typedef TContainer Collection;
86 
87  public: // enums ------------------------------------------------------------
88 
89  enum { LEFT = 0, RIGHT };
90 
91  public: // construtors ------------------------------------------------------
92 
93  KDTree() :
94  NaryTree<KDNode<TIndex>,2>()
95  , index_collection<const TContainer, TIndex>()
96  {}
97 
98  // templated to avoid compilation when used
99  template < typename T_Container >
100  KDTree(const T_Container & c)
101  : NaryTree<KDNode<TIndex>,2>()
102  , index_collection<const TContainer, TIndex>(c)
103  {}
104  };
105 
106  //---------------------------------------------------------------------------
107 
108  //-----------------//
109  // KDTreeFactory //
110  //-----------------//
111 
112  template < typename TKDTree >
114  {
115  public: // typedefs ---------------------------------------------------------
116 
118  typedef typename TKDTree::index_type index_type;
119  typedef typename TKDTree::indexed_type indexed_type;
120  typedef typename TKDTree::Collection Collection;
121  // Of course the real deal is to have KDTreeIndex as a template parameter
122  // of this class
123 
124  public: // constructors -----------------------------------------------------
125 
128  KDTreeFactory(const Collection & v) : m_v(v), m_compare(*this) {}
129 
130  public: // functions --------------------------------------------------------
131 
132  void build(TKDTree & res);
133 
134  private: // classes ---------------------------------------------------------
135 
137  class Coordinate_comparison
138  {
139  public:
140  Coordinate_comparison(const Self & parent) : m_parent(parent) {}
141 
143  template < class TVector >
144  inline bool operator()(const TVector *v1, const TVector *v2)
145  { return (*v1)[m_parent.m_dim] < (*v2)[m_parent.m_dim]; }
146 
148  inline bool operator()(std::size_t i1, std::size_t i2)
149  { return m_parent.m_v[i1][m_parent.m_dim] < m_parent.m_v[i2][m_parent.m_dim];
150  }
151  private:
152  const Self & m_parent;
153  };
154 
155  private: // functions -------------------------------------------------------
156 
165  void
166  genKDIter
167  (
168  typename std::vector<index_type>::iterator left,
169  typename std::vector<index_type>::iterator right,
170  typename TKDTree::iterator iRes,
171  int dim
172  );
173 
175  inline
176  void getIndex(const typename Collection::const_iterator & iV, indexed_type * & vIndex)
177  { vIndex = const_cast<indexed_type*>(&*iV); }
178 
181  inline
182  void getIndex(const typename Collection::const_iterator & iV, std::size_t & vIndex)
183  { vIndex = std::distance(m_v.begin(), iV); }
184 
188  void makeIndexVector(const Collection & v, std::vector<index_type> & vIndex);
189 
190  private: // variables -------------------------------------------------------
191 
193  const Collection & m_v;
194  Coordinate_comparison m_compare;
195  int m_dim;
196  std::vector<index_type> m_vIndex;
197  //KDTree<TIndex> m_kdt;
198  TKDTree *m_pKdt;
199  };
200 
201  //-------------------------------------------------------------------------------------
202 
203  //----------------//
204  // Find_closest //
205  //----------------//
206 
208  // TODO: This should be renamed KDTFinder, or put inside a namespace or something.
209  template < typename TPrecision, typename TKDTree >
211  {
212  public: // typedefs ---------------------------------------------------------
213 
214  typedef typename TKDTree::index_type index_type;
215  typedef typename TKDTree::indexed_type indexed_type;
216 
217  public: // constructors -----------------------------------------------------
218 
220  // TODO: remove reference. People can still put the reference in the template parameters if needed, I think.
221  Find_closest(const TKDTree & kdtree) : m_pKdt(&kdtree), m_niter(0) {}
222 
223  public: // functions --------------------------------------------------------
224 
226  index_type operator()(const indexed_type & vec);
228  int niter() { return m_niter; }
229 
230  private: // functions -------------------------------------------------------
231 
232  void init();
233  void lookMax(typename TKDTree::const_iterator iNode);
234 
235  private: // data ------------------------------------------------------------
236 
237  const TKDTree * m_pKdt;
238  indexed_type m_vec;
239  TPrecision m_min;
240  index_type m_minIndex;
241  int m_niter;
242  };
243 
244  //---------------------------------------------------------------------------
245 
246  template < typename T, typename TIndex, typename TContainer >
247  inline void makeKDTree(const std::vector<T> & v,
249  {
251  kf.build(res);
252  }
253 
254  //---------------------------------------------------------------------------
255 
257  template < typename TPrecision, typename TKDTree >
258  inline
259  typename TKDTree::index_type
260  find_closest(const TKDTree & kdtree, const typename TKDTree::indexed_type & vec)
261  {
263  return fc.doit(vec);
264  }
265 
266 } // namespace til
267 
268 #include "kdtree.tpp"
269 
270 #endif //_KDTREE_H_
271 
void build(TKDTree &res)
KDTree< TIndex, TContainer > Self
Definition: kdtree.h:82
int niter()
Return the number of iterations taken by the last search.
Definition: kdtree.h:228
KDTree(const T_Container &c)
Definition: kdtree.h:100
void Base
Definition: kdtree.h:84
Belongs to package Box Do not include directly, include til/Box.h instead.
Definition: Accumulator.h:10
TKDTree::index_type find_closest(const TKDTree &kdtree, const typename TKDTree::indexed_type &vec)
Returns the closest point to vec in kdtree.
Definition: kdtree.h:260
_TIndex kdtreeDefaultValue()
Definition: kdtree.h:25
TKDTree::index_type index_type
Definition: kdtree.h:118
TKDTree::indexed_type indexed_type
Definition: kdtree.h:215
KDTreeFactory(const Collection &v)
Initialize the factory with the collection of which we want to compute the KDTree.
Definition: kdtree.h:128
TKDTree::index_type index_type
Definition: kdtree.h:214
void makeKDTree(const std::vector< T > &v, KDTree< TIndex, TContainer > &res)
Definition: kdtree.h:247
Find_closest(const TKDTree &kdtree)
Provide input kdtree.
Definition: kdtree.h:221
A class to find a KDTree point closest to an input point.
Definition: kdtree.h:210
TKDTree::Collection Collection
Definition: kdtree.h:120
boost::enable_if_c< boost::is_same< TIndex, std::size_t >::value &&!boost::is_same< TPointer, std::size_t >::value, TIndex >::type getIndex(const std::vector< T, TAlloc > &c, TPointer pElem)
A class to represent an N-ary tree.
KDTree()
Definition: kdtree.h:93
TKDTree::indexed_type indexed_type
Definition: kdtree.h:119
TContainer Collection
Definition: kdtree.h:85
KDTreeFactory< TKDTree > Self
Definition: kdtree.h:117