1. 程式人生 > >kD-tree 的C語言實現 帶有史上最全的註釋和解釋

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

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

下面是kdtree.h檔案,是kdtree資料結構的標頭檔案

#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可直接拿來用

//kd_tree.h  kd_tree的標頭檔案

#include "stdafx.h"

//標頭檔案
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "kd_tree.h"

#if defined(WIN32) || defined(__WIN32__)
#include <malloc.h>
#endif

#ifdef USE_LIST_NODE_ALLOCATOR

#ifndef NO_PTHREADS
#include <pthread.h>
#else

#ifndef I_WANT_THREAD_BUGS
#error "You are compiling with the fast list node allocator, with pthreads disabled! This WILL break if used from multiple threads."
#endif	/* I want thread bugs */

#endif	/* pthread support */
#endif	/* use list node allocator */


//超平面的結構體
//包括一個屬性的維數和每維座標的最大和最小值構成的陣列
struct kdhyperrect {
	int dim;
	double *min, *max;              /* minimum/maximum coords */
};

//節點的結構體,也就是事例的結構體
struct kdnode {
	double *pos;
	int dir;
	void *data;

	struct kdnode *left, *right;	/* negative/positive side */
};

//返回結果節點, 包括樹的節點,距離值, 是一個單鏈表的形式
struct res_node {
	struct kdnode *item;
	double dist_sq;
	struct res_node *next;
};

//樹有幾個屬性,一是維數,一是樹根節點,一是超平面,一是銷燬data的函式
struct kdtree {
	int dim;
	struct kdnode *root;
	struct kdhyperrect *rect;
	void (*destr)(void*);
};

//kdtree的返回結果,包括kdtree,這是一個雙鏈表的形式
struct kdres {
	struct kdtree *tree;
	struct res_node *rlist, *riter;  //雙鏈表?
	int size;
};

//計算平方的巨集定義,相當於函式
#define SQ(x)			((x) * (x))


static void clear_rec(struct kdnode *node, void (*destr)(void*));
static int insert_rec(struct kdnode **node, const double *pos, void *data, int dir, int dim);
static int rlist_insert(struct res_node *list, struct kdnode *item, double dist_sq);
static void clear_results(struct kdres *set);

static struct kdhyperrect* hyperrect_create(int dim, const double *min, const double *max);
static void hyperrect_free(struct kdhyperrect *rect);
static struct kdhyperrect* hyperrect_duplicate(const struct kdhyperrect *rect);
static void hyperrect_extend(struct kdhyperrect *rect, const double *pos);
static double hyperrect_dist_sq(struct kdhyperrect *rect, const double *pos);

#ifdef USE_LIST_NODE_ALLOCATOR
static struct res_node *alloc_resnode(void);
static void free_resnode(struct res_node*);
#else
#define alloc_resnode()		malloc(sizeof(struct res_node))
#define free_resnode(n)		free(n)
#endif


//建立一個kdtree
struct kdtree *kd_create(int k)
{
	struct kdtree *tree;

	if(!(tree = (kdtree*)malloc(sizeof *tree))) {
		return 0;
	}

	tree->dim = k;
	tree->root = 0;
	tree->destr = 0;
	tree->rect = 0;

	return tree;
}

//釋放掉kdtree
void kd_free(struct kdtree *tree)
{
	if(tree) {
		kd_clear(tree);
		free(tree);
	}
}

//清除掉超平面,是按節點遞迴地進行的
static void clear_rec(struct kdnode *node, void (*destr)(void*))
{
	if(!node) return;   //一個節點對應一個超平面

	//遞迴函式,遞迴地清除掉二叉樹左分支的超平面和二叉樹右分支的超平面
	clear_rec(node->left, destr);
	clear_rec(node->right, destr);
	
	//如果data清楚函式不為空,就釋放掉data
	if(destr) 
	{
		destr(node->data);
	}
	//釋放節點的座標陣列
	free(node->pos);
	//釋放節點
	free(node);
}

