⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kdtree2.cpp

📁 kd tree java implementation 2
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//// (c) Matthew B. Kennel, Institute for Nonlinear Science, UCSD (2004)//// Licensed under the Academic Free License version 1.1 found in file LICENSE// with additional provisions in that same file.#include "kdtree2.hpp"#include <algorithm> #include <iostream>// utilityinline float squared(const float x) {  return(x*x);}inline void swap(int& a, int&b) {  int tmp;  tmp = a;  a = b;  b = tmp; }inline void swap(float& a, float&b) {  float tmp;  tmp = a;  a = b;  b = tmp; }////       KDTREE2_RESULT implementation// inline bool operator<(const kdtree2_result& e1, const kdtree2_result& e2) {  return (e1.dis < e2.dis);}////       KDTREE2_RESULT_VECTOR implementation// float kdtree2_result_vector::max_value() {  return( (*begin()).dis ); // very first element}void kdtree2_result_vector::push_element_and_heapify(kdtree2_result& e) {  push_back(e); // what a vector does.  push_heap( begin(), end() ); // and now heapify it, with the new elt.}float kdtree2_result_vector::replace_maxpri_elt_return_new_maxpri(kdtree2_result& e) {  // remove the maximum priority element on the queue and replace it  // with 'e', and return its priority.  //  // here, it means replacing the first element [0] with e, and re heapifying.    pop_heap( begin(), end() );  pop_back();  push_back(e); // insert new  push_heap(begin(), end() );  // and heapify.   return( (*this)[0].dis );}////        KDTREE2 implementation//// constructorkdtree2::kdtree2(kdtree2_array& data_in,bool rearrange_in,int dim_in)  : the_data(data_in),    N  ( data_in.shape()[0] ),    dim( data_in.shape()[1] ),    sort_results(false),    rearrange(rearrange_in),     root(NULL),    data(NULL),    ind(N){  //  // initialize the constant references using this unusual C++  // feature.  //  if (dim_in > 0)     dim = dim_in;    build_tree();  if (rearrange) {    // if we have a rearranged tree.    // allocate the memory for it.     printf("rearranging\n");     rearranged_data.resize( extents[N][dim] );        // permute the data for it.    for (int i=0; i<N; i++) {      for (int j=0; j<dim; j++) {	rearranged_data[i][j] = the_data[ind[i]][j];	// wouldn't F90 be nice here?       }    }    data = &rearranged_data;  } else {    data = &the_data;  }}// destructorkdtree2::~kdtree2() {  delete root;}// building routinesvoid kdtree2::build_tree() {  for (int i=0; i<N; i++) ind[i] = i;   root = build_tree_for_range(0,N-1,NULL); }kdtree2_node* kdtree2::build_tree_for_range(int l, int u, kdtree2_node* parent) {  // recursive function to build   kdtree2_node* node = new kdtree2_node(dim);  // the newly created node.   if (u<l) {    return(NULL); // no data in this node.   }        if ((u-l) <= bucketsize) {    // create a terminal node.     // always compute true bounding box for terminal node.     for (int i=0;i<dim;i++) {      spread_in_coordinate(i,l,u,node->box[i]);    }        node->cut_dim = 0;     node->cut_val = 0.0;    node->l = l;    node->u = u;    node->left = node->right = NULL;      } else {    //    // Compute an APPROXIMATE bounding box for this node.    // if parent == NULL, then this is the root node, and     // we compute for all dimensions.    // Otherwise, we copy the bounding box from the parent for    // all coordinates except for the parent's cut dimension.      // That, we recompute ourself.    //    int c = -1;    float maxspread = 0.0;    int m;     for (int i=0;i<dim;i++) {      if ((parent == NULL) || (parent->cut_dim == i)) {	spread_in_coordinate(i,l,u,node->box[i]);      } else {	node->box[i] = parent->box[i];      }      float spread = node->box[i].upper - node->box[i].lower;       if (spread>maxspread) {	maxspread = spread;	c=i;       }    }    //     // now, c is the identity of which coordinate has the greatest spread    //    if (false) {      m = (l+u)/2;      select_on_coordinate(c,m,l,u);      } else {      float sum;       float average;      if (true) {	sum = 0.0;	for (int k=l; k <= u; k++) {	  sum += the_data[ind[k]][c];	}	average = sum / static_cast<float> (u-l+1);      } else {	// average of top and bottom nodes.	average = (node->box[c].upper + node->box[c].lower)*0.5;       }	      m = select_on_coordinate_value(c,average,l,u);    }    // move the indices around to cut on dim 'c'.    node->cut_dim=c;    node->l = l;    node->u = u;    node->left = build_tree_for_range(l,m,node);    node->right = build_tree_for_range(m+1,u,node);    if (node->right == NULL) {      for (int i=0; i<dim; i++) 	node->box[i] = node->left->box[i];        node->cut_val = node->left->box[c].upper;       node->cut_val_left = node->cut_val_right = node->cut_val;    } else if (node->left == NULL) {      for (int i=0; i<dim; i++) 	node->box[i] = node->right->box[i];       node->cut_val =  node->right->box[c].upper;      node->cut_val_left = node->cut_val_right = node->cut_val;    } else {      node->cut_val_right = node->right->box[c].lower;      node->cut_val_left  = node->left->box[c].upper;      node->cut_val = (node->cut_val_left + node->cut_val_right) / 2.0;       //      // now recompute true bounding box as union of subtree boxes.      // This is now faster having built the tree, being logarithmic in      // N, not linear as would be from naive method.      //      for (int i=0; i<dim; i++) {	node->box[i].upper = max(node->left->box[i].upper,				 node->right->box[i].upper);		node->box[i].lower = min(node->left->box[i].lower,				 node->right->box[i].lower);      }    }  }  return(node);}void kdtree2:: spread_in_coordinate(int c, int l, int u, interval& interv){  // return the minimum and maximum of the indexed data between l and u in  // smin_out and smax_out.  float smin, smax;  float lmin, lmax;  int i;   smin = the_data[ind[l]][c];  smax = smin;    // process two at a time.  for (i=l+2; i<= u; i+=2) {    lmin = the_data[ind[i-1]] [c];    lmax = the_data[ind[i]  ] [c];    if (lmin > lmax) {      swap(lmin,lmax);       //      float t = lmin;      //      lmin = lmax;      //      lmax = t;    }    if (smin > lmin) smin = lmin;    if (smax <lmax) smax = lmax;  }  // is there one more element?   if (i == u+1) {    float last = the_data[ind[u]] [c];    if (smin>last) smin = last;    if (smax<last) smax = last;  }  interv.lower = smin;  interv.upper = smax;  //  printf("Spread in coordinate %d=[%f,%f]\n",c,smin,smax);}void kdtree2::select_on_coordinate(int c, int k, int l, int u) {  //  //  Move indices in ind[l..u] so that the elements in [l .. k]   //  are less than the [k+1..u] elmeents, viewed across dimension 'c'.   //   while (l < u) {    int t = ind[l];    int m = l;    for (int i=l+1; i<=u; i++) {      if ( the_data[ ind[i] ] [c] < the_data[t][c]) {	m++;	swap(ind[i],ind[m]);       }    } // for i     swap(ind[l],ind[m]);    if (m <= k) l = m+1;    if (m >= k) u = m-1;  } // while loop}int kdtree2::select_on_coordinate_value(int c, float alpha, int l, int u) {  //  //  Move indices in ind[l..u] so that the elements in [l .. return]  //  are <= alpha, and hence are less than the [return+1..u]  //  elmeents, viewed across dimension 'c'.  //   int lb = l, ub = u;  while (lb < ub) {    if (the_data[ind[lb]][c] <= alpha) {      lb++; // good where it is.    } else {      swap(ind[lb],ind[ub]);       ub--;    }  }  // here ub=lb  if (the_data[ind[lb]][c] <= alpha)    return(lb);  else    return(lb-1);  }// void kdtree2::dump_data() {//   int upper1, upper2;  //   upper1 = N;//   upper2 = dim;//   printf("Rearrange=%d\n",rearrange);//   printf("N=%d, dim=%d\n", upper1, upper2);//   for (int i=0; i<upper1; i++) {//     printf("the_data[%d][*]=",i); //     for (int j=0; j<upper2; j++)//       printf("%f,",the_data[i][j]); //     printf("\n"); //   }//   for (int i=0; i<upper1; i++)//     printf("Indexes[%d]=%d\n",i,ind[i]); //   for (int i=0; i<upper1; i++) {//     printf("data[%d][*]=",i); //     for (int j=0; j<upper2; j++)//       printf("%f,",(*data)[i][j]); //     printf("\n"); //   }// }//// search record substructure//// one of these is created for each search.// this holds useful information  to be used// during the searchstatic const float infinity = 1.0e38;class searchrecord {private:  friend class kdtree2;  friend class kdtree2_node;  vector<float>& qv;   int dim;  bool rearrange;  unsigned int nn; // , nfound;  float ballsize;  int centeridx, correltime;  kdtree2_result_vector& result;  // results  const kdtree2_array* data;   const vector<int>& ind;   // constructorpublic:  searchrecord(vector<float>& qv_in, kdtree2& tree_in,	       kdtree2_result_vector& result_in) :      qv(qv_in),    result(result_in),    data(tree_in.data),    ind(tree_in.ind)   {    dim = tree_in.dim;    rearrange = tree_in.rearrange;    ballsize = infinity;     nn = 0;   };};void kdtree2::n_nearest_brute_force(vector<float>& qv, int nn, kdtree2_result_vector& result) {  result.clear();  for (int i=0; i<N; i++) {    float dis = 0.0;    kdtree2_result e; 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -