1/*M///////////////////////////////////////////////////////////////////////////////////////
2//
3//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4//
5//  By downloading, copying, installing or using the software you agree to this license.
6//  If you do not agree to this license, do not download, install,
7//  copy or use the software.
8//
9//
10//                        Intel License Agreement
11//                For Open Source Computer Vision Library
12//
13// Copyright (C) 2008, Xavier Delacour, all rights reserved.
14// Third party copyrights are property of their respective owners.
15//
16// Redistribution and use in source and binary forms, with or without modification,
17// are permitted provided that the following conditions are met:
18//
19//   * Redistribution's of source code must retain the above copyright notice,
20//     this list of conditions and the following disclaimer.
21//
22//   * Redistribution's in binary form must reproduce the above copyright notice,
23//     this list of conditions and the following disclaimer in the documentation
24//     and/or other materials provided with the distribution.
25//
26//   * The name of Intel Corporation may not be used to endorse or promote products
27//     derived from this software without specific prior written permission.
28//
29// This software is provided by the copyright holders and contributors "as is" and
30// any express or implied warranties, including, but not limited to, the implied
31// warranties of merchantability and fitness for a particular purpose are disclaimed.
32// In no event shall the Intel Corporation or contributors be liable for any direct,
33// indirect, incidental, special, exemplary, or consequential damages
34// (including, but not limited to, procurement of substitute goods or services;
35// loss of use, data, or profits; or business interruption) however caused
36// and on any theory of liability, whether in contract, strict liability,
37// or tort (including negligence or otherwise) arising in any way out of
38// the use of this software, even if advised of the possibility of such damage.
39//
40//M*/
41
42// 2008-05-13, Xavier Delacour <xavier.delacour@gmail.com>
43
44#ifndef __cv_kdtree_h__
45#define __cv_kdtree_h__
46
47#include "_cv.h"
48
49#include <vector>
50#include <algorithm>
51#include <limits>
52#include <iostream>
53#include "assert.h"
54#include "math.h"
55
56// J.S. Beis and D.G. Lowe. Shape indexing using approximate nearest-neighbor search in highdimensional spaces. In Proc. IEEE Conf. Comp. Vision Patt. Recog., pages 1000--1006, 1997. http://citeseer.ist.psu.edu/beis97shape.html
57#undef __deref
58#undef __valuetype
59
60template < class __valuetype, class __deref >
61class CvKDTree {
62public:
63  typedef __deref deref_type;
64  typedef typename __deref::scalar_type scalar_type;
65  typedef typename __deref::accum_type accum_type;
66
67private:
68  struct node {
69    int dim;			// split dimension; >=0 for nodes, -1 for leaves
70    __valuetype value;		// if leaf, value of leaf
71    int left, right;		// node indices of left and right branches
72    scalar_type boundary;	// left if deref(value,dim)<=boundary, otherwise right
73  };
74  typedef std::vector < node > node_array;
75
76  __deref deref;		// requires operator() (__valuetype lhs,int dim)
77
78  node_array nodes;		// node storage
79  int point_dim;		// dimension of points (the k in kd-tree)
80  int root_node;		// index of root node, -1 if empty tree
81
82  // for given set of point indices, compute dimension of highest variance
83  template < class __instype, class __valuector >
84  int dimension_of_highest_variance(__instype * first, __instype * last,
85				    __valuector ctor) {
86    assert(last - first > 0);
87
88    accum_type maxvar = -std::numeric_limits < accum_type >::max();
89    int maxj = -1;
90    for (int j = 0; j < point_dim; ++j) {
91      accum_type mean = 0;
92      for (__instype * k = first; k < last; ++k)
93	mean += deref(ctor(*k), j);
94      mean /= last - first;
95      accum_type var = 0;
96      for (__instype * k = first; k < last; ++k) {
97	accum_type diff = accum_type(deref(ctor(*k), j)) - mean;
98	var += diff * diff;
99      }
100      var /= last - first;
101
102      assert(maxj != -1 || var >= maxvar);
103
104      if (var >= maxvar) {
105	maxvar = var;
106	maxj = j;
107      }
108    }
109
110    return maxj;
111  }
112
113  // given point indices and dimension, find index of median; (almost) modifies [first,last)
114  // such that points_in[first,median]<=point[median], points_in(median,last)>point[median].
115  // implemented as partial quicksort; expected linear perf.
116  template < class __instype, class __valuector >
117  __instype * median_partition(__instype * first, __instype * last,
118			       int dim, __valuector ctor) {
119    assert(last - first > 0);
120    __instype *k = first + (last - first) / 2;
121    median_partition(first, last, k, dim, ctor);
122    return k;
123  }
124
125  template < class __instype, class __valuector >
126  struct median_pr {
127    const __instype & pivot;
128    int dim;
129    __deref deref;
130    __valuector ctor;
131    median_pr(const __instype & _pivot, int _dim, __deref _deref, __valuector _ctor)
132      : pivot(_pivot), dim(_dim), deref(_deref), ctor(_ctor) {
133    }
134    bool operator() (const __instype & lhs) const {
135      return deref(ctor(lhs), dim) <= deref(ctor(pivot), dim);
136    }
137  };
138
139  template < class __instype, class __valuector >
140  void median_partition(__instype * first, __instype * last,
141			__instype * k, int dim, __valuector ctor) {
142    int pivot = (last - first) / 2;
143
144    std::swap(first[pivot], last[-1]);
145    __instype *middle = std::partition(first, last - 1,
146				       median_pr < __instype, __valuector >
147				       (last[-1], dim, deref, ctor));
148    std::swap(*middle, last[-1]);
149
150    if (middle < k)
151      median_partition(middle + 1, last, k, dim, ctor);
152    else if (middle > k)
153      median_partition(first, middle, k, dim, ctor);
154  }
155
156  // insert given points into the tree; return created node
157  template < class __instype, class __valuector >
158  int insert(__instype * first, __instype * last, __valuector ctor) {
159    if (first == last)
160      return -1;
161    else {
162
163      int dim = dimension_of_highest_variance(first, last, ctor);
164      __instype *median = median_partition(first, last, dim, ctor);
165
166      __instype *split = median;
167      for (; split != last && deref(ctor(*split), dim) ==
168	     deref(ctor(*median), dim); ++split);
169
170      if (split == last) { // leaf
171	int nexti = -1;
172	for (--split; split >= first; --split) {
173	  int i = nodes.size();
174	  node & n = *nodes.insert(nodes.end(), node());
175	  n.dim = -1;
176	  n.value = ctor(*split);
177	  n.left = -1;
178	  n.right = nexti;
179	  nexti = i;
180	}
181
182	return nexti;
183      } else { // node
184	int i = nodes.size();
185	// note that recursive insert may invalidate this ref
186	node & n = *nodes.insert(nodes.end(), node());
187
188	n.dim = dim;
189	n.boundary = deref(ctor(*median), dim);
190
191	int left = insert(first, split, ctor);
192	nodes[i].left = left;
193	int right = insert(split, last, ctor);
194	nodes[i].right = right;
195
196	return i;
197      }
198    }
199  }
200
201  // run to leaf; linear search for p;
202  // if found, remove paths to empty leaves on unwind
203  bool remove(int *i, const __valuetype & p) {
204    if (*i == -1)
205      return false;
206    node & n = nodes[*i];
207    bool r;
208
209    if (n.dim >= 0) { // node
210      if (deref(p, n.dim) <= n.boundary) // left
211	r = remove(&n.left, p);
212      else // right
213	r = remove(&n.right, p);
214
215      // if terminal, remove this node
216      if (n.left == -1 && n.right == -1)
217	*i = -1;
218
219      return r;
220    } else { // leaf
221      if (n.value == p) {
222	*i = n.right;
223	return true;
224      } else
225	return remove(&n.right, p);
226    }
227  }
228
229public:
230  struct identity_ctor {
231    const __valuetype & operator() (const __valuetype & rhs) const {
232      return rhs;
233    }
234  };
235
236  // initialize an empty tree
237  CvKDTree(__deref _deref = __deref())
238    : deref(_deref), root_node(-1) {
239  }
240  // given points, initialize a balanced tree
241  CvKDTree(__valuetype * first, __valuetype * last, int _point_dim,
242	   __deref _deref = __deref())
243    : deref(_deref) {
244    set_data(first, last, _point_dim, identity_ctor());
245  }
246  // given points, initialize a balanced tree
247  template < class __instype, class __valuector >
248  CvKDTree(__instype * first, __instype * last, int _point_dim,
249	   __valuector ctor, __deref _deref = __deref())
250    : deref(_deref) {
251    set_data(first, last, _point_dim, ctor);
252  }
253
254  void set_deref(__deref _deref) {
255    deref = _deref;
256  }
257
258  void set_data(__valuetype * first, __valuetype * last, int _point_dim) {
259    set_data(first, last, _point_dim, identity_ctor());
260  }
261  template < class __instype, class __valuector >
262  void set_data(__instype * first, __instype * last, int _point_dim,
263		__valuector ctor) {
264    point_dim = _point_dim;
265    nodes.clear();
266    nodes.reserve(last - first);
267    root_node = insert(first, last, ctor);
268  }
269
270  int dims() const {
271    return point_dim;
272  }
273
274  // remove the given point
275  bool remove(const __valuetype & p) {
276    return remove(&root_node, p);
277  }
278
279  void print() const {
280    print(root_node);
281  }
282  void print(int i, int indent = 0) const {
283    if (i == -1)
284      return;
285    for (int j = 0; j < indent; ++j)
286      std::cout << " ";
287    const node & n = nodes[i];
288    if (n.dim >= 0) {
289      std::cout << "node " << i << ", left " << nodes[i].left << ", right " <<
290	nodes[i].right << ", dim " << nodes[i].dim << ", boundary " <<
291	nodes[i].boundary << std::endl;
292      print(n.left, indent + 3);
293      print(n.right, indent + 3);
294    } else
295      std::cout << "leaf " << i << ", value = " << nodes[i].value << std::endl;
296  }
297
298  ////////////////////////////////////////////////////////////////////////////////////////
299  // bbf search
300public:
301  struct bbf_nn {		// info on found neighbors (approx k nearest)
302    const __valuetype *p;	// nearest neighbor
303    accum_type dist;		// distance from d to query point
304    bbf_nn(const __valuetype & _p, accum_type _dist)
305      : p(&_p), dist(_dist) {
306    }
307    bool operator<(const bbf_nn & rhs) const {
308      return dist < rhs.dist;
309    }
310  };
311  typedef std::vector < bbf_nn > bbf_nn_pqueue;
312private:
313  struct bbf_node {		// info on branches not taken
314    int node;			// corresponding node
315    accum_type dist;		// minimum distance from bounds to query point
316    bbf_node(int _node, accum_type _dist)
317      : node(_node), dist(_dist) {
318    }
319    bool operator<(const bbf_node & rhs) const {
320      return dist > rhs.dist;
321    }
322  };
323  typedef std::vector < bbf_node > bbf_pqueue;
324  mutable bbf_pqueue tmp_pq;
325
326  // called for branches not taken, as bbf walks to leaf;
327  // construct bbf_node given minimum distance to bounds of alternate branch
328  void pq_alternate(int alt_n, bbf_pqueue & pq, scalar_type dist) const {
329    if (alt_n == -1)
330      return;
331
332    // add bbf_node for alternate branch in priority queue
333    pq.push_back(bbf_node(alt_n, dist));
334    push_heap(pq.begin(), pq.end());
335  }
336
337  // called by bbf to walk to leaf;
338  // takes one step down the tree towards query point d
339  template < class __desctype >
340  int bbf_branch(int i, const __desctype * d, bbf_pqueue & pq) const {
341    const node & n = nodes[i];
342    // push bbf_node with bounds of alternate branch, then branch
343    if (d[n.dim] <= n.boundary) {	// left
344      pq_alternate(n.right, pq, n.boundary - d[n.dim]);
345      return n.left;
346    } else {			// right
347      pq_alternate(n.left, pq, d[n.dim] - n.boundary);
348      return n.right;
349    }
350  }
351
352  // compute euclidean distance between two points
353  template < class __desctype >
354  accum_type distance(const __desctype * d, const __valuetype & p) const {
355    accum_type dist = 0;
356    for (int j = 0; j < point_dim; ++j) {
357      accum_type diff = accum_type(d[j]) - accum_type(deref(p, j));
358      dist += diff * diff;
359    } return (accum_type) sqrt(dist);
360  }
361
362  // called per candidate nearest neighbor; constructs new bbf_nn for
363  // candidate and adds it to priority queue of all candidates; if
364  // queue len exceeds k, drops the point furthest from query point d.
365  template < class __desctype >
366  void bbf_new_nn(bbf_nn_pqueue & nn_pq, int k,
367		  const __desctype * d, const __valuetype & p) const {
368    bbf_nn nn(p, distance(d, p));
369    if ((int) nn_pq.size() < k) {
370      nn_pq.push_back(nn);
371      push_heap(nn_pq.begin(), nn_pq.end());
372    } else if (nn_pq[0].dist > nn.dist) {
373      pop_heap(nn_pq.begin(), nn_pq.end());
374      nn_pq.end()[-1] = nn;
375      push_heap(nn_pq.begin(), nn_pq.end());
376    }
377    assert(nn_pq.size() < 2 || nn_pq[0].dist >= nn_pq[1].dist);
378  }
379
380public:
381  // finds (with high probability) the k nearest neighbors of d,
382  // searching at most emax leaves/bins.
383  // ret_nn_pq is an array containing the (at most) k nearest neighbors
384  // (see bbf_nn structure def above).
385  template < class __desctype >
386  int find_nn_bbf(const __desctype * d,
387		  int k, int emax,
388		  bbf_nn_pqueue & ret_nn_pq) const {
389    assert(k > 0);
390    ret_nn_pq.clear();
391
392    if (root_node == -1)
393      return 0;
394
395    // add root_node to bbf_node priority queue;
396    // iterate while queue non-empty and emax>0
397    tmp_pq.clear();
398    tmp_pq.push_back(bbf_node(root_node, 0));
399    while (tmp_pq.size() && emax > 0) {
400
401      // from node nearest query point d, run to leaf
402      pop_heap(tmp_pq.begin(), tmp_pq.end());
403      bbf_node bbf(tmp_pq.end()[-1]);
404      tmp_pq.erase(tmp_pq.end() - 1);
405
406      int i;
407      for (i = bbf.node;
408	   i != -1 && nodes[i].dim >= 0;
409	   i = bbf_branch(i, d, tmp_pq));
410
411      if (i != -1) {
412
413	// add points in leaf/bin to ret_nn_pq
414	do {
415	  bbf_new_nn(ret_nn_pq, k, d, nodes[i].value);
416	} while (-1 != (i = nodes[i].right));
417
418	--emax;
419      }
420    }
421
422    tmp_pq.clear();
423    return ret_nn_pq.size();
424  }
425
426  ////////////////////////////////////////////////////////////////////////////////////////
427  // orthogonal range search
428private:
429  void find_ortho_range(int i, scalar_type * bounds_min,
430			scalar_type * bounds_max,
431			std::vector < __valuetype > &inbounds) const {
432    if (i == -1)
433      return;
434    const node & n = nodes[i];
435    if (n.dim >= 0) { // node
436      if (bounds_min[n.dim] <= n.boundary)
437	find_ortho_range(n.left, bounds_min, bounds_max, inbounds);
438      if (bounds_max[n.dim] > n.boundary)
439	find_ortho_range(n.right, bounds_min, bounds_max, inbounds);
440    } else { // leaf
441      do {
442	inbounds.push_back(nodes[i].value);
443      } while (-1 != (i = nodes[i].right));
444    }
445  }
446public:
447  // return all points that lie within the given bounds; inbounds is cleared
448  int find_ortho_range(scalar_type * bounds_min,
449		       scalar_type * bounds_max,
450		       std::vector < __valuetype > &inbounds) const {
451    inbounds.clear();
452    find_ortho_range(root_node, bounds_min, bounds_max, inbounds);
453    return inbounds.size();
454  }
455};
456
457#endif // __cv_kdtree_h__
458
459// Local Variables:
460// mode:C++
461// End:
462