//kdtree清除
void kd_clear(struct kdtree *tree)
{
	//清除樹中每個節點的超平面,釋放樹中的各個節點
	clear_rec(tree->root, tree->destr);
	tree->root = 0;

	//如果樹的超平面指標不為空,對其進行釋放
	if (tree->rect) 
	{
		hyperrect_free(tree->rect);
		tree->rect = 0;
	}
}

//資料銷燬,用一個外來的函式來進行data的銷燬
void kd_data_destructor(struct kdtree *tree, void (*destr)(void*))
{
	//用外來的函式來執行kdtree的銷燬函式
	tree->destr = destr;
}


//在一個樹節點位置處插入超矩形
static int insert_rec(struct kdnode **nptr, const double *pos, void *data, int dir, int dim)
{
	int new_dir;
	struct kdnode *node;

	//如果這個節點是不存在的
	if(!*nptr) 
	{
		//分配一個結點
		if(!(node = (kdnode *)malloc(sizeof *node))) 
		{
			return -1;
		}
		if(!(node->pos = (double*)malloc(dim * sizeof *node->pos))) {
			free(node);
			return -1;
		}
		memcpy(node->pos, pos, dim * sizeof *node->pos);
		node->data = data;
		node->dir = dir;
		node->left = node->right = 0;
		*nptr = node;
		return 0;
	}

	node = *nptr;
	new_dir = (node->dir + 1) % dim;
	if(pos[node->dir] < node->pos[node->dir]) {
		return insert_rec(&(*nptr)->left, pos, data, new_dir, dim);
	}
	return insert_rec(&(*nptr)->right, pos, data, new_dir, dim);
}

//節點插入操作
//引數為:要進行插入操作的kdtree,要插入的節點座標,要插入的節點的資料
int kd_insert(struct kdtree *tree, const double *pos, void *data)
{
	//插入超矩形
	if (insert_rec(&tree->root, pos, data, 0, tree->dim)) 
	{
		return -1;
	}
	//如果樹還沒有超矩形,就建立一個超矩形
	//如果已經有了超矩形,就擴充套件原有的超矩形
	if (tree->rect == 0) 
	{
		tree->rect = hyperrect_create(tree->dim, pos, pos);
	} 
	else 
	{
		hyperrect_extend(tree->rect, pos);
	}

	return 0;
}

//插入float型座標的節點
//引數為:要進行插入操作的kdtree,要插入的節點座標,要插入的節點的資料
//將float型的座標賦值給double型的緩衝區,經過這個型別轉化後進行插入
//本質上是一種型別轉化
int kd_insertf(struct kdtree *tree, const float *pos, void *data)
{
	static double sbuf[16];
	double *bptr, *buf = 0;
	int res, dim = tree->dim;

	//如果kdtree的維數大於16, 分配dim維double型別的陣列
	if(dim > 16) 
	{
#ifndef NO_ALLOCA
		if(dim <= 256)
			bptr = buf = (double*)alloca(dim * sizeof *bptr);
		else
#endif
			if(!(bptr = buf = (double*)malloc(dim * sizeof *bptr))) 
			{
				return -1;
			}
	} 
	//如果kdtree的維數小於16, 直接將指標指向已分配的記憶體
	else 
	{
		bptr = buf = sbuf;
	}

	//將要插入點的位置座標賦值給分配的陣列
	while(dim-- > 0) 
	{
		*bptr++ = *pos++;
	}

	//呼叫節點插入函式kd_insert
	res = kd_insert(tree, buf, data);
#ifndef NO_ALLOCA
	if(tree->dim > 256)
#else
	if(tree->dim > 16)
#endif
        //釋放快取
		free(buf);
	return res;
}

