30 #define Magnitude(X) ((X) < 0 ? -(X) : (X)) 31 #define NodeFound(N,K,D) (( (N)->Key == (K) ) && ( (N)->Data == (D) )) 36 #define MINSEARCH -MAX_FLOAT32 37 #define MAXSEARCH MAX_FLOAT32 40 static int NextLevel(
KDTREE *tree,
int level) {
51 template<
typename Key,
typename Value>
54 MinK(Key max_key,
int k);
65 bool insert(Key k, Value v);
79 template<
typename Key,
typename Value>
81 max_key_(max_key), elements_count_(0), k_(k < 1 ? 1 : k), max_index_(0) {
82 elements_ =
new Element[k_];
85 template<
typename Key,
typename Value>
90 template<
typename Key,
typename Value>
92 if (elements_count_ < k_)
94 return elements_[max_index_].
key;
97 template<
typename Key,
typename Value>
99 if (elements_count_ < k_) {
100 elements_[elements_count_++] = Element(key, value);
101 if (key > elements_[max_index_].key)
102 max_index_ = elements_count_ - 1;
104 }
else if (key < elements_[max_index_].key) {
106 elements_[max_index_] = Element(key, value);
108 for (
int i = 0; i < elements_count_; i++) {
109 if (elements_[i].key > elements_[max_index_].key)
127 void Search(
int *result_count,
FLOAT32 *distances,
void **results);
130 void SearchRec(
int Level,
KDNODE *SubTree);
141 : tree_(tree), query_point_(query_point), results_(
MAXSEARCH, k_closest) {
159 for (
int i = 0; i < tree_->
KeySize; i++) {
165 *result_count =
count;
166 for (
int j = 0; j <
count; j++) {
170 results[j] = results_.
elements()[j].value;
184 for (
int i = 0; i < KeySize; i++) {
187 if (KeyDesc[i].Circular) {
224 Level = NextLevel(Tree, -1);
225 while (Node != NULL) {
227 PtrToNode = &(Node->
Left);
232 PtrToNode = &(Node->
Right);
236 Level = NextLevel(Tree, Level);
240 *PtrToNode =
MakeKDNode(Tree, Key, (
void *) Data, Level);
269 Father = &(Tree->
Root);
270 Current = Father->
Left;
271 Level = NextLevel(Tree, -1);
274 while ((Current != NULL) && (!
NodeFound (Current, Key, Data))) {
277 Current = Current->
Left;
279 Current = Current->
Right;
281 Level = NextLevel(Tree, Level);
284 if (Current != NULL) {
285 if (Current == Father->
Left) {
289 Father->
Right = NULL;
321 int *NumberOfResults,
void **NBuffer,
FLOAT32 DBuffer[]) {
323 search.
Search(NumberOfResults, DBuffer, NBuffer);
331 Walk(Tree, action, context, Tree->
Root.
Left, NextLevel(Tree, -1));
377 NewNode->
Data = Data;
381 NewNode->
Left = NULL;
382 NewNode->
Right = NULL;
397 void KDTreeSearch::SearchRec(
int level,
KDNODE *sub_tree) {
401 if (!BoxIntersectsSearch(sb_min_, sb_max_))
409 if (sub_tree->
Left != NULL) {
412 SearchRec(NextLevel(tree_, level), sub_tree->
Left);
413 sb_max_[level] = tmp;
415 if (sub_tree->
Right != NULL) {
418 SearchRec(NextLevel(tree_, level), sub_tree->
Right);
419 sb_min_[level] = tmp;
422 if (sub_tree->
Right != NULL) {
425 SearchRec(NextLevel(tree_, level), sub_tree->
Right);
426 sb_min_[level] = tmp;
428 if (sub_tree->
Left != NULL) {
431 SearchRec(NextLevel(tree_, level), sub_tree->
Left);
432 sb_max_[level] = tmp;
449 for (; k > 0; k--, p1++, p2++, dim++) {
453 FLOAT32 dimension_distance = *p1 - *p2;
457 dimension_distance =
Magnitude(dimension_distance);
458 FLOAT32 wrap_distance = dim->
Max - dim->
Min - dimension_distance;
459 dimension_distance =
MIN(dimension_distance, wrap_distance);
462 total_distance += dimension_distance * dimension_distance;
464 return total_distance;
476 bool KDTreeSearch::BoxIntersectsSearch(
FLOAT32 *lower,
FLOAT32 *upper) {
484 for (
int i = tree_->
KeySize; i > 0; i--, dim++, query++, lower++, upper++) {
490 dimension_distance = *lower - *query;
491 else if (*query > *upper)
492 dimension_distance = *query - *upper;
494 dimension_distance = 0;
500 wrap_distance = *query + dim->
Max - dim->
Min - *upper;
501 else if (*query > *upper)
502 wrap_distance = *lower - (*query - (dim->
Max - dim->
Min));
503 dimension_distance =
MIN(dimension_distance, wrap_distance);
506 total_distance += dimension_distance * dimension_distance;
507 if (total_distance >= radius_squared)
532 (*action)(context, sub_tree->
Data, level);
533 if (sub_tree->
Left != NULL)
534 Walk(tree, action, context, sub_tree->
Left, NextLevel(tree, level));
535 if (sub_tree->
Right != NULL)
536 Walk(tree, action, context, sub_tree->
Right, NextLevel(tree, level));
551 if (sub_tree != NULL) {
KDNODE * MakeKDNode(KDTREE *tree, FLOAT32 Key[], void *Data, int Index)
#define NodeFound(N, K, D)
const Element * elements()
void KDStore(KDTREE *Tree, FLOAT32 *Key, void *Data)
const Key & max_insertable_key()
bool insert(Key k, Value v)
void InsertNodes(KDTREE *tree, KDNODE *nodes)
void FreeKDNode(KDNODE *Node)
void KDDelete(KDTREE *Tree, FLOAT32 Key[], void *Data)
void FreeSubTree(KDNODE *sub_tree)
void FreeKDTree(KDTREE *Tree)
LIST search(LIST list, void *key, int_compare is_equal)
KDTREE * MakeKDTree(inT16 KeySize, const PARAM_DESC KeyDesc[])
void Search(int *result_count, FLOAT32 *distances, void **results)
void KDNearestNeighborSearch(KDTREE *Tree, FLOAT32 Query[], int QuerySize, FLOAT32 MaxDistance, int *NumberOfResults, void **NBuffer, FLOAT32 DBuffer[])
FLOAT32 ComputeDistance(int k, PARAM_DESC *dim, FLOAT32 p1[], FLOAT32 p2[])
void Walk(KDTREE *tree, void_proc action, void *context, KDNODE *sub_tree, inT32 level)
Element(const Key &k, const Value &v)
FLOAT32 DistanceSquared(int k, PARAM_DESC *dim, FLOAT32 p1[], FLOAT32 p2[])
void KDWalk(KDTREE *Tree, void_proc action, void *context)
KDTreeSearch(KDTREE *tree, FLOAT32 *query_point, int k_closest)