kD-tree 的C語言實現 帶有史上最全的註釋和解釋

 
  1. kdtree的原理就是基於二叉樹的形式,將高維空間用超矩形進行劃分.其主要用途是用來求解高維空間中最近鄰的值.  
kdtree的原理就是基於二叉樹的形式,將高維空間用超矩形進行劃分.其主要用途是用來求解高維空間中最近鄰的值.

 

 

下面是kdtree.h文件,是kdtree數據結構的頭文件

  1. #ifndef _KDTREE_H_   
  2. #define _KDTREE_H_   
  3.   
  4. #ifdef __cplusplus   
  5. extern "C" {  
  6. #endif   
  7.   
  8. struct kdtree;  
  9. struct kdres;  
  10.   
  11.   
  12. /* create a kd-tree for "k"-dimensional data */  
  13. struct kdtree *kd_create(int k);  
  14.   
  15. /* free the struct kdtree */  
  16. void kd_free(struct kdtree *tree);  
  17.   
  18. /* remove all the elements from the tree */  
  19. void kd_clear(struct kdtree *tree);  
  20.   
  21. /* if called with non-null 2nd argument, the function provided 
  22.  * will be called on data pointers (see kd_insert) when nodes 
  23.  * are to be removed from the tree. 
  24.  */  
  25. void kd_data_destructor(struct kdtree *tree, void (*destr)(void*));  
  26.   
  27. /* insert a node, specifying its position, and optional data */  
  28. int kd_insert(struct kdtree *tree, const double *pos, void *data);  
  29. int kd_insertf(struct kdtree *tree, const float *pos, void *data);  
  30. int kd_insert3(struct kdtree *tree, double x, double y, double z, void *data);  
  31. int kd_insert3f(struct kdtree *tree, float x, float y, float z, void *data);  
  32.   
  33. /* Find the nearest node from a given point. 
  34.  * 
  35.  * This function returns a pointer to a result set with at most one element. 
  36.  */  
  37. struct kdres *kd_nearest(struct kdtree *tree, const double *pos);  
  38. struct kdres *kd_nearestf(struct kdtree *tree, const float *pos);  
  39. struct kdres *kd_nearest3(struct kdtree *tree, double x, double y, double z);  
  40. struct kdres *kd_nearest3f(struct kdtree *tree, float x, float y, float z);  
  41.   
  42. /* Find the N nearest nodes from a given point. 
  43.  * 
  44.  * This function returns a pointer to a result set, with at most N elements, 
  45.  * which can be manipulated with the kd_res_* functions. 
  46.  * The returned pointer can be null as an indication of an error. Otherwise 
  47.  * a valid result set is always returned which may contain 0 or more elements. 
  48.  * The result set must be deallocated with kd_res_free after use. 
  49.  */  
  50. /* 
  51. struct kdres *kd_nearest_n(struct kdtree *tree, const double *pos, int num); 
  52. struct kdres *kd_nearest_nf(struct kdtree *tree, const float *pos, int num); 
  53. struct kdres *kd_nearest_n3(struct kdtree *tree, double x, double y, double z); 
  54. struct kdres *kd_nearest_n3f(struct kdtree *tree, float x, float y, float z); 
  55. */  
  56.   
  57. /* Find any nearest nodes from a given point within a range. 
  58.  * 
  59.  * This function returns a pointer to a result set, which can be manipulated 
  60.  * by the kd_res_* functions. 
  61.  * The returned pointer can be null as an indication of an error. Otherwise 
  62.  * a valid result set is always returned which may contain 0 or more elements. 
  63.  * The result set must be deallocated with kd_res_free after use. 
  64.  */  
  65. struct kdres *kd_nearest_range(struct kdtree *tree, const double *pos, double range);  
  66. struct kdres *kd_nearest_rangef(struct kdtree *tree, const float *pos, float range);  
  67. struct kdres *kd_nearest_range3(struct kdtree *tree, double x, double y, double z, double range);  
  68. struct kdres *kd_nearest_range3f(struct kdtree *tree, float x, float y, float z, float range);  
  69.   
  70. /* frees a result set returned by kd_nearest_range() */  
  71. void kd_res_free(struct kdres *set);  
  72.   
  73. /* returns the size of the result set (in elements) */  
  74. int kd_res_size(struct kdres *set);  
  75.   
  76. /* rewinds the result set iterator */  
  77. void kd_res_rewind(struct kdres *set);  
  78.   
  79. /* returns non-zero if the set iterator reached the end after the last element */  
  80. int kd_res_end(struct kdres *set);  
  81.   
  82. /* advances the result set iterator, returns non-zero on success, zero if 
  83.  * there are no more elements in the result set. 
  84.  */  
  85. int kd_res_next(struct kdres *set);  
  86.   
  87. /* returns the data pointer (can be null) of the current result set item 
  88.  * and optionally sets its position to the pointers(s) if not null. 
  89.  */  
  90. void *kd_res_item(struct kdres *set, double *pos);  
  91. void *kd_res_itemf(struct kdres *set, float *pos);  
  92. void *kd_res_item3(struct kdres *set, double *x, double *y, double *z);  
  93. void *kd_res_item3f(struct kdres *set, float *x, float *y, float *z);  
  94.   
  95. /* equivalent to kd_res_item(set, 0) */  
  96. void *kd_res_item_data(struct kdres *set);  
  97.   
  98.   
  99. #ifdef __cplusplus   
  100. }  
  101. #endif   
  102.   
  103. #endif  /* _KDTREE_H_ */  
#ifndef _KDTREE_H_
#define _KDTREE_H_

