31 #define Magnitude(X) ((X) < 0 ? -(X) : (X))
32 #define NodeFound(N,K,D) (( (N)->Key == (K) ) && ( (N)->Data == (D) ))
37 #define MINSEARCH -MAX_FLOAT32
38 #define MAXSEARCH MAX_FLOAT32
41 static int NextLevel(
KDTREE *tree,
int level) {
52 template<
typename Key,
typename Value>
55 MinK(Key max_key,
int k);
66 bool insert(Key k, Value v);
70 const Element*
elements() {
return elements_; }
80 template<
typename Key,
typename Value>
82 max_key_(max_key), elements_count_(0), k_(k < 1 ? 1 : k), max_index_(0) {
86 template<
typename Key,
typename Value>
91 template<
typename Key,
typename Value>
93 if (elements_count_ < k_)
95 return elements_[max_index_].key;
98 template<
typename Key,
typename Value>
100 if (elements_count_ < k_) {
101 elements_[elements_count_++] =
Element(key, value);
102 if (key > elements_[max_index_].key)
103 max_index_ = elements_count_ - 1;
105 }
else if (key < elements_[max_index_].key) {
107 elements_[max_index_] =
Element(key, value);
109 for (
int i = 0; i < elements_count_; i++) {
110 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);
142 query_point_(query_point) {
162 for (
int i = 0; i < tree_->
KeySize; i++) {
168 *result_count =
count;
169 for (
int j = 0; j <
count; j++) {
171 results[j] = results_->
elements()[j].value;
185 for (
int i = 0; i < KeySize; i++) {
188 if (KeyDesc[i].Circular) {
225 Level = NextLevel(Tree, -1);
226 while (Node !=
NULL) {
228 PtrToNode = &(Node->
Left);
233 PtrToNode = &(Node->
Right);
237 Level = NextLevel(Tree, Level);
241 *PtrToNode =
MakeKDNode(Tree, Key, (
void *) Data, Level);
271 Father = &(Tree->
Root);
272 Current = Father->
Left;
273 Level = NextLevel(Tree, -1);
276 while ((Current !=
NULL) && (!
NodeFound (Current, Key, Data))) {
279 Current = Current->
Left;
281 Current = Current->
Right;
283 Level = NextLevel(Tree, Level);
286 if (Current !=
NULL) {
287 if (Current == Father->
Left) {
324 int *NumberOfResults,
void **NBuffer,
FLOAT32 DBuffer[]) {
326 search.
Search(NumberOfResults, DBuffer, NBuffer);
334 Walk(Tree, action, context, Tree->
Root.
Left, NextLevel(Tree, -1));
380 NewNode->
Data = Data;
403 void KDTreeSearch::SearchRec(
int level,
KDNODE *sub_tree) {
407 if (!BoxIntersectsSearch(sb_min_, sb_max_))
411 query_point_, sub_tree->
Key),
418 SearchRec(NextLevel(tree_, level), sub_tree->
Left);
419 sb_max_[level] = tmp;
424 SearchRec(NextLevel(tree_, level), sub_tree->
Right);
425 sb_min_[level] = tmp;
431 SearchRec(NextLevel(tree_, level), sub_tree->
Right);
432 sb_min_[level] = tmp;
437 SearchRec(NextLevel(tree_, level), sub_tree->
Left);
438 sb_max_[level] = tmp;
455 for (; k > 0; k--, p1++, p2++, dim++) {
459 FLOAT32 dimension_distance = *p1 - *p2;
463 dimension_distance =
Magnitude(dimension_distance);
464 FLOAT32 wrap_distance = dim->
Max - dim->
Min - dimension_distance;
465 dimension_distance =
MIN(dimension_distance, wrap_distance);
468 total_distance += dimension_distance * dimension_distance;
470 return total_distance;
482 bool KDTreeSearch::BoxIntersectsSearch(
FLOAT32 *lower,
FLOAT32 *upper) {
489 for (
int i = tree_->
KeySize; i > 0; i--, dim++, query++, lower++, upper++) {
495 dimension_distance = *lower - *query;
496 else if (*query > *upper)
497 dimension_distance = *query - *upper;
499 dimension_distance = 0;
505 wrap_distance = *query + dim->
Max - dim->
Min - *upper;
506 else if (*query > *upper)
507 wrap_distance = *lower - (*query - (dim->
Max - dim->
Min));
508 dimension_distance =
MIN(dimension_distance, wrap_distance);
511 total_distance += dimension_distance * dimension_distance;
512 if (total_distance >= radius_squared)
537 (*action)(context, sub_tree->
Data, level);
539 Walk(tree, action, context, sub_tree->
Left, NextLevel(tree, level));
541 Walk(tree, action, context, sub_tree->
Right, NextLevel(tree, level));
557 if (sub_tree !=
NULL) {
void memfree(void *element)
FLOAT32 DistanceSquared(int k, PARAM_DESC *dim, FLOAT32 p1[], FLOAT32 p2[])
#define NodeFound(N, K, D)
KDNODE * MakeKDNode(KDTREE *tree, FLOAT32 Key[], void *Data, int Index)
const Key & max_insertable_key()
bool insert(Key k, Value v)
void KDNearestNeighborSearch(KDTREE *Tree, FLOAT32 Query[], int QuerySize, FLOAT32 MaxDistance, int *NumberOfResults, void **NBuffer, FLOAT32 DBuffer[])
void Walk(KDTREE *tree, void_proc action, void *context, KDNODE *sub_tree, inT32 level)
void FreeKDTree(KDTREE *Tree)
void FreeSubTree(KDNODE *sub_tree)
LIST search(LIST list, void *key, int_compare is_equal)
void InsertNodes(KDTREE *tree, KDNODE *nodes)
void FreeKDNode(KDNODE *Node)
FLOAT32 ComputeDistance(int k, PARAM_DESC *dim, FLOAT32 p1[], FLOAT32 p2[])
void KDStore(KDTREE *Tree, FLOAT32 *Key, void *Data)
Element(const Key &k, const Value &v)
const Element * elements()
void Search(int *result_count, FLOAT32 *distances, void **results)
void KDWalk(KDTREE *Tree, void_proc action, void *context)
void KDDelete(KDTREE *Tree, FLOAT32 Key[], void *Data)
KDTREE * MakeKDTree(inT16 KeySize, const PARAM_DESC KeyDesc[])
KDTreeSearch(KDTREE *tree, FLOAT32 *query_point, int k_closest)