//給出三維座標值的三維kdtree插入
int kd_insert3(struct kdtree *tree, double x, double y, double z, void *data)
{
	double buf[3];
	buf[0] = x;
	buf[1] = y;
	buf[2] = z;
	return kd_insert(tree, buf, data);
}

//給出三維float型座標值的三維kdtree插入
int kd_insert3f(struct kdtree *tree, float x, float y, float z, void *data)
{
	double buf[3];
	buf[0] = x;
	buf[1] = y;
	buf[2] = z;
	return kd_insert(tree, buf, data);
}

//找到最近鄰的點
//引數為:樹節點指標, 位置座標, 閾值, 返回結果的節點, bool型排序,維度
static int find_nearest(struct kdnode *node, const double *pos, double range, struct res_node *list, int ordered, int dim)
{
	double dist_sq, dx;
	int i, ret, added_res = 0;

	if(!node) return 0;  //注意這個地方,當節點為空的時候,表明已經查詢到最終的葉子結點,返回值為零

	dist_sq = 0;
	//計算兩個節點間的平方和
	for(i=0; i<dim; i++) 
	{
		dist_sq += SQ(node->pos[i] - pos[i]);
	}
	//如果距離在閾值範圍內,就將其插入到返回結果連結串列中
	if(dist_sq <= SQ(range)) 
	{		
		if(rlist_insert(list, node, ordered ? dist_sq : -1.0) == -1) 
		{
			return -1;
		}
		added_res = 1;
	}

	//在這個節點的劃分方向上,求兩者之間的差值
	dx = pos[node->dir] - node->pos[node->dir];

	//根據這個差值的符號, 選擇進行遞迴查詢的分支方向
	ret = find_nearest(dx <= 0.0 ? node->left : node->right, pos, range, list, ordered, dim);
	//如果返回的值大於等於零,表明在這個分支中有滿足條件的節點,則返回結果的個數進行累加,並在節點的另一個方向進行查詢最近的節點
	if(ret >= 0 && fabs(dx) < range) 
	{
		added_res += ret;
		ret = find_nearest(dx <= 0.0 ? node->right : node->left, pos, range, list, ordered, dim);
	}
	if(ret == -1) 
	{
		return -1;
	}
	added_res += ret;

	return added_res;
}


//找到最近鄰的n個節點
#if 0
static int find_nearest_n(struct kdnode *node, const double *pos, double range, int num, struct rheap *heap, int dim)
{
	double dist_sq, dx;
	int i, ret, added_res = 0;

	if(!node) return 0;
	
	/* if the photon is close enough, add it to the result heap */
	//如果足夠近就將其加入到結果堆中
	dist_sq = 0;
	//計算兩者間的歐式距離
	for(i=0; i<dim; i++) 
	{
		dist_sq += SQ(node->pos[i] - pos[i]);
	}
	//如果計算所得距離小於閾值
	if(dist_sq <= range_sq) {
	//如果堆的大小大於num,也就是大於總的要找的節點數
		if(heap->size >= num)
		{
			/* get furthest element */
			//得到最遠的節點
			struct res_node *maxelem = rheap_get_max(heap);

			/* and check if the new one is closer than that */
			//測試這個節點是不是比最遠的節點要近
			if(maxelem->dist_sq > dist_sq) 
			{
			//如果是的話,就移除最遠的節點
				rheap_remove_max(heap);
				//並將此節點插入堆中
				if(rheap_insert(heap, node, dist_sq) == -1) 
				{
					return -1;
				}
				added_res = 1;

				range_sq = dist_sq;
			}
		} 
		//如果堆的大小小於num,直接將此節點插入堆中
		else 
		{
			if(rheap_insert(heap, node, dist_sq) == -1) 
			{
				return =1;
			}
			added_res = 1;
		}
	}


	/* find signed distance from the splitting plane */
	dx = pos[node->dir] - node->pos[node->dir];

	ret = find_nearest_n(dx <= 0.0 ? node->left : node->right, pos, range, num, heap, dim);
	if(ret >= 0 && fabs(dx) < range) {
		added_res += ret;
		ret = find_nearest_n(dx <= 0.0 ? node->right : node->left, pos, range, num, heap, dim);
	}
}
#endif