#ifdef __cplusplus
extern "C" {
#endif

struct kdtree;
struct kdres;


/* create a kd-tree for "k"-dimensional data */
struct kdtree *kd_create(int k);

/* free the struct kdtree */
void kd_free(struct kdtree *tree);

/* remove all the elements from the tree */
void kd_clear(struct kdtree *tree);

/* if called with non-null 2nd argument, the function provided
 * will be called on data pointers (see kd_insert) when nodes
 * are to be removed from the tree.
 */
void kd_data_destructor(struct kdtree *tree, void (*destr)(void*));

/* insert a node, specifying its position, and optional data */
int kd_insert(struct kdtree *tree, const double *pos, void *data);
int kd_insertf(struct kdtree *tree, const float *pos, void *data);
int kd_insert3(struct kdtree *tree, double x, double y, double z, void *data);
int kd_insert3f(struct kdtree *tree, float x, float y, float z, void *data);

/* Find the nearest node from a given point.
 *
 * This function returns a pointer to a result set with at most one element.
 */
struct kdres *kd_nearest(struct kdtree *tree, const double *pos);
struct kdres *kd_nearestf(struct kdtree *tree, const float *pos);
struct kdres *kd_nearest3(struct kdtree *tree, double x, double y, double z);
struct kdres *kd_nearest3f(struct kdtree *tree, float x, float y, float z);

/* Find the N nearest nodes from a given point.
 *
 * This function returns a pointer to a result set, with at most N elements,
 * which can be manipulated with the kd_res_* functions.
 * The returned pointer can be null as an indication of an error. Otherwise
 * a valid result set is always returned which may contain 0 or more elements.
 * The result set must be deallocated with kd_res_free after use.
 */
/*
struct kdres *kd_nearest_n(struct kdtree *tree, const double *pos, int num);
struct kdres *kd_nearest_nf(struct kdtree *tree, const float *pos, int num);
struct kdres *kd_nearest_n3(struct kdtree *tree, double x, double y, double z);
struct kdres *kd_nearest_n3f(struct kdtree *tree, float x, float y, float z);
*/

/* Find any nearest nodes from a given point within a range.
 *
 * This function returns a pointer to a result set, which can be manipulated
 * by the kd_res_* functions.
 * The returned pointer can be null as an indication of an error. Otherwise
 * a valid result set is always returned which may contain 0 or more elements.
 * The result set must be deallocated with kd_res_free after use.
 */
struct kdres *kd_nearest_range(struct kdtree *tree, const double *pos, double range);
struct kdres *kd_nearest_rangef(struct kdtree *tree, const float *pos, float range);
struct kdres *kd_nearest_range3(struct kdtree *tree, double x, double y, double z, double range);
struct kdres *kd_nearest_range3f(struct kdtree *tree, float x, float y, float z, float range);

/* frees a result set returned by kd_nearest_range() */
void kd_res_free(struct kdres *set);

/* returns the size of the result set (in elements) */
int kd_res_size(struct kdres *set);

/* rewinds the result set iterator */
void kd_res_rewind(struct kdres *set);

/* returns non-zero if the set iterator reached the end after the last element */
int kd_res_end(struct kdres *set);

/* advances the result set iterator, returns non-zero on success, zero if
 * there are no more elements in the result set.
 */
int kd_res_next(struct kdres *set);

/* returns the data pointer (can be null) of the current result set item
 * and optionally sets its position to the pointers(s) if not null.
 */
void *kd_res_item(struct kdres *set, double *pos);
void *kd_res_itemf(struct kdres *set, float *pos);
void *kd_res_item3(struct kdres *set, double *x, double *y, double *z);
void *kd_res_item3f(struct kdres *set, float *x, float *y, float *z);

/* equivalent to kd_res_item(set, 0) */
void *kd_res_item_data(struct kdres *set);


#ifdef __cplusplus
}
#endif

#endif	/* _KDTREE_H_ */


