tesseract  4.0.0-1-g2a2b
kdtree.cpp
Go to the documentation of this file.
1 /******************************************************************************
2  ** Filename: kdtree.cpp
3  ** Purpose: Routines for managing K-D search trees
4  ** Author: Dan Johnson
5  **
6  ** (c) Copyright Hewlett-Packard Company, 1988.
7  ** Licensed under the Apache License, Version 2.0 (the "License");
8  ** you may not use this file except in compliance with the License.
9  ** You may obtain a copy of the License at
10  ** http://www.apache.org/licenses/LICENSE-2.0
11  ** Unless required by applicable law or agreed to in writing, software
12  ** distributed under the License is distributed on an "AS IS" BASIS,
13  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  ** See the License for the specific language governing permissions and
15  ** limitations under the License.
16  ******************************************************************************/
17 
18 /*-----------------------------------------------------------------------------
19  Include Files and Type Defines
20 -----------------------------------------------------------------------------*/
21 #include "kdtree.h"
22 #include "cutil.h" // for void_proc
23 #include "emalloc.h"
24 
25 #include <algorithm>
26 #include <cfloat> // for FLT_MAX
27 #include <cstdio>
28 #include <cmath>
29 
30 #define Magnitude(X) ((X) < 0 ? -(X) : (X))
31 #define NodeFound(N,K,D) (((N)->Key == (K)) && ((N)->Data == (D)))
32 
33 /*-----------------------------------------------------------------------------
34  Global Data Definitions and Declarations
35 -----------------------------------------------------------------------------*/
36 #define MINSEARCH -FLT_MAX
37 #define MAXSEARCH FLT_MAX
38 
39 // Helper function to find the next essential dimension in a cycle.
40 static int NextLevel(KDTREE *tree, int level) {
41  do {
42  ++level;
43  if (level >= tree->KeySize)
44  level = 0;
45  } while (tree->KeyDesc[level].NonEssential);
46  return level;
47 }
48 
49 //-----------------------------------------------------------------------------
51 template<typename Key, typename Value>
52 class MinK {
53  public:
54  MinK(Key max_key, int k);
55  ~MinK();
56 
57  struct Element {
58  Element() {}
59  Element(const Key& k, const Value& v) : key(k), value(v) {}
60 
61  Key key;
62  Value value;
63  };
64 
65  bool insert(Key k, Value v);
66  const Key& max_insertable_key();
67 
68  int elements_count() { return elements_count_; }
69  const Element* elements() { return elements_; }
70 
71  private:
72  const Key max_key_; //< the maximum possible Key
73  Element *elements_; //< unsorted array of elements
74  int elements_count_; //< the number of results collected so far
75  int k_; //< the number of results we want from the search
76  int max_index_; //< the index of the result with the largest key
77 };
78 
79 template<typename Key, typename Value>
80 MinK<Key, Value>::MinK(Key max_key, int k) :
81  max_key_(max_key), elements_count_(0), k_(k < 1 ? 1 : k), max_index_(0) {
82  elements_ = new Element[k_];
83 }
84 
85 template<typename Key, typename Value>
87  delete []elements_;
88 }
89 
90 template<typename Key, typename Value>
92  if (elements_count_ < k_)
93  return max_key_;
94  return elements_[max_index_].key;
95 }
96 
97 template<typename Key, typename Value>
98 bool MinK<Key, Value>::insert(Key key, Value 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;
103  return true;
104  } else if (key < elements_[max_index_].key) {
105  // evict the largest element.
106  elements_[max_index_] = Element(key, value);
107  // recompute max_index_
108  for (int i = 0; i < elements_count_; i++) {
109  if (elements_[i].key > elements_[max_index_].key)
110  max_index_ = i;
111  }
112  return true;
113  }
114  return false;
115 }
116 
117 
118 //-----------------------------------------------------------------------------
122  public:
123  KDTreeSearch(KDTREE* tree, float *query_point, int k_closest);
124  ~KDTreeSearch();
125 
127  void Search(int *result_count, float *distances, void **results);
128 
129  private:
130  void SearchRec(int Level, KDNODE *SubTree);
131  bool BoxIntersectsSearch(float *lower, float *upper);
132 
133  KDTREE *tree_;
134  float *query_point_;
135  float *sb_min_; //< search box minimum
136  float *sb_max_; //< search box maximum
137  MinK<float, void *> results_;
138 };
139 
140 KDTreeSearch::KDTreeSearch(KDTREE *tree, float *query_point, int k_closest)
141  : tree_(tree), query_point_(query_point), results_(MAXSEARCH, k_closest) {
142  sb_min_ = new float[tree->KeySize];
143  sb_max_ = new float[tree->KeySize];
144 }
145 
147  delete[] sb_min_;
148  delete[] sb_max_;
149 }
150 
153 void KDTreeSearch::Search(int *result_count,
154  float *distances,
155  void **results) {
156  if (tree_->Root.Left == nullptr) {
157  *result_count = 0;
158  } else {
159  for (int i = 0; i < tree_->KeySize; i++) {
160  sb_min_[i] = tree_->KeyDesc[i].Min;
161  sb_max_[i] = tree_->KeyDesc[i].Max;
162  }
163  SearchRec(0, tree_->Root.Left);
164  int count = results_.elements_count();
165  *result_count = count;
166  for (int j = 0; j < count; j++) {
167  // Pre-cast to float64 as key is a template type and we have no control
168  // over its actual type.
169  distances[j] = (float)sqrt((double)results_.elements()[j].key);
170  results[j] = results_.elements()[j].value;
171  }
172  }
173 }
174 
175 /*-----------------------------------------------------------------------------
176  Public Code
177 -----------------------------------------------------------------------------*/
181 KDTREE *MakeKDTree(int16_t KeySize, const PARAM_DESC KeyDesc[]) {
182  KDTREE *KDTree = (KDTREE *) Emalloc(
183  sizeof(KDTREE) + (KeySize - 1) * sizeof(PARAM_DESC));
184  for (int i = 0; i < KeySize; i++) {
185  KDTree->KeyDesc[i].NonEssential = KeyDesc[i].NonEssential;
186  KDTree->KeyDesc[i].Circular = KeyDesc[i].Circular;
187  if (KeyDesc[i].Circular) {
188  KDTree->KeyDesc[i].Min = KeyDesc[i].Min;
189  KDTree->KeyDesc[i].Max = KeyDesc[i].Max;
190  KDTree->KeyDesc[i].Range = KeyDesc[i].Max - KeyDesc[i].Min;
191  KDTree->KeyDesc[i].HalfRange = KDTree->KeyDesc[i].Range / 2;
192  KDTree->KeyDesc[i].MidRange = (KeyDesc[i].Max + KeyDesc[i].Min) / 2;
193  } else {
194  KDTree->KeyDesc[i].Min = MINSEARCH;
195  KDTree->KeyDesc[i].Max = MAXSEARCH;
196  }
197  }
198  KDTree->KeySize = KeySize;
199  KDTree->Root.Left = nullptr;
200  KDTree->Root.Right = nullptr;
201  return KDTree;
202 }
203 
204 
213 void KDStore(KDTREE *Tree, float *Key, void *Data) {
214  int Level;
215  KDNODE *Node;
216  KDNODE **PtrToNode;
217 
218  PtrToNode = &(Tree->Root.Left);
219  Node = *PtrToNode;
220  Level = NextLevel(Tree, -1);
221  while (Node != nullptr) {
222  if (Key[Level] < Node->BranchPoint) {
223  PtrToNode = &(Node->Left);
224  if (Key[Level] > Node->LeftBranch)
225  Node->LeftBranch = Key[Level];
226  }
227  else {
228  PtrToNode = &(Node->Right);
229  if (Key[Level] < Node->RightBranch)
230  Node->RightBranch = Key[Level];
231  }
232  Level = NextLevel(Tree, Level);
233  Node = *PtrToNode;
234  }
235 
236  *PtrToNode = MakeKDNode(Tree, Key, (void *) Data, Level);
237 } /* KDStore */
238 
253 void
254 KDDelete (KDTREE * Tree, float Key[], void *Data) {
255  int Level;
256  KDNODE *Current;
257  KDNODE *Father;
258 
259  /* initialize search at root of tree */
260  Father = &(Tree->Root);
261  Current = Father->Left;
262  Level = NextLevel(Tree, -1);
263 
264  /* search tree for node to be deleted */
265  while ((Current != nullptr) && (!NodeFound (Current, Key, Data))) {
266  Father = Current;
267  if (Key[Level] < Current->BranchPoint)
268  Current = Current->Left;
269  else
270  Current = Current->Right;
271 
272  Level = NextLevel(Tree, Level);
273  }
274 
275  if (Current != nullptr) { /* if node to be deleted was found */
276  if (Current == Father->Left) {
277  Father->Left = nullptr;
278  Father->LeftBranch = Tree->KeyDesc[Level].Min;
279  } else {
280  Father->Right = nullptr;
281  Father->RightBranch = Tree->KeyDesc[Level].Max;
282  }
283 
284  InsertNodes(Tree, Current->Left);
285  InsertNodes(Tree, Current->Right);
286  FreeSubTree(Current);
287  }
288 } /* KDDelete */
289 
307  KDTREE *Tree, float Query[], int QuerySize, float MaxDistance,
308  int *NumberOfResults, void **NBuffer, float DBuffer[]) {
309  KDTreeSearch search(Tree, Query, QuerySize);
310  search.Search(NumberOfResults, DBuffer, NBuffer);
311 }
312 
313 
314 /*---------------------------------------------------------------------------*/
316 void KDWalk(KDTREE *Tree, void_proc action, void *context) {
317  if (Tree->Root.Left != nullptr)
318  Walk(Tree, action, context, Tree->Root.Left, NextLevel(Tree, -1));
319 }
320 
321 
322 /*---------------------------------------------------------------------------*/
333 void FreeKDTree(KDTREE *Tree) {
334  FreeSubTree(Tree->Root.Left);
335  free(Tree);
336 } /* FreeKDTree */
337 
338 
339 /*-----------------------------------------------------------------------------
340  Private Code
341 -----------------------------------------------------------------------------*/
342 /*---------------------------------------------------------------------------*/
354 KDNODE *MakeKDNode(KDTREE *tree, float Key[], void *Data, int Index) {
355  KDNODE *NewNode;
356 
357  NewNode = (KDNODE *) Emalloc (sizeof (KDNODE));
358 
359  NewNode->Key = Key;
360  NewNode->Data = Data;
361  NewNode->BranchPoint = Key[Index];
362  NewNode->LeftBranch = tree->KeyDesc[Index].Min;
363  NewNode->RightBranch = tree->KeyDesc[Index].Max;
364  NewNode->Left = nullptr;
365  NewNode->Right = nullptr;
366 
367  return NewNode;
368 } /* MakeKDNode */
369 
370 
371 /*---------------------------------------------------------------------------*/
372 void FreeKDNode(KDNODE *Node) { free(Node); }
373 
374 /*---------------------------------------------------------------------------*/
380 void KDTreeSearch::SearchRec(int level, KDNODE *sub_tree) {
381  if (level >= tree_->KeySize)
382  level = 0;
383 
384  if (!BoxIntersectsSearch(sb_min_, sb_max_))
385  return;
386 
387  results_.insert(DistanceSquared(tree_->KeySize, tree_->KeyDesc, query_point_,
388  sub_tree->Key),
389  sub_tree->Data);
390 
391  if (query_point_[level] < sub_tree->BranchPoint) {
392  if (sub_tree->Left != nullptr) {
393  float tmp = sb_max_[level];
394  sb_max_[level] = sub_tree->LeftBranch;
395  SearchRec(NextLevel(tree_, level), sub_tree->Left);
396  sb_max_[level] = tmp;
397  }
398  if (sub_tree->Right != nullptr) {
399  float tmp = sb_min_[level];
400  sb_min_[level] = sub_tree->RightBranch;
401  SearchRec(NextLevel(tree_, level), sub_tree->Right);
402  sb_min_[level] = tmp;
403  }
404  } else {
405  if (sub_tree->Right != nullptr) {
406  float tmp = sb_min_[level];
407  sb_min_[level] = sub_tree->RightBranch;
408  SearchRec(NextLevel(tree_, level), sub_tree->Right);
409  sb_min_[level] = tmp;
410  }
411  if (sub_tree->Left != nullptr) {
412  float tmp = sb_max_[level];
413  sb_max_[level] = sub_tree->LeftBranch;
414  SearchRec(NextLevel(tree_, level), sub_tree->Left);
415  sb_max_[level] = tmp;
416  }
417  }
418 }
419 
420 
421 /*---------------------------------------------------------------------------*/
429 float DistanceSquared(int k, PARAM_DESC *dim, float p1[], float p2[]) {
430  float total_distance = 0;
431 
432  for (; k > 0; k--, p1++, p2++, dim++) {
433  if (dim->NonEssential)
434  continue;
435 
436  float dimension_distance = *p1 - *p2;
437 
438  /* if this dimension is circular - check wraparound distance */
439  if (dim->Circular) {
440  dimension_distance = Magnitude(dimension_distance);
441  float wrap_distance = dim->Max - dim->Min - dimension_distance;
442  dimension_distance = std::min(dimension_distance, wrap_distance);
443  }
444 
445  total_distance += dimension_distance * dimension_distance;
446  }
447  return total_distance;
448 }
449 
450 float ComputeDistance(int k, PARAM_DESC *dim, float p1[], float p2[]) {
451  return sqrt(DistanceSquared(k, dim, p1, p2));
452 }
453 
454 /*---------------------------------------------------------------------------*/
459 bool KDTreeSearch::BoxIntersectsSearch(float *lower, float *upper) {
460  float *query = query_point_;
461  // Compute the sum in higher precision.
462  double total_distance = 0.0;
463  double radius_squared = static_cast<double>(results_.max_insertable_key()) *
464  results_.max_insertable_key();
465  PARAM_DESC *dim = tree_->KeyDesc;
466 
467  for (int i = tree_->KeySize; i > 0; i--, dim++, query++, lower++, upper++) {
468  if (dim->NonEssential)
469  continue;
470 
471  float dimension_distance;
472  if (*query < *lower)
473  dimension_distance = *lower - *query;
474  else if (*query > *upper)
475  dimension_distance = *query - *upper;
476  else
477  dimension_distance = 0;
478 
479  /* if this dimension is circular - check wraparound distance */
480  if (dim->Circular) {
481  float wrap_distance = FLT_MAX;
482  if (*query < *lower)
483  wrap_distance = *query + dim->Max - dim->Min - *upper;
484  else if (*query > *upper)
485  wrap_distance = *lower - (*query - (dim->Max - dim->Min));
486  dimension_distance = std::min(dimension_distance, wrap_distance);
487  }
488 
489  total_distance +=
490  static_cast<double>(dimension_distance) * dimension_distance;
491  if (total_distance >= radius_squared)
492  return false;
493  }
494  return true;
495 }
496 
497 
498 /*---------------------------------------------------------------------------*/
514 void Walk(KDTREE *tree, void_proc action, void *context,
515  KDNODE *sub_tree, int32_t level) {
516  (*action)(context, sub_tree->Data, level);
517  if (sub_tree->Left != nullptr)
518  Walk(tree, action, context, sub_tree->Left, NextLevel(tree, level));
519  if (sub_tree->Right != nullptr)
520  Walk(tree, action, context, sub_tree->Right, NextLevel(tree, level));
521 }
522 
524 void InsertNodes(KDTREE *tree, KDNODE *nodes) {
525  if (nodes == nullptr)
526  return;
527 
528  KDStore(tree, nodes->Key, nodes->Data);
529  InsertNodes(tree, nodes->Left);
530  InsertNodes(tree, nodes->Right);
531 }
532 
534 void FreeSubTree(KDNODE *sub_tree) {
535  if (sub_tree != nullptr) {
536  FreeSubTree(sub_tree->Left);
537  FreeSubTree(sub_tree->Right);
538  free(sub_tree);
539  }
540 }
KDTreeSearch(KDTREE *tree, float *query_point, int k_closest)
Definition: kdtree.cpp:140
float MidRange
Definition: ocrfeatures.h:50
int8_t Circular
Definition: ocrfeatures.h:44
KDTREE * MakeKDTree(int16_t KeySize, const PARAM_DESC KeyDesc[])
Definition: kdtree.cpp:181
float DistanceSquared(int k, PARAM_DESC *dim, float p1[], float p2[])
Definition: kdtree.cpp:429
float HalfRange
Definition: ocrfeatures.h:49
const Key & max_insertable_key()
Definition: kdtree.cpp:91
int elements_count()
Definition: kdtree.cpp:68
float * Key
Definition: kdtree.h:38
struct KDNODE * Left
Definition: kdtree.h:43
PARAM_DESC KeyDesc[1]
Definition: kdtree.h:50
float Min
Definition: ocrfeatures.h:46
~MinK()
Definition: kdtree.cpp:86
KDNODE * MakeKDNode(KDTREE *tree, float Key[], void *Data, int Index)
Definition: kdtree.cpp:354
void FreeKDTree(KDTREE *Tree)
Definition: kdtree.cpp:333
#define Magnitude(X)
Definition: kdtree.cpp:30
int count(LIST var_list)
Definition: oldlist.cpp:98
void Walk(KDTREE *tree, void_proc action, void *context, KDNODE *sub_tree, int32_t level)
Definition: kdtree.cpp:514
void InsertNodes(KDTREE *tree, KDNODE *nodes)
Definition: kdtree.cpp:524
void * Emalloc(int Size)
Definition: emalloc.cpp:31
void KDStore(KDTREE *Tree, float *Key, void *Data)
Definition: kdtree.cpp:213
void FreeKDNode(KDNODE *Node)
Definition: kdtree.cpp:372
Definition: kdtree.h:47
void FreeSubTree(KDNODE *sub_tree)
Definition: kdtree.cpp:534
#define MINSEARCH
Definition: kdtree.cpp:36
float LeftBranch
Definition: kdtree.h:41
void KDDelete(KDTREE *Tree, float Key[], void *Data)
Definition: kdtree.cpp:254
float Range
Definition: ocrfeatures.h:48
#define MAXSEARCH
Definition: kdtree.cpp:37
Value value
Definition: kdtree.cpp:62
int16_t KeySize
Definition: kdtree.h:48
LIST search(LIST list, void *key, int_compare is_equal)
Definition: oldlist.cpp:366
void KDNearestNeighborSearch(KDTREE *Tree, float Query[], int QuerySize, float MaxDistance, int *NumberOfResults, void **NBuffer, float DBuffer[])
Definition: kdtree.cpp:306
float RightBranch
Definition: kdtree.h:42
Definition: kdtree.h:37
int8_t NonEssential
Definition: ocrfeatures.h:45
void Search(int *result_count, float *distances, void **results)
Definition: kdtree.cpp:153
Definition: kdtree.cpp:52
float BranchPoint
Definition: kdtree.h:40
void * Data
Definition: kdtree.h:39
KDNODE Root
Definition: kdtree.h:49
void(* void_proc)(...)
Definition: cutil.h:30
#define NodeFound(N, K, D)
Definition: kdtree.cpp:31
float Max
Definition: ocrfeatures.h:47
void KDWalk(KDTREE *Tree, void_proc action, void *context)
Definition: kdtree.cpp:316
Element(const Key &k, const Value &v)
Definition: kdtree.cpp:59
MinK(Key max_key, int k)
Definition: kdtree.cpp:80
bool insert(Key k, Value v)
Definition: kdtree.cpp:98
float ComputeDistance(int k, PARAM_DESC *dim, float p1[], float p2[])
Definition: kdtree.cpp:450
struct KDNODE * Right
Definition: kdtree.h:44
const Element * elements()
Definition: kdtree.cpp:69