static void kd_nearest_i(struct kdnode *node, const double *pos, struct kdnode **result, double *result_dist_sq, struct kdhyperrect* rect)
{
	int dir = node->dir;
	int i;
	double dummy, dist_sq;
	struct kdnode *nearer_subtree, *farther_subtree;
	double *nearer_hyperrect_coord, *farther_hyperrect_coord;

	/* Decide whether to go left or right in the tree */
	//在二叉樹中,決定向左走還是向右走
	dummy = pos[dir] - node->pos[dir];
	if (dummy <= 0) 
	{
		nearer_subtree = node->left;
		farther_subtree = node->right;
		nearer_hyperrect_coord = rect->max + dir;
		farther_hyperrect_coord = rect->min + dir;
	} 
	else 
	{
		nearer_subtree = node->right;
		farther_subtree = node->left;
		nearer_hyperrect_coord = rect->min + dir;
		farther_hyperrect_coord = rect->max + dir;
	}

	if (nearer_subtree) {
		/* Slice the hyperrect to get the hyperrect of the nearer subtree */
		dummy = *nearer_hyperrect_coord;
		*nearer_hyperrect_coord = node->pos[dir];
		/* Recurse down into nearer subtree */
		kd_nearest_i(nearer_subtree, pos, result, result_dist_sq, rect);
		/* Undo the slice */
		*nearer_hyperrect_coord = dummy;
	}

	/* Check the distance of the point at the current node, compare it
	 * with our best so far */
	dist_sq = 0;
	for(i=0; i < rect->dim; i++) 
	{
		dist_sq += SQ(node->pos[i] - pos[i]);
	}
	if (dist_sq < *result_dist_sq) 
	{
		*result = node;
		*result_dist_sq = dist_sq;
	}

	if (farther_subtree) {
		/* Get the hyperrect of the farther subtree */
		dummy = *farther_hyperrect_coord;
		*farther_hyperrect_coord = node->pos[dir];
		/* Check if we have to recurse down by calculating the closest
		 * point of the hyperrect and see if it's closer than our
		 * minimum distance in result_dist_sq. */
		if (hyperrect_dist_sq(rect, pos) < *result_dist_sq) {
			/* Recurse down into farther subtree */
			kd_nearest_i(farther_subtree, pos, result, result_dist_sq, rect);
		}
		/* Undo the slice on the hyperrect */
		*farther_hyperrect_coord = dummy;
	}
}

//求kdtree中與點pos最近鄰的值
struct kdres *kd_nearest(struct kdtree *kd, const double *pos)
{
	struct kdhyperrect *rect;
	struct kdnode *result;
	struct kdres *rset;
	double dist_sq;
	int i;

	//如果kd不存在,或者其超平面不存在的話,則就不會有結果
	if (!kd) return 0;
	if (!kd->rect) return 0;

	/* Allocate result set */
	//為返回結果集合分配空間
	if(!(rset = (kdres*)malloc(sizeof *rset))) 
	{
		return 0;
	}
	if(!(rset->rlist = (res_node*)alloc_resnode())) {
		free(rset);
		return 0;
	}
	rset->rlist->next = 0;
	rset->tree = kd;

	/* Duplicate the bounding hyperrectangle, we will work on the copy */
	//複製邊界超平面
	if (!(rect = hyperrect_duplicate(kd->rect))) 
	{
		kd_res_free(rset);
		return 0;
	}

	/* Our first guesstimate is the root node */
	result = kd->root;
	dist_sq = 0;
	for (i = 0; i < kd->dim; i++)
		dist_sq += SQ(result->pos[i] - pos[i]);

