tesseract  3.05.02
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  ** History: 3/10/89, DSJ, Created.
6  ** 5/23/89, DSJ, Added circular feature capability.
7  ** 7/13/89, DSJ, Made tree nodes invisible to outside.
8  **
9  ** (c) Copyright Hewlett-Packard Company, 1988.
10  ** Licensed under the Apache License, Version 2.0 (the "License");
11  ** you may not use this file except in compliance with the License.
12  ** You may obtain a copy of the License at
13  ** http://www.apache.org/licenses/LICENSE-2.0
14  ** Unless required by applicable law or agreed to in writing, software
15  ** distributed under the License is distributed on an "AS IS" BASIS,
16  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  ** See the License for the specific language governing permissions and
18  ** limitations under the License.
19  ******************************************************************************/
20 
21 /*-----------------------------------------------------------------------------
22  Include Files and Type Defines
23 -----------------------------------------------------------------------------*/
24 #include "kdtree.h"
25 #include "const.h"
26 #include "emalloc.h"
27 #include "freelist.h"
28 #include <stdio.h>
29 #include <math.h>
30 
31 #define Magnitude(X) ((X) < 0 ? -(X) : (X))
32 #define NodeFound(N,K,D) (( (N)->Key == (K) ) && ( (N)->Data == (D) ))
33 
34 /*-----------------------------------------------------------------------------
35  Global Data Definitions and Declarations
36 -----------------------------------------------------------------------------*/
37 #define MINSEARCH -MAX_FLOAT32
38 #define MAXSEARCH MAX_FLOAT32
39 
40 // Helper function to find the next essential dimension in a cycle.
41 static int NextLevel(KDTREE *tree, int level) {
42  do {
43  ++level;
44  if (level >= tree->KeySize)
45  level = 0;
46  } while (tree->KeyDesc[level].NonEssential);
47  return level;
48 }
49 
50 //-----------------------------------------------------------------------------
52 template<typename Key, typename Value>
53 class MinK {
54  public:
55  MinK(Key max_key, int k);
56  ~MinK();
57 
58  struct Element {
59  Element() {}
60  Element(const Key& k, const Value& v) : key(k), value(v) {}
61 
62  Key key;
63  Value value;
64  };
65 
66  bool insert(Key k, Value v);
67  const Key& max_insertable_key();
68 
69  int elements_count() { return elements_count_; }
70  const Element* elements() { return elements_; }
71 
72  private:
73  const Key max_key_; //< the maximum possible Key
74  Element *elements_; //< unsorted array of elements
75  int elements_count_; //< the number of results collected so far
76  int k_; //< the number of results we want from the search
77  int max_index_; //< the index of the result with the largest key
78 };
79 
80 template<typename Key, typename Value>
81 MinK<Key, Value>::MinK(Key max_key, int k) :
82  max_key_(max_key), elements_count_(0), k_(k < 1 ? 1 : k), max_index_(0) {
83  elements_ = new Element[k_];
84 }
85 
86 template<typename Key, typename Value>
88  delete []elements_;
89 }
90 
91 template<typename Key, typename Value>
93  if (elements_count_ < k_)
94  return max_key_;
95  return elements_[max_index_].key;
96 }
97 
98 template<typename Key, typename Value>
99 bool MinK<Key, Value>::insert(Key key, Value 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;
104  return true;
105  } else if (key < elements_[max_index_].key) {
106  // evict the largest element.
107  elements_[max_index_] = Element(key, value);
108  // recompute max_index_
109  for (int i = 0; i < elements_count_; i++) {
110  if (elements_[i].key > elements_[max_index_].key)
111  max_index_ = i;
112  }
113  return true;
114  }
115  return false;
116 }
117 
118 
119 //-----------------------------------------------------------------------------
123  public:
124  KDTreeSearch(KDTREE* tree, FLOAT32 *query_point, int k_closest);
125  ~KDTreeSearch();
126 
128  void Search(int *result_count, FLOAT32 *distances, void **results);
129 
130  private:
131  void SearchRec(int Level, KDNODE *SubTree);
132  bool BoxIntersectsSearch(FLOAT32 *lower, FLOAT32 *upper);
133 
134  KDTREE *tree_;
135  FLOAT32 *query_point_;
136  FLOAT32 *sb_min_; //< search box minimum
137  FLOAT32 *sb_max_; //< search box maximum
138  MinK<FLOAT32, void *> results_;
139 };
140 
141 KDTreeSearch::KDTreeSearch(KDTREE* tree, FLOAT32 *query_point, int k_closest) :
142  tree_(tree),
143  query_point_(query_point),
144  results_(MAXSEARCH, k_closest) {
145  sb_min_ = new FLOAT32[tree->KeySize];
146  sb_max_ = new FLOAT32[tree->KeySize];
147 }
148 
150  delete[] sb_min_;
151  delete[] sb_max_;
152 }
153 
156 void KDTreeSearch::Search(int *result_count,
157  FLOAT32 *distances,
158  void **results) {
159  if (tree_->Root.Left == NULL) {
160  *result_count = 0;
161  } else {
162  for (int i = 0; i < tree_->KeySize; i++) {
163  sb_min_[i] = tree_->KeyDesc[i].Min;
164  sb_max_[i] = tree_->KeyDesc[i].Max;
165  }
166  SearchRec(0, tree_->Root.Left);
167  int count = results_.elements_count();
168  *result_count = count;
169  for (int j = 0; j < count; j++) {
170  // TODO: why FLOAT64 here?
171  distances[j] = (FLOAT32) sqrt((FLOAT64)results_.elements()[j].key);
172  results[j] = results_.elements()[j].value;
173  }
174  }
175 }
176 
177 /*-----------------------------------------------------------------------------
178  Public Code
179 -----------------------------------------------------------------------------*/
183 KDTREE *MakeKDTree(inT16 KeySize, const PARAM_DESC KeyDesc[]) {
184  KDTREE *KDTree = (KDTREE *) Emalloc(
185  sizeof(KDTREE) + (KeySize - 1) * sizeof(PARAM_DESC));
186  for (int i = 0; i < KeySize; i++) {
187  KDTree->KeyDesc[i].NonEssential = KeyDesc[i].NonEssential;
188  KDTree->KeyDesc[i].Circular = KeyDesc[i].Circular;
189  if (KeyDesc[i].Circular) {
190  KDTree->KeyDesc[i].Min = KeyDesc[i].Min;
191  KDTree->KeyDesc[i].Max = KeyDesc[i].Max;
192  KDTree->KeyDesc[i].Range = KeyDesc[i].Max - KeyDesc[i].Min;
193  KDTree->KeyDesc[i].HalfRange = KDTree->KeyDesc[i].Range / 2;
194  KDTree->KeyDesc[i].MidRange = (KeyDesc[i].Max + KeyDesc[i].Min) / 2;
195  } else {
196  KDTree->KeyDesc[i].Min = MINSEARCH;
197  KDTree->KeyDesc[i].Max = MAXSEARCH;
198  }
199  }
200  KDTree->KeySize = KeySize;
201  KDTree->Root.Left = NULL;
202  KDTree->Root.Right = NULL;
203  return KDTree;
204 }
205 
206 
219 void KDStore(KDTREE *Tree, FLOAT32 *Key, void *Data) {
220  int Level;
221  KDNODE *Node;
222  KDNODE **PtrToNode;
223 
224  PtrToNode = &(Tree->Root.Left);
225  Node = *PtrToNode;
226  Level = NextLevel(Tree, -1);
227  while (Node != NULL) {
228  if (Key[Level] < Node->BranchPoint) {
229  PtrToNode = &(Node->Left);
230  if (Key[Level] > Node->LeftBranch)
231  Node->LeftBranch = Key[Level];
232  }
233  else {
234  PtrToNode = &(Node->Right);
235  if (Key[Level] < Node->RightBranch)
236  Node->RightBranch = Key[Level];
237  }
238  Level = NextLevel(Tree, Level);
239  Node = *PtrToNode;
240  }
241 
242  *PtrToNode = MakeKDNode(Tree, Key, (void *) Data, Level);
243 } /* KDStore */
244 
264 void
265 KDDelete (KDTREE * Tree, FLOAT32 Key[], void *Data) {
266  int Level;
267  KDNODE *Current;
268  KDNODE *Father;
269 
270  /* initialize search at root of tree */
271  Father = &(Tree->Root);
272  Current = Father->Left;
273  Level = NextLevel(Tree, -1);
274 
275  /* search tree for node to be deleted */
276  while ((Current != NULL) && (!NodeFound (Current, Key, Data))) {
277  Father = Current;
278  if (Key[Level] < Current->BranchPoint)
279  Current = Current->Left;
280  else
281  Current = Current->Right;
282 
283  Level = NextLevel(Tree, Level);
284  }
285 
286  if (Current != NULL) { /* if node to be deleted was found */
287  if (Current == Father->Left) {
288  Father->Left = NULL;
289  Father->LeftBranch = Tree->KeyDesc[Level].Min;
290  } else {
291  Father->Right = NULL;
292  Father->RightBranch = Tree->KeyDesc[Level].Max;
293  }
294 
295  InsertNodes(Tree, Current->Left);
296  InsertNodes(Tree, Current->Right);
297  FreeSubTree(Current);
298  }
299 } /* KDDelete */
300 
322  KDTREE *Tree, FLOAT32 Query[], int QuerySize, FLOAT32 MaxDistance,
323  int *NumberOfResults, void **NBuffer, FLOAT32 DBuffer[]) {
324  KDTreeSearch search(Tree, Query, QuerySize);
325  search.Search(NumberOfResults, DBuffer, NBuffer);
326 }
327 
328 
329 /*---------------------------------------------------------------------------*/
331 void KDWalk(KDTREE *Tree, void_proc action, void *context) {
332  if (Tree->Root.Left != NULL)
333  Walk(Tree, action, context, Tree->Root.Left, NextLevel(Tree, -1));
334 }
335 
336 
337 /*---------------------------------------------------------------------------*/
350 void FreeKDTree(KDTREE *Tree) {
351  FreeSubTree(Tree->Root.Left);
352  memfree(Tree);
353 } /* FreeKDTree */
354 
355 
356 /*-----------------------------------------------------------------------------
357  Private Code
358 -----------------------------------------------------------------------------*/
359 /*---------------------------------------------------------------------------*/
373 KDNODE *MakeKDNode(KDTREE *tree, FLOAT32 Key[], void *Data, int Index) {
374  KDNODE *NewNode;
375 
376  NewNode = (KDNODE *) Emalloc (sizeof (KDNODE));
377 
378  NewNode->Key = Key;
379  NewNode->Data = Data;
380  NewNode->BranchPoint = Key[Index];
381  NewNode->LeftBranch = tree->KeyDesc[Index].Min;
382  NewNode->RightBranch = tree->KeyDesc[Index].Max;
383  NewNode->Left = NULL;
384  NewNode->Right = NULL;
385 
386  return NewNode;
387 } /* MakeKDNode */
388 
389 
390 /*---------------------------------------------------------------------------*/
391 void FreeKDNode(KDNODE *Node) {
392  memfree ((char *)Node);
393 }
394 
395 
396 /*---------------------------------------------------------------------------*/
402 void KDTreeSearch::SearchRec(int level, KDNODE *sub_tree) {
403  if (level >= tree_->KeySize)
404  level = 0;
405 
406  if (!BoxIntersectsSearch(sb_min_, sb_max_))
407  return;
408 
409  results_.insert(DistanceSquared(tree_->KeySize, tree_->KeyDesc,
410  query_point_, sub_tree->Key),
411  sub_tree->Data);
412 
413  if (query_point_[level] < sub_tree->BranchPoint) {
414  if (sub_tree->Left != NULL) {
415  FLOAT32 tmp = sb_max_[level];
416  sb_max_[level] = sub_tree->LeftBranch;
417  SearchRec(NextLevel(tree_, level), sub_tree->Left);
418  sb_max_[level] = tmp;
419  }
420  if (sub_tree->Right != NULL) {
421  FLOAT32 tmp = sb_min_[level];
422  sb_min_[level] = sub_tree->RightBranch;
423  SearchRec(NextLevel(tree_, level), sub_tree->Right);
424  sb_min_[level] = tmp;
425  }
426  } else {
427  if (sub_tree->Right != NULL) {
428  FLOAT32 tmp = sb_min_[level];
429  sb_min_[level] = sub_tree->RightBranch;
430  SearchRec(NextLevel(tree_, level), sub_tree->Right);
431  sb_min_[level] = tmp;
432  }
433  if (sub_tree->Left != NULL) {
434  FLOAT32 tmp = sb_max_[level];
435  sb_max_[level] = sub_tree->LeftBranch;
436  SearchRec(NextLevel(tree_, level), sub_tree->Left);
437  sb_max_[level] = tmp;
438  }
439  }
440 }
441 
442 
443 /*---------------------------------------------------------------------------*/
452  FLOAT32 total_distance = 0;
453 
454  for (; k > 0; k--, p1++, p2++, dim++) {
455  if (dim->NonEssential)
456  continue;
457 
458  FLOAT32 dimension_distance = *p1 - *p2;
459 
460  /* if this dimension is circular - check wraparound distance */
461  if (dim->Circular) {
462  dimension_distance = Magnitude(dimension_distance);
463  FLOAT32 wrap_distance = dim->Max - dim->Min - dimension_distance;
464  dimension_distance = MIN(dimension_distance, wrap_distance);
465  }
466 
467  total_distance += dimension_distance * dimension_distance;
468  }
469  return total_distance;
470 }
471 
473  return sqrt(DistanceSquared(k, dim, p1, p2));
474 }
475 
476 /*---------------------------------------------------------------------------*/
481 bool KDTreeSearch::BoxIntersectsSearch(FLOAT32 *lower, FLOAT32 *upper) {
482  FLOAT32 *query = query_point_;
483  // Why FLOAT64?
484  FLOAT64 total_distance = 0.0;
485  FLOAT64 radius_squared =
486  results_.max_insertable_key() * results_.max_insertable_key();
487  PARAM_DESC *dim = tree_->KeyDesc;
488 
489  for (int i = tree_->KeySize; i > 0; i--, dim++, query++, lower++, upper++) {
490  if (dim->NonEssential)
491  continue;
492 
493  FLOAT32 dimension_distance;
494  if (*query < *lower)
495  dimension_distance = *lower - *query;
496  else if (*query > *upper)
497  dimension_distance = *query - *upper;
498  else
499  dimension_distance = 0;
500 
501  /* if this dimension is circular - check wraparound distance */
502  if (dim->Circular) {
503  FLOAT32 wrap_distance = MAX_FLOAT32;
504  if (*query < *lower)
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);
509  }
510 
511  total_distance += dimension_distance * dimension_distance;
512  if (total_distance >= radius_squared)
513  return FALSE;
514  }
515  return TRUE;
516 }
517 
518 
519 /*---------------------------------------------------------------------------*/
535 void Walk(KDTREE *tree, void_proc action, void *context,
536  KDNODE *sub_tree, inT32 level) {
537  (*action)(context, sub_tree->Data, level);
538  if (sub_tree->Left != NULL)
539  Walk(tree, action, context, sub_tree->Left, NextLevel(tree, level));
540  if (sub_tree->Right != NULL)
541  Walk(tree, action, context, sub_tree->Right, NextLevel(tree, level));
542 }
543 
545 void InsertNodes(KDTREE *tree, KDNODE *nodes) {
546  if (nodes == NULL)
547  return;
548 
549  KDStore(tree, nodes->Key, nodes->Data);
550  InsertNodes(tree, nodes->Left);
551  InsertNodes(tree, nodes->Right);
552 }
553 
555 void FreeSubTree(KDNODE *sub_tree) {
556  if (sub_tree != NULL) {
557  FreeSubTree(sub_tree->Left);
558  FreeSubTree(sub_tree->Right);
559  memfree(sub_tree);
560  }
561 }
FLOAT32 ComputeDistance(int k, PARAM_DESC *dim, FLOAT32 p1[], FLOAT32 p2[])
Definition: kdtree.cpp:472
void Walk(KDTREE *tree, void_proc action, void *context, KDNODE *sub_tree, inT32 level)
Definition: kdtree.cpp:535
int count(LIST var_list)
Definition: oldlist.cpp:103
struct KDNODE * Right
Definition: kdtree.h:46
#define TRUE
Definition: capi.h:45
short inT16
Definition: host.h:33
inT16 KeySize
Definition: kdtree.h:50
#define MINSEARCH
Definition: kdtree.cpp:37
FLOAT32 RightBranch
Definition: kdtree.h:44
#define NodeFound(N, K, D)
Definition: kdtree.cpp:32
void KDDelete(KDTREE *Tree, FLOAT32 Key[], void *Data)
Definition: kdtree.cpp:265
FLOAT32 Range
Definition: ocrfeatures.h:51
void KDStore(KDTREE *Tree, FLOAT32 *Key, void *Data)
Definition: kdtree.cpp:219
#define Magnitude(X)
Definition: kdtree.cpp:31
FLOAT32 LeftBranch
Definition: kdtree.h:43
#define MIN(x, y)
Definition: ndminx.h:28
int elements_count()
Definition: kdtree.cpp:69
Value value
Definition: kdtree.cpp:63
FLOAT32 BranchPoint
Definition: kdtree.h:42
KDTREE * MakeKDTree(inT16 KeySize, const PARAM_DESC KeyDesc[])
Definition: kdtree.cpp:183
void memfree(void *element)
Definition: freelist.cpp:30
Element(const Key &k, const Value &v)
Definition: kdtree.cpp:60
void InsertNodes(KDTREE *tree, KDNODE *nodes)
Definition: kdtree.cpp:545
void FreeKDNode(KDNODE *Node)
Definition: kdtree.cpp:391
LIST search(LIST list, void *key, int_compare is_equal)
Definition: oldlist.cpp:406
#define MAX_FLOAT32
Definition: host.h:57
Definition: kdtree.h:49
void KDNearestNeighborSearch(KDTREE *Tree, FLOAT32 Query[], int QuerySize, FLOAT32 MaxDistance, int *NumberOfResults, void **NBuffer, FLOAT32 DBuffer[])
Definition: kdtree.cpp:321
void FreeSubTree(KDNODE *sub_tree)
Definition: kdtree.cpp:555
const Key & max_insertable_key()
Definition: kdtree.cpp:92
#define FALSE
Definition: capi.h:46
FLOAT32 HalfRange
Definition: ocrfeatures.h:52
float FLOAT32
Definition: host.h:44
double FLOAT64
Definition: host.h:45
void(* void_proc)(...)
Definition: cutil.h:66
FLOAT32 * Key
Definition: kdtree.h:40
int inT32
Definition: host.h:35
void FreeKDTree(KDTREE *Tree)
Definition: kdtree.cpp:350
#define MAXSEARCH
Definition: kdtree.cpp:38
PARAM_DESC KeyDesc[1]
Definition: kdtree.h:52
FLOAT32 MidRange
Definition: ocrfeatures.h:53
inT8 Circular
Definition: ocrfeatures.h:47
inT8 NonEssential
Definition: ocrfeatures.h:48
bool insert(Key k, Value v)
Definition: kdtree.cpp:99
Definition: kdtree.h:39
Definition: kdtree.cpp:53
FLOAT32 Min
Definition: ocrfeatures.h:49
MinK(Key max_key, int k)
Definition: kdtree.cpp:81
void * Emalloc(int Size)
Definition: emalloc.cpp:47
void Search(int *result_count, FLOAT32 *distances, void **results)
Definition: kdtree.cpp:156
KDTreeSearch(KDTREE *tree, FLOAT32 *query_point, int k_closest)
Definition: kdtree.cpp:141
struct KDNODE * Left
Definition: kdtree.h:45
FLOAT32 Max
Definition: ocrfeatures.h:50
void * Data
Definition: kdtree.h:41
KDNODE Root
Definition: kdtree.h:51
KDNODE * MakeKDNode(KDTREE *tree, FLOAT32 Key[], void *Data, int Index)
Definition: kdtree.cpp:373
~MinK()
Definition: kdtree.cpp:87
const Element * elements()
Definition: kdtree.cpp:70
FLOAT32 DistanceSquared(int k, PARAM_DESC *dim, FLOAT32 p1[], FLOAT32 p2[])
Definition: kdtree.cpp:451
void KDWalk(KDTREE *Tree, void_proc action, void *context)
Definition: kdtree.cpp:331