28   struct kdtree_leaf : 
public kdtree_elt_base {
 
   29     kdtree_tab_type::const_iterator it;
 
   30     kdtree_leaf(kdtree_tab_type::const_iterator begin, 
 
   31                 kdtree_tab_type::const_iterator end) : 
 
   32       kdtree_elt_base(unsigned(std::distance(begin,end))) { it = begin; }
 
   35   struct kdtree_node : 
public kdtree_elt_base {
 
   37     std::unique_ptr<kdtree_elt_base> left, right; 
 
   38     kdtree_node(scalar_type v, std::unique_ptr<kdtree_elt_base> &&left_,
 
   39                 std::unique_ptr<kdtree_elt_base> &&right_) : 
 
   40       kdtree_elt_base(0), split_v(v),
 
   41       left(std::move(left_)), right(std::move(right_)) {}
 
   44   typedef kdtree_tab_type::iterator ITER;
 
   47   struct component_sort {
 
   49     component_sort(
unsigned d) : dir(d) {}
 
   50     bool operator()(
const index_node_pair& a, 
const index_node_pair& b) 
 
   51     { 
return a.n.at(dir) < b.n.at(dir); }
 
   62   static ITER partition(ITER begin, ITER end, 
unsigned dir, scalar_type median) {
 
   65       while (begin <= end && (*begin).n.at(dir) <= median) ++begin; 
 
   66       while (begin <= end && (*end).n.at(dir) > median) --end;
 
   67       if (begin < end) { begin->swap(*end); ++begin; --end; } 
else break;
 
   76   static std::unique_ptr<kdtree_elt_base> build_tree_(ITER begin,
 
   77                                                       ITER end, 
unsigned dir) {
 
   78     if (begin == end) 
return 0;
 
   79     size_type npts = std::distance(begin,end);
 
   80     if (npts > kdtree_elt_base::PTS_PER_LEAF) {
 
   84       unsigned ndir_tests = unsigned(dir/N); dir = unsigned(dir % N);
 
   87         std::vector<index_node_pair> v(30);
 
   90           v[i] = begin[rand() % npts];
 
   91         std::sort(v.begin(), v.end(), component_sort(dir));
 
   92         median = (v[v.size()/2-1].n.at(dir)+v[v.size()/2].n.at(dir))/2;
 
   94         itmedian = partition(begin,end,dir,median);
 
  103         std::sort(begin, end, component_sort(dir));
 
  104         itmedian = begin + npts/2 - 1;
 
  105         median = (*itmedian).n[dir];
 
  106         while (itmedian < end && (*itmedian).n[dir] == median) itmedian++;
 
  109         if (ndir_tests == N-1) 
 
  110           return std::make_unique<kdtree_leaf>(begin,end); 
 
  111         else return std::make_unique<kdtree_node>
 
  113                 build_tree_(begin, itmedian, 
unsigned((dir+1)%N + (ndir_tests+1)*N)), std::unique_ptr<kdtree_node>());
 
  115         assert((*itmedian).n[dir] >= median && median >= (*(itmedian-1)).n[dir]);
 
  116         return std::make_unique<kdtree_node>
 
  117           (median, build_tree_(begin, itmedian, 
unsigned((dir+1)%N)), 
 
  118            build_tree_(itmedian,end, 
unsigned((dir+1)%N)));
 
  121       return std::make_unique<kdtree_leaf>(begin,end);
 
  126   struct points_in_box_data_ {
 
  127     base_node::const_iterator bmin;
 
  128     base_node::const_iterator bmax;
 
  134   static void points_in_box_(
const points_in_box_data_& p,
 
  135                              const kdtree_elt_base *t, 
unsigned dir) {
 
  137       const kdtree_node *tn = 
static_cast<const kdtree_node*
>(t);
 
  138       if (p.bmin[dir] <= tn->split_v && tn->left.get())
 
  139         points_in_box_(p, tn->left.get(), unsigned((dir+1)%p.N));
 
  140       if (p.bmax[dir] > tn->split_v && tn->right)
 
  141         points_in_box_(p, tn->right.get(), 
unsigned((dir+1)%p.N));
 
  143       const kdtree_leaf *tl = 
static_cast<const kdtree_leaf*
>(t);
 
  144       kdtree_tab_type::const_iterator itpt = tl->it;
 
  147         base_node::const_iterator it=itpt->n.const_begin();
 
  150           if (it[k] < p.bmin[k] || it[k] > p.bmax[k]) {
 
  151             is_in = 
false; 
break; 
 
  154         if (is_in) p.ipts->push_back(*itpt);
 
  160   struct nearest_neighbor_data_ {
 
  161     base_node::const_iterator pos;
 
  162     index_node_pair *ipt;
 
  164     mutable scalar_type dist2;
 
  165     base_node::iterator vec_to_tree_elm;
 
  169   static void nearest_neighbor_assist(
const nearest_neighbor_data_& p,
 
  170                                       const kdtree_elt_base *t, 
unsigned dir) {
 
  171     scalar_type dist2(0);
 
  173       dist2 += p.vec_to_tree_elm[k] * p.vec_to_tree_elm[k];
 
  174     if (dist2 > p.dist2 && p.dist2 > scalar_type(0)) 
return;
 
  177       const kdtree_node *tn = 
static_cast<const kdtree_node*
>(t);
 
  178       scalar_type tmp = p.vec_to_tree_elm[dir];
 
  179       scalar_type dist = p.pos[dir] - tn->split_v;
 
  180       if (tn->left.get()) {
 
  181         if (dist > tmp) p.vec_to_tree_elm[dir] = dist;
 
  182         nearest_neighbor_assist(p, tn->left.get(), 
unsigned((dir+1)%p.N));
 
  183         p.vec_to_tree_elm[dir] = tmp;
 
  186         if (-dist > tmp) p.vec_to_tree_elm[dir] = -dist;
 
  187         nearest_neighbor_assist(p, tn->right.get(), 
unsigned((dir+1)%p.N));
 
  188         p.vec_to_tree_elm[dir] = tmp;
 
  192       const kdtree_leaf *tl = 
static_cast<const kdtree_leaf*
>(t);
 
  193       kdtree_tab_type::const_iterator itpt = tl->it;
 
  195         dist2 = scalar_type(0);
 
  196         base_node::const_iterator it=itpt->n.const_begin();
 
  198           scalar_type dist = it[k] - p.pos[k];
 
  199           dist2 += dist * dist;
 
  201         if (dist2 < p.dist2 || p.dist2 < scalar_type(0)){
 
  209   static void nearest_neighbor_main(
const nearest_neighbor_data_& p,
 
  210                                     const kdtree_elt_base *t, 
unsigned dir) {
 
  212       const kdtree_node *tn = 
static_cast<const kdtree_node*
>(t);
 
  213       scalar_type dist = p.pos[dir] - tn->split_v;
 
  214       if ((dist <= scalar_type(0) && tn->left.get()) || !tn->right.get()) {
 
  215         nearest_neighbor_main(p, tn->left.get(), 
unsigned((dir+1)%p.N));
 
  216       } 
else if (tn->right.get()) {
 
  217         nearest_neighbor_main(p, tn->right.get(), 
unsigned((dir+1)%p.N));
 
  223       if (dist * dist <= p.dist2) {
 
  224         for (
size_type k=0; k < p.N; ++k) p.vec_to_tree_elm[k] = 0.;
 
  225         if ((dist <= scalar_type(0) && tn->right.get()) || !tn->left.get()) {
 
  226           p.vec_to_tree_elm[dir] = -dist;
 
  227           nearest_neighbor_assist(p, tn->right.get(), 
unsigned((dir+1)%p.N));
 
  228         } 
else if (tn->left.get()) {
 
  229           p.vec_to_tree_elm[dir] = dist;
 
  230           nearest_neighbor_assist(p, tn->left.get(), 
unsigned((dir+1)%p.N));
 
  235       nearest_neighbor_assist(p, t, dir);
 
  239   void kdtree::clear_tree() { tree = std::unique_ptr<kdtree_elt_base>(); }
 
  242                              const base_node &min, 
 
  243                              const base_node &max) {
 
  245     if (tree == 0) { tree = build_tree_(pts.begin(), pts.end(), 0); 
if (!tree) 
return; }
 
  246     base_node bmin(min), bmax(max);
 
  247     for (
size_type i=0; i < bmin.size(); ++i) 
if (bmin[i] > bmax[i]) 
return;
 
  248     points_in_box_data_ p; 
 
  249     p.bmin = bmin.const_begin(); p.bmax = bmax.const_begin();
 
  250     p.ipts = &ipts; p.N = N; 
 
  251     points_in_box_(p, tree.get(), 0);
 
  254   scalar_type kdtree::nearest_neighbor(index_node_pair &ipt,
 
  255                                        const base_node &pos) {
 
  259       tree = build_tree_(pts.begin(), pts.end(), 0);
 
  260       if (!tree) 
return scalar_type(-1);
 
  262     nearest_neighbor_data_ p;
 
  263     p.pos = pos.const_begin();
 
  266     p.dist2 = scalar_type(-1);
 
  268     p.vec_to_tree_elm = tmp.begin();
 
  269     nearest_neighbor_main(p, tree.get(), 0);
 
Simple implementation of a KD-tree.
 
std::vector< index_node_pair > kdtree_tab_type
store a set of points with associated indexes.
 
size_t size_type
used as the common size type in the library