	/* Search for the nearest neighbour recursively */
	//遞迴地查詢最近鄰的鄰居
	kd_nearest_i(kd->root, pos, &result, &dist_sq, rect);

	/* Free the copy of the hyperrect */
	//釋放超矩形
	hyperrect_free(rect);

	/* Store the result */
	//儲存結果
	if (result) 
	{
		if (rlist_insert(rset->rlist, result, -1.0) == -1) 
		{
			kd_res_free(rset);
			return 0;
		}
		rset->size = 1;
		kd_res_rewind(rset);
		return rset;
	} 
	else 
	{
		kd_res_free(rset);
		return 0;
	}
}

//kd_nearest的float特例
struct kdres *kd_nearestf(struct kdtree *tree, const float *pos)
{
	static double sbuf[16];
	double *bptr, *buf = 0;
	int dim = tree->dim;
	struct kdres *res;

	if(dim > 16) {
#ifndef NO_ALLOCA
		if(dim <= 256)
			bptr = buf = (double*)alloca(dim * sizeof *bptr);
		else
#endif
			if(!(bptr = buf = (double*)malloc(dim * sizeof *bptr))) {
				return 0;
			}
	} else {
		bptr = buf = sbuf;
	}

	while(dim-- > 0) {
		*bptr++ = *pos++;
	}

	res = kd_nearest(tree, buf);
#ifndef NO_ALLOCA
	if(tree->dim > 256)
#else
	if(tree->dim > 16)
#endif
		free(buf);
	return res;
}

//kd_nearest的三座標特例
struct kdres *kd_nearest3(struct kdtree *tree, double x, double y, double z)
{
	double pos[3];
	pos[0] = x;
	pos[1] = y;
	pos[2] = z;
	return kd_nearest(tree, pos);
}

//kd_nearest的三座標float特例
struct kdres *kd_nearest3f(struct kdtree *tree, float x, float y, float z)
{
	double pos[3];
	pos[0] = x;
	pos[1] = y;
	pos[2] = z;
	return kd_nearest(tree, pos);
}

/* ---- nearest N search ---- */
/*
static kdres *kd_nearest_n(struct kdtree *kd, const double *pos, int num)
{
	int ret;
	struct kdres *rset;

	if(!(rset = malloc(sizeof *rset))) {
		return 0;
	}
	if(!(rset->rlist = alloc_resnode())) {
		free(rset);
		return 0;
	}
	rset->rlist->next = 0;
	rset->tree = kd;

	if((ret = find_nearest_n(kd->root, pos, range, num, rset->rlist, kd->dim)) == -1) {
		kd_res_free(rset);
		return 0;
	}
	rset->size = ret;
	kd_res_rewind(rset);
	return rset;
}*/

//找到滿足距離小於range值的節點
struct kdres *kd_nearest_range(struct kdtree *kd, const double *pos, double range)
{
	int ret;
	struct kdres *rset;

	if(!(rset = (kdres*)malloc(sizeof *rset))) {
		return 0;
	}
	if(!(rset->rlist = (res_node*)alloc_resnode())) {
		free(rset);
		return 0;
	}
	rset->rlist->next = 0;
	rset->tree = kd;

	if((ret = find_nearest(kd->root, pos, range, rset->rlist, 0, kd->dim)) == -1) {
		kd_res_free(rset);
		return 0;
	}
	rset->size = ret;
	kd_res_rewind(rset);
	return rset;
}

//kd_nearest_range的float特例
struct kdres *kd_nearest_rangef(struct kdtree *kd, const float *pos, float range)
{
	static double sbuf[16];
	double *bptr, *buf = 0;
	int dim = kd->dim;
	struct kdres *res;

	if(dim > 16) {
#ifndef NO_ALLOCA
		if(dim <= 256)
			bptr = buf = (double*)alloca(dim * sizeof *bptr);
		else
#endif
			if(!(bptr = buf = (double*)malloc(dim * sizeof *bptr))) {
				return 0;
			}
	} else {
		bptr = buf = sbuf;
	}

