30#define Magnitude(X) ((X) < 0 ? -(X) : (X))
31#define NodeFound(N, K, D) (((N)->Key == (K)) && ((N)->Data == (D)))
36#define MINSEARCH (-FLT_MAX)
37#define MAXSEARCH FLT_MAX
40static int NextLevel(KDTREE *tree,
int level) {
43 if (level >= tree->KeySize) {
46 }
while (tree->KeyDesc[level].NonEssential);
52template <
typename Key,
typename Value>
70 return elements_count_;
84template <
typename Key,
typename Value>
86 : max_key_(max_key), elements_count_(0), k_(k < 1 ? 1 : k), max_index_(0) {
90template <
typename Key,
typename Value>
95template <
typename Key,
typename Value>
97 if (elements_count_ < k_) {
100 return elements_[max_index_].key;
103template <
typename Key,
typename Value>
105 if (elements_count_ < k_) {
107 if (key > elements_[max_index_].key) {
108 max_index_ = elements_count_ - 1;
111 }
else if (key < elements_[max_index_].key) {
115 for (
int i = 0;
i < elements_count_;
i++) {
116 if (elements_[
i].key > elements_[max_index_].key) {
134 void Search(
int *result_count,
float *distances,
void **results);
137 void SearchRec(
int Level,
KDNODE *SubTree);
138 bool BoxIntersectsSearch(
float *lower,
float *upper);
148 : tree_(tree), query_point_(query_point), results_(
MAXSEARCH, k_closest) {
149 sb_min_ =
new float[tree->
KeySize];
150 sb_max_ =
new float[tree->
KeySize];
170 *result_count =
count;
171 for (
int j = 0; j <
count; j++) {
174 distances[j] =
static_cast<float>(sqrt(
static_cast<double>(results_.
elements()[j].key)));
175 results[j] = results_.
elements()[j].value;
187 auto *KDTree =
new KDTREE(KeySize);
188 for (
int i = 0;
i < KeySize;
i++) {
190 KDTree->KeyDesc[
i].Circular = KeyDesc[
i].
Circular;
191 if (KeyDesc[
i].Circular) {
192 KDTree->KeyDesc[
i].Min = KeyDesc[
i].
Min;
193 KDTree->KeyDesc[
i].Max = KeyDesc[
i].
Max;
194 KDTree->KeyDesc[
i].Range = KeyDesc[
i].
Max - KeyDesc[
i].
Min;
195 KDTree->KeyDesc[
i].HalfRange = KDTree->KeyDesc[
i].Range / 2;
196 KDTree->KeyDesc[
i].MidRange = (KeyDesc[
i].
Max + KeyDesc[
i].
Min) / 2;
202 KDTree->Root.Left =
nullptr;
203 KDTree->Root.Right =
nullptr;
216 auto PtrToNode = &(Tree->
Root.
Left);
217 auto Node = *PtrToNode;
218 auto Level = NextLevel(Tree, -1);
219 while (Node !=
nullptr) {
220 if (Key[Level] < Node->BranchPoint) {
221 PtrToNode = &(Node->Left);
222 if (Key[Level] > Node->LeftBranch) {
223 Node->LeftBranch = Key[Level];
226 PtrToNode = &(Node->Right);
227 if (Key[Level] < Node->RightBranch) {
228 Node->RightBranch = Key[Level];
231 Level = NextLevel(Tree, Level);
235 *PtrToNode =
new KDNODE(Tree, Key, Data, Level);
258 Father = &(Tree->
Root);
259 Current = Father->
Left;
260 Level = NextLevel(Tree, -1);
263 while ((Current !=
nullptr) && (!
NodeFound(Current, Key, Data))) {
266 Current = Current->
Left;
268 Current = Current->
Right;
271 Level = NextLevel(Tree, Level);
274 if (Current !=
nullptr) {
275 if (Current == Father->
Left) {
276 Father->
Left =
nullptr;
279 Father->
Right =
nullptr;
306 int *NumberOfResults,
void **NBuffer,
float DBuffer[]) {
308 search.Search(NumberOfResults, DBuffer, NBuffer);
329void KDTreeSearch::SearchRec(
int level, KDNODE *sub_tree) {
334 if (!BoxIntersectsSearch(sb_min_, sb_max_)) {
341 if (query_point_[level] < sub_tree->BranchPoint) {
342 if (sub_tree->Left !=
nullptr) {
343 float tmp = sb_max_[level];
344 sb_max_[level] = sub_tree->LeftBranch;
345 SearchRec(NextLevel(tree_, level), sub_tree->Left);
346 sb_max_[level] = tmp;
348 if (sub_tree->Right !=
nullptr) {
349 float tmp = sb_min_[level];
350 sb_min_[level] = sub_tree->RightBranch;
351 SearchRec(NextLevel(tree_, level), sub_tree->Right);
352 sb_min_[level] = tmp;
355 if (sub_tree->Right !=
nullptr) {
356 float tmp = sb_min_[level];
357 sb_min_[level] = sub_tree->RightBranch;
358 SearchRec(NextLevel(tree_, level), sub_tree->Right);
359 sb_min_[level] = tmp;
361 if (sub_tree->Left !=
nullptr) {
362 float tmp = sb_max_[level];
363 sb_max_[level] = sub_tree->LeftBranch;
364 SearchRec(NextLevel(tree_, level), sub_tree->Left);
365 sb_max_[level] = tmp;
379 float total_distance = 0;
381 for (; k > 0; k--, p1++, p2++, dim++) {
386 float dimension_distance = *p1 - *p2;
390 dimension_distance =
Magnitude(dimension_distance);
391 float wrap_distance = dim->
Max - dim->
Min - dimension_distance;
392 dimension_distance = std::min(dimension_distance, wrap_distance);
395 total_distance += dimension_distance * dimension_distance;
397 return total_distance;
409bool KDTreeSearch::BoxIntersectsSearch(
float *lower,
float *upper) {
410 float *query = query_point_;
412 double total_distance = 0.0;
413 double radius_squared =
415 PARAM_DESC *dim = &tree_->
KeyDesc[0];
417 for (
int i = tree_->
KeySize;
i > 0;
i--, dim++, query++, lower++, upper++) {
418 if (dim->NonEssential) {
422 float dimension_distance;
423 if (*query < *lower) {
424 dimension_distance = *lower - *query;
425 }
else if (*query > *upper) {
426 dimension_distance = *query - *upper;
428 dimension_distance = 0;
433 float wrap_distance = FLT_MAX;
434 if (*query < *lower) {
435 wrap_distance = *query + dim->Max - dim->Min - *upper;
436 }
else if (*query > *upper) {
437 wrap_distance = *lower - (*query - (dim->Max - dim->Min));
439 dimension_distance = std::min(dimension_distance, wrap_distance);
442 total_distance +=
static_cast<double>(dimension_distance) * dimension_distance;
443 if (total_distance >= radius_squared) {
467 (*action)(context, sub_tree->
Data, level);
468 if (sub_tree->
Left !=
nullptr) {
469 Walk(tree,
action, context, sub_tree->
Left, NextLevel(tree, level));
471 if (sub_tree->
Right !=
nullptr) {
478 if (nodes ==
nullptr) {
#define NodeFound(N, K, D)
void(*)(ClusteringContext *context, CLUSTER *Cluster, int32_t Level) kdwalk_proc
void KDDelete(KDTREE *Tree, float Key[], void *Data)
void KDWalk(KDTREE *Tree, kdwalk_proc action, ClusteringContext *context)
float ComputeDistance(int k, PARAM_DESC *dim, float p1[], float p2[])
void Walk(KDTREE *tree, kdwalk_proc action, ClusteringContext *context, KDNODE *sub_tree, int32_t level)
float DistanceSquared(int k, PARAM_DESC *dim, float p1[], float p2[])
void InsertNodes(KDTREE *tree, KDNODE *nodes)
KDTREE * MakeKDTree(int16_t KeySize, const PARAM_DESC KeyDesc[])
LIST search(LIST list, void *key, int_compare is_equal)
void KDNearestNeighborSearch(KDTREE *Tree, float Query[], int QuerySize, float MaxDistance, int *NumberOfResults, void **NBuffer, float DBuffer[])
void KDStore(KDTREE *Tree, float *Key, CLUSTER *Data)
bool insert(Key k, Value v)
const Key & max_insertable_key()
const Element * elements()
Element(const Key &k, const Value &v)
KDTreeSearch(KDTREE *tree, float *query_point, int k_closest)
void Search(int *result_count, float *distances, void **results)
std::vector< PARAM_DESC > KeyDesc