下面是kdtree.c 文件,上面有我自己精心整理的詳細的漢語註釋,這個版本的kdtree可直接拿來用

  1. //kd_tree.h  kd_tree的頭文件   
  2.   
  3. #include "stdafx.h"   
  4.   
  5. //頭文件   
  6. #include <stdio.h>   
  7. #include <stdlib.h>   
  8. #include <string.h>   
  9. #include <math.h>   
  10. #include "kd_tree.h"   
  11.   
  12. #if defined(WIN32) || defined(__WIN32__)   
  13. #include <malloc.h>   
  14. #endif   
  15.   
  16. #ifdef USE_LIST_NODE_ALLOCATOR   
  17.   
  18. #ifndef NO_PTHREADS   
  19. #include <pthread.h>   
  20. #else   
  21.   
  22. #ifndef I_WANT_THREAD_BUGS   
  23. #error "You are compiling with the fast list node allocator, with pthreads disabled! This WILL break if used from multiple threads."  
  24. #endif  /* I want thread bugs */   
  25.   
  26. #endif  /* pthread support */   
  27. #endif  /* use list node allocator */   
  28.   
  29.   
  30. //超平面的結構體   
  31. //包括一個屬性的維數和每維座標的最大和最小值構成的數組   
  32. struct kdhyperrect {  
  33.     int dim;  
  34.     double *min, *max;              /* minimum/maximum coords */  
  35. };  
  36.   
  37. //節點的結構體,也就是事例的結構體   
  38. struct kdnode {  
  39.     double *pos;  
  40.     int dir;  
  41.     void *data;  
  42.   
  43.     struct kdnode *left, *right;    /* negative/positive side */  
  44. };  
  45.   
  46. //返回結果節點, 包括樹的節點,距離值, 是一個單鏈表的形式   
  47. struct res_node {  
  48.     struct kdnode *item;  
  49.     double dist_sq;  
  50.     struct res_node *next;  
  51. };  
  52.   
  53. //樹有幾個屬性,一是維數,一是樹根節點,一是超平面,一是銷燬data的函數   
  54. struct kdtree {  
  55.     int dim;  
  56.     struct kdnode *root;  
  57.     struct kdhyperrect *rect;  
  58.     void (*destr)(void*);  
  59. };  
  60.   
  61. //kdtree的返回結果,包括kdtree,這是一個雙鏈表的形式   
  62. struct kdres {  
  63.     struct kdtree *tree;  
  64.     struct res_node *rlist, *riter;  //雙鏈表?  
  65.     int size;  
  66. };  
  67.   
  68. //計算平方的宏定義,相當於函數   
  69. #define SQ(x)           ((x) * (x))   
  70.   
  71.   
  72. static void clear_rec(struct kdnode *node, void (*destr)(void*));  
  73. static int insert_rec(struct kdnode **node, const double *pos, void *data, int dir, int dim);  
  74. static int rlist_insert(struct res_node *list, struct kdnode *item, double dist_sq);  
  75. static void clear_results(struct kdres *set);  
  76.   
  77. static struct kdhyperrect* hyperrect_create(int dim, const double *min, const double *max);  
  78. static void hyperrect_free(struct kdhyperrect *rect);  
  79. static struct kdhyperrect* hyperrect_duplicate(const struct kdhyperrect *rect);  
  80. static void hyperrect_extend(struct kdhyperrect *rect, const double *pos);  
  81. static double hyperrect_dist_sq(struct kdhyperrect *rect, const double *pos);  
  82.   
  83. #ifdef USE_LIST_NODE_ALLOCATOR   
  84. static struct res_node *alloc_resnode(void);  
  85. static void free_resnode(struct res_node*);  
  86. #else   
  87. #define alloc_resnode()     malloc(sizeof(struct res_node))  
  88. #define free_resnode(n)     free(n)   
  89. #endif   
  90.   
  91.   
  92. //創建一個kdtree   
  93. struct kdtree *kd_create(int k)  
  94. {  
  95.     struct kdtree *tree;  
  96.   
  97.     if(!(tree = (kdtree*)malloc(sizeof *tree))) {  
  98.         return 0;  
  99.     }  
  100.   
  101.     tree->dim = k;  
  102.     tree->root = 0;  
  103.     tree->destr = 0;  
  104.     tree->rect = 0;  
  105.   
  106.     return tree;  
  107. }  
  108.   
  109. //釋放掉kdtree   
  110. void kd_free(struct kdtree *tree)  
  111. {  
  112.     if(tree) {  
  113.         kd_clear(tree);  
  114.         free(tree);  
  115.     }  
  116. }  
  117.   
  118. //清除掉超平面,是按節點遞歸地進行的   
  119. static void clear_rec(struct kdnode *node, void (*destr)(void*))  
  120. {  
  121.     if(!node) return;   //一個節點對應一個超平面  
  122.   
  123.     //遞歸函數,遞歸地清除掉二叉樹左分支的超平面和二叉樹右分支的超平面   
  124.     clear_rec(node->left, destr);  
  125.     clear_rec(node->right, destr);  
  126.       
  127.     //如果data清楚函數不爲空,就釋放掉data   
  128.     if(destr)   
  129.     {  
  130.         destr(node->data);  
  131.     }  
  132.     //釋放節點的座標數組   
  133.     free(node->pos);  
  134.     //釋放節點   
  135.     free(node);  
  136. }  
  137.   
  138. //kdtree清除   
  139. void kd_clear(struct kdtree *tree)  
  140. {  
  141.     //清除樹中每個節點的超平面,釋放樹中的各個節點   
  142.     clear_rec(tree->root, tree->destr);  
  143.     tree->root = 0;  
  144.   
  145.     //如果樹的超平面指針不爲空,對其進行釋放   
  146.     if (tree->rect)   
  147.     {  
  148.         hyperrect_free(tree->rect);  
  149.         tree->rect = 0;  
  150.     }  
  151. }  
  152.   
  153. //數據銷燬,用一個外來的函數來進行data的銷燬   
  154. void kd_data_destructor(struct kdtree *tree, void (*destr)(void*))  
  155. {  
  156.     //用外來的函數來執行kdtree的銷燬函數   
  157.     tree->destr = destr;  
  158. }  
  159.   
  160.   
  161. //在一個樹節點位置處插入超矩形   
  162. static int insert_rec(struct kdnode **nptr, const double *pos, void *data, int dir, int dim)  
  163. {  
  164.     int new_dir;  
  165.     struct kdnode *node;  
  166.   
  167.     //如果這個節點是不存在的   
  168.     if(!*nptr)   
  169.     {  
  170.         //分配一個結點   
  171.         if(!(node = (kdnode *)malloc(sizeof *node)))   
  172.         {  
  173.             return -1;  
  174.         }  
  175.         if(!(node->pos = (double*)malloc(dim * sizeof *node->pos))) {  
  176.             free(node);  
  177.             return -1;  
  178.         }  
  179.         memcpy(node->pos, pos, dim * sizeof *node->pos);  
  180.         node->data = data;  
  181.         node->dir = dir;  
  182.         node->left = node->right = 0;  
  183.         *nptr = node;  
  184.         return 0;  
  185.     }  
  186.   
  187.     node = *nptr;  
  188.     new_dir = (node->dir + 1) % dim;  
  189.     if(pos[node->dir] < node->pos[node->dir]) {  
  190.         return insert_rec(&(*nptr)->left, pos, data, new_dir, dim);  
  191.     }  
  192.     return insert_rec(&(*nptr)->right, pos, data, new_dir, dim);  
  193. }  
  194.   
  195. //節點插入操作   
  196. //參數爲:要進行插入操作的kdtree,要插入的節點座標,要插入的節點的數據   
  197. int kd_insert(struct kdtree *tree, const double *pos, void *data)  
  198. {  
  199.     //插入超矩形   
  200.     if (insert_rec(&tree->root, pos, data, 0, tree->dim))   
  201.     {  
  202.         return -1;  
  203.     }  
  204.     //如果樹還沒有超矩形,就創建一個超矩形   
  205.     //如果已經有了超矩形,就擴展原有的超矩形   
  206.     if (tree->rect == 0)   
  207.     {  
  208.         tree->rect = hyperrect_create(tree->dim, pos, pos);  
  209.     }   
  210.     else   
  211.     {  
  212.         hyperrect_extend(tree->rect, pos);  
  213.     }  
  214.   
  215.     return 0;  
  216. }  
  217.   
  218. //插入float型座標的節點   
  219. //參數爲:要進行插入操作的kdtree,要插入的節點座標,要插入的節點的數據   
  220. //將float型的座標賦值給double型的緩衝區,經過這個類型轉化後進行插入   
  221. //本質上是一種類型轉化   
  222. int kd_insertf(struct kdtree *tree, const float *pos, void *data)  
  223. {  
  224.     static double sbuf[16];  
  225.     double *bptr, *buf = 0;  
  226.     int res, dim = tree->dim;  
  227.   
  228.     //如果kdtree的維數大於16, 分配dim維double類型的數組   
  229.     if(dim > 16)   
  230.     {  
  231. #ifndef NO_ALLOCA   
  232.         if(dim <= 256)  
  233.             bptr = buf = (double*)alloca(dim * sizeof *bptr);  
  234.         else  
  235. #endif   
  236.             if(!(bptr = buf = (double*)malloc(dim * sizeof *bptr)))   
  237.             {  
  238.                 return -1;  
  239.             }  
  240.     }   
  241.     //如果kdtree的維數小於16, 直接將指針指向已分配的內存   
  242.     else   
  243.     {  
  244.         bptr = buf = sbuf;  
  245.     }  
  246.   
  247.     //將要插入點的位置座標賦值給分配的數組   
  248.     while(dim-- > 0)   
  249.     {  
  250.         *bptr++ = *pos++;  
  251.     }  
  252.   
  253.     //調用節點插入函數kd_insert   
  254.     res = kd_insert(tree, buf, data);  
  255. #ifndef NO_ALLOCA   
  256.     if(tree->dim > 256)  
  257. #else   
  258.     if(tree->dim > 16)  
  259. #endif   
  260.         //釋放緩存   
  261.         free(buf);  
  262.     return res;  
  263. }  
  264.   
  265. //給出三維座標值的三維kdtree插入   
  266. int kd_insert3(struct kdtree *tree, double x, double y, double z, void *data)  
  267. {  
  268.     double buf[3];  
  269.     buf[0] = x;  
  270.     buf[1] = y;  
  271.     buf[2] = z;  
  272.     return kd_insert(tree, buf, data);  
  273. }  
  274.   
  275. //給出三維float型座標值的三維kdtree插入   
  276. int kd_insert3f(struct kdtree *tree, float x, float y, float z, void *data)  
  277. {  
  278.     double buf[3];  
  279.     buf[0] = x;  
  280.     buf[1] = y;  
  281.     buf[2] = z;  
  282.     return kd_insert(tree, buf, data);  
  283. }  
  284.   
  285. //找到最近鄰的點   
  286. //參數爲:樹節點指針, 位置座標, 閾值, 返回結果的節點, bool型排序,維度   
  287. static int find_nearest(struct kdnode *node, const double *pos, double range, struct res_node *list, int ordered, int dim)  
  288. {  
  289.     double dist_sq, dx;  
  290.     int i, ret, added_res = 0;  
  291.   
  292.     if(!node) return 0;  //注意這個地方,當節點爲空的時候,表明已經查找到最終的葉子結點,返回值爲零  
  293.   
  294.     dist_sq = 0;  
  295.     //計算兩個節點間的平方和   
  296.     for(i=0; i<dim; i++)   
  297.     {  
  298.         dist_sq += SQ(node->pos[i] - pos[i]);  
  299.     }  
  300.     //如果距離在閾值範圍內,就將其插入到返回結果鏈表中   
  301.     if(dist_sq <= SQ(range))   
  302.     {         
  303.         if(rlist_insert(list, node, ordered ? dist_sq : -1.0) == -1)   
  304.         {  
  305.             return -1;  
  306.         }  
  307.         added_res = 1;  
  308.     }  
  309.   
  310.     //在這個節點的劃分方向上,求兩者之間的差值   
  311.     dx = pos[node->dir] - node->pos[node->dir];  
  312.   
  313.     //根據這個差值的符號, 選擇進行遞歸查找的分支方向   
  314.     ret = find_nearest(dx <= 0.0 ? node->left : node->right, pos, range, list, ordered, dim);  
  315.     //如果返回的值大於等於零,表明在這個分支中有滿足條件的節點,則返回結果的個數進行累加,並在節點的另一個方向進行查找最近的節點  
  316.     if(ret >= 0 && fabs(dx) < range)   
  317.     {  
  318.         added_res += ret;  
  319.         ret = find_nearest(dx <= 0.0 ? node->right : node->left, pos, range, list, ordered, dim);  
  320.     }  
  321.     if(ret == -1)   
  322.     {  
  323.         return -1;  
  324.     }  
  325.     added_res += ret;  
  326.   
  327.     return added_res;  
  328. }  
  329.   
  330.   
  331. //找到最近鄰的n個節點   
  332. #if 0   
  333. static int find_nearest_n(struct kdnode *node, const double *pos, double range, int num, struct rheap *heap, int dim)  
  334. {  
  335.     double dist_sq, dx;  
  336.     int i, ret, added_res = 0;  
  337.   
  338.     if(!node) return 0;  
  339.       
  340.     /* if the photon is close enough, add it to the result heap */  
  341.     //如果足夠近就將其加入到結果堆中   
  342.     dist_sq = 0;  
  343.     //計算兩者間的歐式距離   
  344.     for(i=0; i<dim; i++)   
  345.     {  
  346.         dist_sq += SQ(node->pos[i] - pos[i]);  
  347.     }  
  348.     //如果計算所得距離小於閾值   
  349.     if(dist_sq <= range_sq) {  
  350.     //如果堆的大小大於num,也就是大於總的要找的節點數   
  351.         if(heap->size >= num)  
  352.         {  
  353.             /* get furthest element */  
  354.             //得到最遠的節點   
  355.             struct res_node *maxelem = rheap_get_max(heap);  
  356.   
  357.             /* and check if the new one is closer than that */  
  358.             //測試這個節點是不是比最遠的節點要近   
  359.             if(maxelem->dist_sq > dist_sq)   
  360.             {  
  361.             //如果是的話,就移除最遠的節點   
  362.                 rheap_remove_max(heap);  
  363.                 //並將此節點插入堆中   
  364.                 if(rheap_insert(heap, node, dist_sq) == -1)   
  365.                 {  
  366.                     return -1;  
  367.                 }  
  368.                 added_res = 1;  
  369.   
  370.                 range_sq = dist_sq;  
  371.             }  
  372.         }   
  373.         //如果堆的大小小於num,直接將此節點插入堆中   
  374.         else   
  375.         {  
  376.             if(rheap_insert(heap, node, dist_sq) == -1)   
  377.             {  
  378.                 return =1;  
  379.             }  
  380.             added_res = 1;  
  381.         }  
  382.     }  
  383.   
  384.   
  385.     /* find signed distance from the splitting plane */  
  386.     dx = pos[node->dir] - node->pos[node->dir];  
  387.   
  388.     ret = find_nearest_n(dx <= 0.0 ? node->left : node->right, pos, range, num, heap, dim);  
  389.     if(ret >= 0 && fabs(dx) < range) {  
  390.         added_res += ret;  
  391.         ret = find_nearest_n(dx <= 0.0 ? node->right : node->left, pos, range, num, heap, dim);  
  392.     }  
  393. }  
  394. #endif   
  395.   
  396.   
  397. static void kd_nearest_i(struct kdnode *node, const double *pos, struct kdnode **result, double *result_dist_sq, struct kdhyperrect* rect)  
  398. {  
  399.     int dir = node->dir;  
  400.     int i;  
  401.     double dummy, dist_sq;  
  402.     struct kdnode *nearer_subtree, *farther_subtree;  
  403.     double *nearer_hyperrect_coord, *farther_hyperrect_coord;  
  404.   
  405.     /* Decide whether to go left or right in the tree */  
  406.     //在二叉樹中,決定向左走還是向右走   
  407.     dummy = pos[dir] - node->pos[dir];  
  408.     if (dummy <= 0)   
  409.     {  
  410.         nearer_subtree = node->left;  
  411.         farther_subtree = node->right;  
  412.         nearer_hyperrect_coord = rect->max + dir;  
  413.         farther_hyperrect_coord = rect->min + dir;  
  414.     }   
  415.     else   
  416.     {  
  417.         nearer_subtree = node->right;  
  418.         farther_subtree = node->left;  
  419.         nearer_hyperrect_coord = rect->min + dir;  
  420.         farther_hyperrect_coord = rect->max + dir;  
  421.     }  
  422.   
  423.     if (nearer_subtree) {  
  424.         /* Slice the hyperrect to get the hyperrect of the nearer subtree */  
  425.         dummy = *nearer_hyperrect_coord;  
  426.         *nearer_hyperrect_coord = node->pos[dir];  
  427.         /* Recurse down into nearer subtree */  
  428.         kd_nearest_i(nearer_subtree, pos, result, result_dist_sq, rect);  
  429.         /* Undo the slice */  
  430.         *nearer_hyperrect_coord = dummy;  
  431.     }  
  432.   
  433.     /* Check the distance of the point at the current node, compare it 
  434.      * with our best so far */  
  435.     dist_sq = 0;  
  436.     for(i=0; i < rect->dim; i++)   
  437.     {  
  438.         dist_sq += SQ(node->pos[i] - pos[i]);  
  439.     }  
  440.     if (dist_sq < *result_dist_sq)   
  441.     {  
  442.         *result = node;  
  443.         *result_dist_sq = dist_sq;  
  444.     }  
  445.   
  446.     if (farther_subtree) {  
  447.         /* Get the hyperrect of the farther subtree */  
  448.         dummy = *farther_hyperrect_coord;  
  449.         *farther_hyperrect_coord = node->pos[dir];  
  450.         /* Check if we have to recurse down by calculating the closest 
  451.          * point of the hyperrect and see if it's closer than our 
  452.          * minimum distance in result_dist_sq. */  
  453.         if (hyperrect_dist_sq(rect, pos) < *result_dist_sq) {  
  454.             /* Recurse down into farther subtree */  
  455.             kd_nearest_i(farther_subtree, pos, result, result_dist_sq, rect);  
  456.         }  
  457.         /* Undo the slice on the hyperrect */  
  458.         *farther_hyperrect_coord = dummy;  
  459.     }  
  460. }  
  461.   
  462. //求kdtree中與點pos最近鄰的值   
  463. struct kdres *kd_nearest(struct kdtree *kd, const double *pos)  
  464. {  
  465.     struct kdhyperrect *rect;  
  466.     struct kdnode *result;  
  467.     struct kdres *rset;  
  468.     double dist_sq;  
  469.     int i;  
  470.   
  471.     //如果kd不存在,或者其超平面不存在的話,則就不會有結果   
  472.     if (!kd) return 0;  
  473.     if (!kd->rect) return 0;  
  474.   
  475.     /* Allocate result set */  
  476.     //爲返回結果集合分配空間   
  477.     if(!(rset = (kdres*)malloc(sizeof *rset)))   
  478.     {  
  479.         return 0;  
  480.     }  
  481.     if(!(rset->rlist = (res_node*)alloc_resnode())) {  
  482.         free(rset);  
  483.         return 0;  
  484.     }  
  485.     rset->rlist->next = 0;  
  486.     rset->tree = kd;  
  487.   
  488.     /* Duplicate the bounding hyperrectangle, we will work on the copy */  
  489.     //複製邊界超平面   
  490.     if (!(rect = hyperrect_duplicate(kd->rect)))   
  491.     {  
  492.         kd_res_free(rset);  
  493.         return 0;  
  494.     }  
  495.   
  496.     /* Our first guesstimate is the root node */  
  497.     result = kd->root;  
  498.     dist_sq = 0;  
  499.     for (i = 0; i < kd->dim; i++)  
  500.         dist_sq += SQ(result->pos[i] - pos[i]);  
  501.   
  502.     /* Search for the nearest neighbour recursively */  
  503.     //遞歸地查找最近鄰的鄰居   
  504.     kd_nearest_i(kd->root, pos, &result, &dist_sq, rect);  
  505.   
  506.     /* Free the copy of the hyperrect */  
  507.     //釋放超矩形   
  508.     hyperrect_free(rect);  
  509.   
  510.     /* Store the result */  
  511.     //存儲結果   
  512.     if (result)   
  513.     {  
  514.         if (rlist_insert(rset->rlist, result, -1.0) == -1)   
  515.         {  
  516.             kd_res_free(rset);  
  517.             return 0;  
  518.         }  
  519.         rset->size = 1;  
  520.         kd_res_rewind(rset);  
  521.         return rset;  
  522.     }   
  523.     else   
  524.     {  
  525.         kd_res_free(rset);  
  526.         return 0;  
  527.     }  
  528. }  
  529.   
  530. //kd_nearest的float特例   
  531. struct kdres *kd_nearestf(struct kdtree *tree, const float *pos)  
  532. {  
  533.     static double sbuf[16];  
  534.     double *bptr, *buf = 0;  
  535.     int dim = tree->dim;  
  536.     struct kdres *res;  
  537.   
  538.     if(dim > 16) {  
  539. #ifndef NO_ALLOCA   
  540.         if(dim <= 256)  
  541.             bptr = buf = (double*)alloca(dim * sizeof *bptr);  
  542.         else  
  543. #endif   
  544.             if(!(bptr = buf = (double*)malloc(dim * sizeof *bptr))) {  
  545.                 return 0;  
  546.             }  
  547.     } else {  
  548.         bptr = buf = sbuf;  
  549.     }  
  550.   
  551.     while(dim-- > 0) {  
  552.         *bptr++ = *pos++;  
  553.     }  
  554.   
  555.     res = kd_nearest(tree, buf);  
  556. #ifndef NO_ALLOCA   
  557.     if(tree->dim > 256)  
  558. #else   
  559.     if(tree->dim > 16)  
  560. #endif   
  561.         free(buf);  
  562.     return res;  
  563. }  
  564.   
  565. //kd_nearest的三座標特例   
  566. struct kdres *kd_nearest3(struct kdtree *tree, double x, double y, double z)  
  567. {  
  568.     double pos[3];  
  569.     pos[0] = x;  
  570.     pos[1] = y;  
  571.     pos[2] = z;  
  572.     return kd_nearest(tree, pos);  
  573. }  
  574.   
  575. //kd_nearest的三座標float特例   
  576. struct kdres *kd_nearest3f(struct kdtree *tree, float x, float y, float z)  
  577. {  
  578.     double pos[3];  
  579.     pos[0] = x;  
  580.     pos[1] = y;  
  581.     pos[2] = z;  
  582.     return kd_nearest(tree, pos);  
  583. }  
  584.   
  585. /* ---- nearest N search ---- */  
  586. /* 
  587. static kdres *kd_nearest_n(struct kdtree *kd, const double *pos, int num) 
  588. { 
  589.     int ret; 
  590.     struct kdres *rset; 
  591.  
  592.     if(!(rset = malloc(sizeof *rset))) { 
  593.         return 0; 
  594.     } 
  595.     if(!(rset->rlist = alloc_resnode())) { 
  596.         free(rset); 
  597.         return 0; 
  598.     } 
  599.     rset->rlist->next = 0; 
  600.     rset->tree = kd; 
  601.  
  602.     if((ret = find_nearest_n(kd->root, pos, range, num, rset->rlist, kd->dim)) == -1) { 
  603.         kd_res_free(rset); 
  604.         return 0; 
  605.     } 
  606.     rset->size = ret; 
  607.     kd_res_rewind(rset); 
  608.     return rset; 
  609. }*/  
  610.   
  611. //找到滿足距離小於range值的節點   
  612. struct kdres *kd_nearest_range(struct kdtree *kd, const double *pos, double range)  
  613. {  
  614.     int ret;  
  615.     struct kdres *rset;  
  616.   
  617.     if(!(rset = (kdres*)malloc(sizeof *rset))) {  
  618.         return 0;  
  619.     }  
  620.     if(!(rset->rlist = (res_node*)alloc_resnode())) {  
  621.         free(rset);  
  622.         return 0;  
  623.     }  
  624.     rset->rlist->next = 0;  
  625.     rset->tree = kd;  
  626.   
  627.     if((ret = find_nearest(kd->root, pos, range, rset->rlist, 0, kd->dim)) == -1) {  
  628.         kd_res_free(rset);  
  629.         return 0;  
  630.     }  
  631.     rset->size = ret;  
  632.     kd_res_rewind(rset);  
  633.     return rset;  
  634. }  
  635.   
  636. //kd_nearest_range的float特例   
  637. struct kdres *kd_nearest_rangef(struct kdtree *kd, const float *pos, float range)  
  638. {  
  639.     static double sbuf[16];  
  640.     double *bptr, *buf = 0;  
  641.     int dim = kd->dim;  
  642.     struct kdres *res;  
  643.   
  644.     if(dim > 16) {  
  645. #ifndef NO_ALLOCA   
  646.         if(dim <= 256)  
  647.             bptr = buf = (double*)alloca(dim * sizeof *bptr);  
  648.         else  
  649. #endif   
  650.             if(!(bptr = buf = (double*)malloc(dim * sizeof *bptr))) {  
  651.                 return 0;  
  652.             }  
  653.     } else {  
  654.         bptr = buf = sbuf;  
  655.     }  
  656.   
  657.     while(dim-- > 0) {  
  658.         *bptr++ = *pos++;  
  659.     }  
  660.   
  661.     res = kd_nearest_range(kd, buf, range);  
  662. #ifndef NO_ALLOCA   
  663.     if(kd->dim > 256)  
  664. #else   
  665.     if(kd->dim > 16)  
  666. #endif   
  667.         free(buf);  
  668.     return res;  
  669. }  
  670.   
  671. //kd_nearest_range的三座標特例   
  672. struct kdres *kd_nearest_range3(struct kdtree *tree, double x, double y, double z, double range)  
  673. {  
  674.     double buf[3];  
  675.     buf[0] = x;  
  676.     buf[1] = y;  
  677.     buf[2] = z;  
  678.     return kd_nearest_range(tree, buf, range);  
  679. }  
  680.   
  681. //kd_nearest_range的三座標float特例   
  682. struct kdres *kd_nearest_range3f(struct kdtree *tree, float x, float y, float z, float range)  
  683. {  
  684.     double buf[3];  
  685.     buf[0] = x;  
  686.     buf[1] = y;  
  687.     buf[2] = z;  
  688.     return kd_nearest_range(tree, buf, range);  
  689. }  
  690.   
  691. //返回結果的釋放   
  692. void kd_res_free(struct kdres *rset)  
  693. {  
  694.     clear_results(rset);  
  695.     free_resnode(rset->rlist);  
  696.     free(rset);  
  697. }  
  698.   
  699. //獲取返回結果集合的大小   
  700. int kd_res_size(struct kdres *set)  
  701. {  
  702.     return (set->size);  
  703. }  
  704.   
  705. //再次回到這個節點本身的位置   
  706. void kd_res_rewind(struct kdres *rset)  
  707. {  
  708.     rset->riter = rset->rlist->next;  
  709. }  
  710.   
  711. //找到返回結果中的最終節點   
  712. int kd_res_end(struct kdres *rset)  
  713. {  
  714.     return rset->riter == 0;  
  715. }  
  716.   
  717. //返回結果列表中的下一個節點   
  718. int kd_res_next(struct kdres *rset)  
  719. {  
  720.     rset->riter = rset->riter->next;  
  721.     return rset->riter != 0;  
  722. }  
  723.   
  724. //將返回結果的節點的座標和data抽取出來   
  725. void *kd_res_item(struct kdres *rset, double *pos)  
  726. {  
  727.     if(rset->riter) {  
  728.         if(pos) {  
  729.             memcpy(pos, rset->riter->item->pos, rset->tree->dim * sizeof *pos);  
  730.         }  
  731.         return rset->riter->item->data;  
  732.     }  
  733.     return 0;  
  734. }  
  735.   
  736. //將返回結果的節點的座標和data抽取出來,座標爲float型的值   
  737. void *kd_res_itemf(struct kdres *rset, float *pos)  
  738. {  
  739.     if(rset->riter) {  
  740.         if(pos) {  
  741.             int i;  
  742.             for(i=0; i<rset->tree->dim; i++) {  
  743.                 pos[i] = rset->riter->item->pos[i];  
  744.             }  
  745.         }  
  746.         return rset->riter->item->data;  
  747.     }  
  748.     return 0;  
  749. }  
  750.   
  751. //將返回結果的節點的座標和data抽取出來,座標具體形式給出   
  752. void *kd_res_item3(struct kdres *rset, double *x, double *y, double *z)  
  753. {  
  754.     if(rset->riter) {  
  755.         if(*x) *x = rset->riter->item->pos[0];  
  756.         if(*y) *y = rset->riter->item->pos[1];  
  757.         if(*z) *z = rset->riter->item->pos[2];  
  758.     }  
  759.     return 0;  
  760. }  
  761.   
  762. //將返回結果的節點的座標和data抽取出來,座標爲float型的值,座標具體形式給出   
  763. void *kd_res_item3f(struct kdres *rset, float *x, float *y, float *z)  
  764. {  
  765.     if(rset->riter) {  
  766.         if(*x) *x = rset->riter->item->pos[0];  
  767.         if(*y) *y = rset->riter->item->pos[1];  
  768.         if(*z) *z = rset->riter->item->pos[2];  
  769.     }  
  770.     return 0;  
  771. }  
  772.   
  773. //獲取data數據   
  774. void *kd_res_item_data(struct kdres *set)  
  775. {  
  776.     return kd_res_item(set, 0);  
  777. }  
  778.   
  779. /* ---- hyperrectangle helpers ---- */  
  780. //創建超平面,包括三個參數:維度,每維的最小值和最大值數組   
  781. static struct kdhyperrect* hyperrect_create(int dim, const double *min, const double *max)  
  782. {  
  783.     size_t size = dim * sizeof(double);  
  784.     struct kdhyperrect* rect = 0;  
  785.   
  786.     if (!(rect = (kdhyperrect*)malloc(sizeof(struct kdhyperrect))))   
  787.     {  
  788.         return 0;  
  789.     }  
  790.   
  791.     rect->dim = dim;  
  792.     if (!(rect->min = (double*)malloc(size))) {  
  793.         free(rect);  
  794.         return 0;  
  795.     }  
  796.     if (!(rect->max = (double*)malloc(size))) {  
  797.         free(rect->min);  
  798.         free(rect);  
  799.         return 0;  
  800.     }  
  801.     memcpy(rect->min, min, size);  
  802.     memcpy(rect->max, max, size);  
  803.   
  804.     return rect;  
  805. }  
  806.   
  807. //釋放超平面結構體   
  808. static void hyperrect_free(struct kdhyperrect *rect)  
  809. {  
  810.     free(rect->min);  
  811.     free(rect->max);  
  812.     free(rect);  
  813. }  
  814.   
  815. //賦值超平面結構體   
  816. static struct kdhyperrect* hyperrect_duplicate(const struct kdhyperrect *rect)  
  817. {  
  818.     return hyperrect_create(rect->dim, rect->min, rect->max);  
  819. }  
  820.   
  821. //更新超平面結構體最大\最小值數組   
  822. static void hyperrect_extend(struct kdhyperrect *rect, const double *pos)  
  823. {  
  824.     int i;  
  825.   
  826.     for (i=0; i < rect->dim; i++) {  
  827.         if (pos[i] < rect->min[i]) {  
  828.             rect->min[i] = pos[i];  
  829.         }  
  830.         if (pos[i] > rect->max[i]) {  
  831.             rect->max[i] = pos[i];  
  832.         }  
  833.     }  
  834. }  
  835.   
  836. //計算固定座標點與超平面之間的距離   
  837. static double hyperrect_dist_sq(struct kdhyperrect *rect, const double *pos)  
  838. {  
  839.     int i;  
  840.     double result = 0;  
  841.   
  842.     for (i=0; i < rect->dim; i++)   
  843.     {  
  844.         if (pos[i] < rect->min[i])   
  845.         {  
  846.             result += SQ(rect->min[i] - pos[i]);  
  847.         }   
  848.         else if (pos[i] > rect->max[i])   
  849.         {  
  850.             result += SQ(rect->max[i] - pos[i]);  
  851.         }  
  852.     }  
  853.     return result;  
  854. }  
  855.   
  856.   
  857. /* ---- static helpers ---- */  
  858. #ifdef USE_LIST_NODE_ALLOCATOR   
  859. /* special list node allocators. */  
  860. static struct res_node *free_nodes;  
  861.   
  862. #ifndef NO_PTHREADS   
  863. static pthread_mutex_t alloc_mutex = PTHREAD_MUTEX_INITIALIZER;  
  864. #endif   
  865.   
  866. //創建返回結果節點   
  867. static struct res_node *alloc_resnode(void)  
  868. {  
  869.     struct res_node *node;  
  870.   
  871. #ifndef NO_PTHREADS   
  872.     pthread_mutex_lock(&alloc_mutex);  
  873. #endif   
  874.   
  875.     if(!free_nodes) {  
  876.         node = malloc(sizeof *node);  
  877.     } else {  
  878.         node = free_nodes;  
  879.         free_nodes = free_nodes->next;  
  880.         node->next = 0;  
  881.     }  
  882.   
  883. #ifndef NO_PTHREADS   
  884.     pthread_mutex_unlock(&alloc_mutex);  
  885. #endif   
  886.   
  887.     return node;  
  888. }  
  889.   
  890. //釋放返回結果節點   
  891. static void free_resnode(struct res_node *node)  
  892. {  
  893. #ifndef NO_PTHREADS   
  894.     pthread_mutex_lock(&alloc_mutex);  
  895. #endif   
  896.   
  897.     node->next = free_nodes;  
  898.     free_nodes = node;  
  899.   
  900. #ifndef NO_PTHREADS   
  901.     pthread_mutex_unlock(&alloc_mutex);  
  902. #endif   
  903. }  
  904. #endif  /* list node allocator or not */   
  905.   
  906.   
  907. /* inserts the item. if dist_sq is >= 0, then do an ordered insert */  
  908. /* TODO make the ordering code use heapsort */  
  909. //函數參數: 返回結果節點指針,樹節點指針,距離函數   
  910. //將一個結果節點插入到返回結果的列表中   
  911. static int rlist_insert(struct res_node *list, struct kdnode *item, double dist_sq)  
  912. {  
  913.     struct res_node *rnode;  
  914.   
  915.     //創建一個返回結果的節點   
  916.     if(!(rnode = (res_node*)alloc_resnode()))   
  917.     {  
  918.         return -1;  
  919.     }  
  920.     rnode->item = item;           //對應的樹節點   
  921.     rnode->dist_sq = dist_sq;     //對應的距離值   
  922.   
  923.     //當距離大於零的時候   
  924.     if(dist_sq >= 0.0)   
  925.     {  
  926.         while(list->next && list->next->dist_sq < dist_sq)   
  927.         {  
  928.             list = list->next;  
  929.         }  
  930.     }  
  931.     rnode->next = list->next;  
  932.     list->next = rnode;  
  933.     return 0;  
  934. }  
  935.   
  936. //清除返回結果的集合   
  937. //本質上是個雙鏈表中單鏈表的清理   
  938. static void clear_results(struct kdres *rset)  
  939. {  
  940.     struct res_node *tmp, *node = rset->rlist->next;  
  941.   
  942.     while(node)   
  943.     {  
  944.         tmp = node;  
  945.         node = node->next;  
  946.         free_resnode(tmp);  
  947.     }  
  948.   
  949.     rset->rlist->next = 0;  
  950. }  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章