	while(dim-- > 0) {
		*bptr++ = *pos++;
	}

	res = kd_nearest_range(kd, buf, range);
#ifndef NO_ALLOCA
	if(kd->dim > 256)
#else
	if(kd->dim > 16)
#endif
		free(buf);
	return res;
}

//kd_nearest_range的三座標特例
struct kdres *kd_nearest_range3(struct kdtree *tree, double x, double y, double z, double range)
{
	double buf[3];
	buf[0] = x;
	buf[1] = y;
	buf[2] = z;
	return kd_nearest_range(tree, buf, range);
}

//kd_nearest_range的三座標float特例
struct kdres *kd_nearest_range3f(struct kdtree *tree, float x, float y, float z, float range)
{
	double buf[3];
	buf[0] = x;
	buf[1] = y;
	buf[2] = z;
	return kd_nearest_range(tree, buf, range);
}

//返回結果的釋放
void kd_res_free(struct kdres *rset)
{
	clear_results(rset);
	free_resnode(rset->rlist);
	free(rset);
}

//獲取返回結果集合的大小
int kd_res_size(struct kdres *set)
{
	return (set->size);
}

//再次回到這個節點本身的位置
void kd_res_rewind(struct kdres *rset)
{
	rset->riter = rset->rlist->next;
}

//找到返回結果中的最終節點
int kd_res_end(struct kdres *rset)
{
	return rset->riter == 0;
}

//返回結果列表中的下一個節點
int kd_res_next(struct kdres *rset)
{
	rset->riter = rset->riter->next;
	return rset->riter != 0;
}

//將返回結果的節點的座標和data抽取出來
void *kd_res_item(struct kdres *rset, double *pos)
{
	if(rset->riter) {
		if(pos) {
			memcpy(pos, rset->riter->item->pos, rset->tree->dim * sizeof *pos);
		}
		return rset->riter->item->data;
	}
	return 0;
}

//將返回結果的節點的座標和data抽取出來,座標為float型的值
void *kd_res_itemf(struct kdres *rset, float *pos)
{
	if(rset->riter) {
		if(pos) {
			int i;
			for(i=0; i<rset->tree->dim; i++) {
				pos[i] = rset->riter->item->pos[i];
			}
		}
		return rset->riter->item->data;
	}
	return 0;
}

//將返回結果的節點的座標和data抽取出來,座標具體形式給出
void *kd_res_item3(struct kdres *rset, double *x, double *y, double *z)
{
	if(rset->riter) {
		if(*x) *x = rset->riter->item->pos[0];
		if(*y) *y = rset->riter->item->pos[1];
		if(*z) *z = rset->riter->item->pos[2];
	}
	return 0;
}

//將返回結果的節點的座標和data抽取出來,座標為float型的值,座標具體形式給出
void *kd_res_item3f(struct kdres *rset, float *x, float *y, float *z)
{
	if(rset->riter) {
		if(*x) *x = rset->riter->item->pos[0];
		if(*y) *y = rset->riter->item->pos[1];
		if(*z) *z = rset->riter->item->pos[2];
	}
	return 0;
}

//獲取data資料
void *kd_res_item_data(struct kdres *set)
{
	return kd_res_item(set, 0);
}

/* ---- hyperrectangle helpers ---- */
//建立超平面,包括三個引數:維度,每維的最小值和最大值陣列
static struct kdhyperrect* hyperrect_create(int dim, const double *min, const double *max)
{
	size_t size = dim * sizeof(double);
	struct kdhyperrect* rect = 0;

	if (!(rect = (kdhyperrect*)malloc(sizeof(struct kdhyperrect)))) 
	{
		return 0;
	}

	rect->dim = dim;
	if (!(rect->min = (double*)malloc(size))) {
		free(rect);
		return 0;
	}
	if (!(rect->max = (double*)malloc(size))) {
		free(rect->min);
		free(rect);
		return 0;
	}
	memcpy(rect->min, min, size);
	memcpy(rect->max, max, size);

	return rect;
}

//釋放超平面結構體
static void hyperrect_free(struct kdhyperrect *rect)
{
	free(rect->min);
	free(rect->max);
	free(rect);
}

//賦值超平面結構體
static struct kdhyperrect* hyperrect_duplicate(const struct kdhyperrect *rect)
{
	return hyperrect_create(rect->dim, rect->min, rect->max);
}

//更新超平面結構體最大\最小值陣列
static void hyperrect_extend(struct kdhyperrect *rect, const double *pos)
{
	int i;

	for (i=0; i < rect->dim; i++) {
		if (pos[i] < rect->min[i]) {
			rect->min[i] = pos[i];
		}
		if (pos[i] > rect->max[i]) {
			rect->max[i] = pos[i];
		}
	}
}

//計算固定座標點與超平面之間的距離
static double hyperrect_dist_sq(struct kdhyperrect *rect, const double *pos)
{
	int i;
	double result = 0;

	for (i=0; i < rect->dim; i++) 
	{
		if (pos[i] < rect->min[i]) 
		{
			result += SQ(rect->min[i] - pos[i]);
		} 
		else if (pos[i] > rect->max[i]) 
		{
			result += SQ(rect->max[i] - pos[i]);
		}
	}
	return result;
}


/* ---- static helpers ---- */
#ifdef USE_LIST_NODE_ALLOCATOR
/* special list node allocators. */
static struct res_node *free_nodes;

#ifndef NO_PTHREADS
static pthread_mutex_t alloc_mutex = PTHREAD_MUTEX_INITIALIZER;
#endif

//建立返回結果節點
static struct res_node *alloc_resnode(void)
{
	struct res_node *node;

#ifndef NO_PTHREADS
	pthread_mutex_lock(&alloc_mutex);
#endif

	if(!free_nodes) {
		node = malloc(sizeof *node);
	} else {
		node = free_nodes;
		free_nodes = free_nodes->next;
		node->next = 0;
	}

#ifndef NO_PTHREADS
	pthread_mutex_unlock(&alloc_mutex);
#endif

	return node;
}

//釋放返回結果節點
static void free_resnode(struct res_node *node)
{
#ifndef NO_PTHREADS
	pthread_mutex_lock(&alloc_mutex);
#endif

	node->next = free_nodes;
	free_nodes = node;

#ifndef NO_PTHREADS
	pthread_mutex_unlock(&alloc_mutex);
#endif
}
#endif	/* list node allocator or not */


/* inserts the item. if dist_sq is >= 0, then do an ordered insert */
/* TODO make the ordering code use heapsort */
//函式引數: 返回結果節點指標,樹節點指標,距離函式
//將一個結果節點插入到返回結果的列表中
static int rlist_insert(struct res_node *list, struct kdnode *item, double dist_sq)
{
	struct res_node *rnode;

	//建立一個返回結果的節點
	if(!(rnode = (res_node*)alloc_resnode())) 
	{
		return -1;
	}
	rnode->item = item;           //對應的樹節點
	rnode->dist_sq = dist_sq;     //對應的距離值

	//當距離大於零的時候
	if(dist_sq >= 0.0) 
	{
		while(list->next && list->next->dist_sq < dist_sq) 
		{
			list = list->next;
		}
	}
	rnode->next = list->next;
	list->next = rnode;
	return 0;
}

//清除返回結果的集合
//本質上是個雙鏈表中單鏈表的清理
static void clear_results(struct kdres *rset)
{
	struct res_node *tmp, *node = rset->rlist->next;

	while(node) 
	{
		tmp = node;
		node = node->next;
		free_resnode(tmp);
	}

	rset->rlist->next = 0;
}