tesseract 3.04.01

classify/kdtree.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002  **  Filename:  kdtree.cpp
00003  **  Purpose:   Routines for managing K-D search trees
00004  **  Author:    Dan Johnson
00005  **  History:  3/10/89, DSJ, Created.
00006  **      5/23/89, DSJ, Added circular feature capability.
00007  **      7/13/89, DSJ, Made tree nodes invisible to outside.
00008  **
00009  **  (c) Copyright Hewlett-Packard Company, 1988.
00010  ** Licensed under the Apache License, Version 2.0 (the "License");
00011  ** you may not use this file except in compliance with the License.
00012  ** You may obtain a copy of the License at
00013  ** http://www.apache.org/licenses/LICENSE-2.0
00014  ** Unless required by applicable law or agreed to in writing, software
00015  ** distributed under the License is distributed on an "AS IS" BASIS,
00016  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00017  ** See the License for the specific language governing permissions and
00018  ** limitations under the License.
00019  ******************************************************************************/
00020 
00021 /*-----------------------------------------------------------------------------
00022           Include Files and Type Defines
00023 -----------------------------------------------------------------------------*/
00024 #include "kdtree.h"
00025 #include "const.h"
00026 #include "emalloc.h"
00027 #include "freelist.h"
00028 #include <stdio.h>
00029 #include <math.h>
00030 
00031 #define Magnitude(X)    ((X) < 0 ? -(X) : (X))
00032 #define NodeFound(N,K,D)  (( (N)->Key == (K) ) && ( (N)->Data == (D) ))
00033 
00034 /*-----------------------------------------------------------------------------
00035         Global Data Definitions and Declarations
00036 -----------------------------------------------------------------------------*/
00037 #define MINSEARCH -MAX_FLOAT32
00038 #define MAXSEARCH MAX_FLOAT32
00039 
00040 // Helper function to find the next essential dimension in a cycle.
00041 static int NextLevel(KDTREE *tree, int level) {
00042   do {
00043     ++level;
00044     if (level >= tree->KeySize)
00045       level = 0;
00046   } while (tree->KeyDesc[level].NonEssential);
00047   return level;
00048 }
00049 
00050 //-----------------------------------------------------------------------------
00052 template<typename Key, typename Value>
00053 class MinK {
00054  public:
00055   MinK(Key max_key, int k);
00056   ~MinK();
00057 
00058   struct Element {
00059     Element() {}
00060     Element(const Key& k, const Value& v) : key(k), value(v) {}
00061 
00062     Key key;
00063     Value value;
00064   };
00065 
00066   bool insert(Key k, Value v);
00067   const Key& max_insertable_key();
00068 
00069   int elements_count() { return elements_count_; }
00070   const Element* elements() { return elements_; }
00071 
00072  private:
00073   const Key max_key_;  //< the maximum possible Key
00074   Element* elements_;  //< unsorted array of elements
00075   int elements_count_;  //< the number of results collected so far
00076   int k_;  //< the number of results we want from the search
00077   int max_index_;  //< the index of the result with the largest key
00078 };
00079 
00080 template<typename Key, typename Value>
00081 MinK<Key, Value>::MinK(Key max_key, int k) :
00082   max_key_(max_key), elements_count_(0), k_(k < 1 ? 1 : k), max_index_(0) {
00083   elements_ = new Element[k_];
00084 }
00085 
00086 template<typename Key, typename Value>
00087 MinK<Key, Value>::~MinK() {
00088   delete []elements_;
00089 }
00090 
00091 template<typename Key, typename Value>
00092 const Key& MinK<Key, Value>::max_insertable_key() {
00093   if (elements_count_ < k_)
00094     return max_key_;
00095   return elements_[max_index_].key;
00096 }
00097 
00098 template<typename Key, typename Value>
00099 bool MinK<Key, Value>::insert(Key key, Value value) {
00100   if (elements_count_ < k_) {
00101     elements_[elements_count_++] = Element(key, value);
00102     if (key > elements_[max_index_].key)
00103       max_index_ = elements_count_ - 1;
00104     return true;
00105   } else if (key < elements_[max_index_].key) {
00106     // evict the largest element.
00107     elements_[max_index_] = Element(key, value);
00108     // recompute max_index_
00109     for (int i = 0; i < elements_count_; i++) {
00110       if (elements_[i].key > elements_[max_index_].key)
00111         max_index_ = i;
00112     }
00113     return true;
00114   }
00115   return false;
00116 }
00117 
00118 
00119 //-----------------------------------------------------------------------------
00121 class KDTreeSearch {
00122  public:
00123   KDTreeSearch(KDTREE* tree, FLOAT32 *query_point, int k_closest);
00124   ~KDTreeSearch();
00125 
00127   void Search(int *result_count, FLOAT32 *distances, void **results);
00128 
00129  private:
00130   void SearchRec(int Level, KDNODE *SubTree);
00131   bool BoxIntersectsSearch(FLOAT32 *lower, FLOAT32 *upper);
00132 
00133   KDTREE *tree_;
00134   FLOAT32 *query_point_;
00135   MinK<FLOAT32, void *>* results_;
00136   FLOAT32 *sb_min_;  //< search box minimum
00137   FLOAT32 *sb_max_;  //< search box maximum
00138 };
00139 
00140 KDTreeSearch::KDTreeSearch(KDTREE* tree, FLOAT32 *query_point, int k_closest) :
00141     tree_(tree),
00142     query_point_(query_point) {
00143   results_ = new MinK<FLOAT32, void *>(MAXSEARCH, k_closest);
00144   sb_min_ = new FLOAT32[tree->KeySize];
00145   sb_max_ = new FLOAT32[tree->KeySize];
00146 }
00147 
00148 KDTreeSearch::~KDTreeSearch() {
00149   delete results_;
00150   delete[] sb_min_;
00151   delete[] sb_max_;
00152 }
00153 
00156 void KDTreeSearch::Search(int *result_count,
00157                           FLOAT32 *distances,
00158                           void **results) {
00159   if (tree_->Root.Left == NULL) {
00160     *result_count = 0;
00161   } else {
00162     for (int i = 0; i < tree_->KeySize; i++) {
00163       sb_min_[i] = tree_->KeyDesc[i].Min;
00164       sb_max_[i] = tree_->KeyDesc[i].Max;
00165     }
00166     SearchRec(0, tree_->Root.Left);
00167     int count = results_->elements_count();
00168     *result_count = count;
00169     for (int j = 0; j < count; j++) {
00170       distances[j] = (FLOAT32) sqrt((FLOAT64)results_->elements()[j].key);
00171       results[j] = results_->elements()[j].value;
00172     }
00173   }
00174 }
00175 
00176 /*-----------------------------------------------------------------------------
00177               Public Code
00178 -----------------------------------------------------------------------------*/
00182 KDTREE *MakeKDTree(inT16 KeySize, const PARAM_DESC KeyDesc[]) {
00183   KDTREE *KDTree = (KDTREE *) Emalloc(
00184       sizeof(KDTREE) + (KeySize - 1) * sizeof(PARAM_DESC));
00185   for (int i = 0; i < KeySize; i++) {
00186     KDTree->KeyDesc[i].NonEssential = KeyDesc[i].NonEssential;
00187     KDTree->KeyDesc[i].Circular = KeyDesc[i].Circular;
00188     if (KeyDesc[i].Circular) {
00189       KDTree->KeyDesc[i].Min = KeyDesc[i].Min;
00190       KDTree->KeyDesc[i].Max = KeyDesc[i].Max;
00191       KDTree->KeyDesc[i].Range = KeyDesc[i].Max - KeyDesc[i].Min;
00192       KDTree->KeyDesc[i].HalfRange = KDTree->KeyDesc[i].Range / 2;
00193       KDTree->KeyDesc[i].MidRange = (KeyDesc[i].Max + KeyDesc[i].Min) / 2;
00194     } else {
00195       KDTree->KeyDesc[i].Min = MINSEARCH;
00196       KDTree->KeyDesc[i].Max = MAXSEARCH;
00197     }
00198   }
00199   KDTree->KeySize = KeySize;
00200   KDTree->Root.Left = NULL;
00201   KDTree->Root.Right = NULL;
00202   return KDTree;
00203 }
00204 
00205 
00218 void KDStore(KDTREE *Tree, FLOAT32 *Key, void *Data) {
00219   int Level;
00220   KDNODE *Node;
00221   KDNODE **PtrToNode;
00222 
00223   PtrToNode = &(Tree->Root.Left);
00224   Node = *PtrToNode;
00225   Level = NextLevel(Tree, -1);
00226   while (Node != NULL) {
00227     if (Key[Level] < Node->BranchPoint) {
00228       PtrToNode = &(Node->Left);
00229       if (Key[Level] > Node->LeftBranch)
00230         Node->LeftBranch = Key[Level];
00231     }
00232     else {
00233       PtrToNode = &(Node->Right);
00234       if (Key[Level] < Node->RightBranch)
00235         Node->RightBranch = Key[Level];
00236     }
00237     Level = NextLevel(Tree, Level);
00238     Node = *PtrToNode;
00239   }
00240 
00241   *PtrToNode = MakeKDNode(Tree, Key, (void *) Data, Level);
00242 }                                /* KDStore */
00243 
00244 
00264 void
00265 KDDelete (KDTREE * Tree, FLOAT32 Key[], void *Data) {
00266   int Level;
00267   KDNODE *Current;
00268   KDNODE *Father;
00269 
00270   /* initialize search at root of tree */
00271   Father = &(Tree->Root);
00272   Current = Father->Left;
00273   Level = NextLevel(Tree, -1);
00274 
00275   /* search tree for node to be deleted */
00276   while ((Current != NULL) && (!NodeFound (Current, Key, Data))) {
00277     Father = Current;
00278     if (Key[Level] < Current->BranchPoint)
00279       Current = Current->Left;
00280     else
00281       Current = Current->Right;
00282 
00283     Level = NextLevel(Tree, Level);
00284   }
00285 
00286   if (Current != NULL) {         /* if node to be deleted was found */
00287     if (Current == Father->Left) {
00288       Father->Left = NULL;
00289       Father->LeftBranch = Tree->KeyDesc[Level].Min;
00290     } else {
00291       Father->Right = NULL;
00292       Father->RightBranch = Tree->KeyDesc[Level].Max;
00293     }
00294 
00295     InsertNodes(Tree, Current->Left);
00296     InsertNodes(Tree, Current->Right);
00297     FreeSubTree(Current);
00298   }
00299 }                                /* KDDelete */
00300 
00301 
00322 void KDNearestNeighborSearch(
00323     KDTREE *Tree, FLOAT32 Query[], int QuerySize, FLOAT32 MaxDistance,
00324     int *NumberOfResults, void **NBuffer, FLOAT32 DBuffer[]) {
00325   KDTreeSearch search(Tree, Query, QuerySize);
00326   search.Search(NumberOfResults, DBuffer, NBuffer);
00327 }
00328 
00329 
00330 /*---------------------------------------------------------------------------*/
00332 void KDWalk(KDTREE *Tree, void_proc action, void *context) {
00333   if (Tree->Root.Left != NULL)
00334     Walk(Tree, action, context, Tree->Root.Left, NextLevel(Tree, -1));
00335 }
00336 
00337 
00338 /*---------------------------------------------------------------------------*/
00351 void FreeKDTree(KDTREE *Tree) {
00352   FreeSubTree(Tree->Root.Left);
00353   memfree(Tree);
00354 }                                /* FreeKDTree */
00355 
00356 
00357 /*-----------------------------------------------------------------------------
00358               Private Code
00359 -----------------------------------------------------------------------------*/
00360 /*---------------------------------------------------------------------------*/
00374 KDNODE *MakeKDNode(KDTREE *tree, FLOAT32 Key[], void *Data, int Index) {
00375   KDNODE *NewNode;
00376 
00377   NewNode = (KDNODE *) Emalloc (sizeof (KDNODE));
00378 
00379   NewNode->Key = Key;
00380   NewNode->Data = Data;
00381   NewNode->BranchPoint = Key[Index];
00382   NewNode->LeftBranch = tree->KeyDesc[Index].Min;
00383   NewNode->RightBranch = tree->KeyDesc[Index].Max;
00384   NewNode->Left = NULL;
00385   NewNode->Right = NULL;
00386 
00387   return NewNode;
00388 }                                /* MakeKDNode */
00389 
00390 
00391 /*---------------------------------------------------------------------------*/
00392 void FreeKDNode(KDNODE *Node) {
00393   memfree ((char *)Node);
00394 }
00395 
00396 
00397 /*---------------------------------------------------------------------------*/
00403 void KDTreeSearch::SearchRec(int level, KDNODE *sub_tree) {
00404   if (level >= tree_->KeySize)
00405     level = 0;
00406 
00407   if (!BoxIntersectsSearch(sb_min_, sb_max_))
00408     return;
00409 
00410   results_->insert(DistanceSquared(tree_->KeySize, tree_->KeyDesc,
00411                                   query_point_, sub_tree->Key),
00412                    sub_tree->Data);
00413 
00414   if (query_point_[level] < sub_tree->BranchPoint) {
00415     if (sub_tree->Left != NULL) {
00416       FLOAT32 tmp = sb_max_[level];
00417       sb_max_[level] = sub_tree->LeftBranch;
00418       SearchRec(NextLevel(tree_, level), sub_tree->Left);
00419       sb_max_[level] = tmp;
00420     }
00421     if (sub_tree->Right != NULL) {
00422       FLOAT32 tmp = sb_min_[level];
00423       sb_min_[level] = sub_tree->RightBranch;
00424       SearchRec(NextLevel(tree_, level), sub_tree->Right);
00425       sb_min_[level] = tmp;
00426     }
00427   } else {
00428     if (sub_tree->Right != NULL) {
00429       FLOAT32 tmp = sb_min_[level];
00430       sb_min_[level] = sub_tree->RightBranch;
00431       SearchRec(NextLevel(tree_, level), sub_tree->Right);
00432       sb_min_[level] = tmp;
00433     }
00434     if (sub_tree->Left != NULL) {
00435       FLOAT32 tmp = sb_max_[level];
00436       sb_max_[level] = sub_tree->LeftBranch;
00437       SearchRec(NextLevel(tree_, level), sub_tree->Left);
00438       sb_max_[level] = tmp;
00439     }
00440   }
00441 }
00442 
00443 
00444 /*---------------------------------------------------------------------------*/
00452 FLOAT32 DistanceSquared(int k, PARAM_DESC *dim, FLOAT32 p1[], FLOAT32 p2[]) {
00453   FLOAT32 total_distance = 0;
00454 
00455   for (; k > 0; k--, p1++, p2++, dim++) {
00456     if (dim->NonEssential)
00457       continue;
00458 
00459     FLOAT32 dimension_distance = *p1 - *p2;
00460 
00461     /* if this dimension is circular - check wraparound distance */
00462     if (dim->Circular) {
00463       dimension_distance = Magnitude(dimension_distance);
00464       FLOAT32 wrap_distance = dim->Max - dim->Min - dimension_distance;
00465       dimension_distance = MIN(dimension_distance, wrap_distance);
00466     }
00467 
00468     total_distance += dimension_distance * dimension_distance;
00469   }
00470   return total_distance;
00471 }
00472 
00473 FLOAT32 ComputeDistance(int k, PARAM_DESC *dim, FLOAT32 p1[], FLOAT32 p2[]) {
00474   return sqrt(DistanceSquared(k, dim, p1, p2));
00475 }
00476 
00477 /*---------------------------------------------------------------------------*/
00482 bool KDTreeSearch::BoxIntersectsSearch(FLOAT32 *lower, FLOAT32 *upper) {
00483   FLOAT32 *query = query_point_;
00484   FLOAT64 total_distance = 0.0;
00485   FLOAT64 radius_squared =
00486       results_->max_insertable_key() * results_->max_insertable_key();
00487   PARAM_DESC *dim = tree_->KeyDesc;
00488 
00489   for (int i = tree_->KeySize; i > 0; i--, dim++, query++, lower++, upper++) {
00490     if (dim->NonEssential)
00491       continue;
00492 
00493     FLOAT32 dimension_distance;
00494     if (*query < *lower)
00495       dimension_distance = *lower - *query;
00496     else if (*query > *upper)
00497       dimension_distance = *query - *upper;
00498     else
00499       dimension_distance = 0;
00500 
00501     /* if this dimension is circular - check wraparound distance */
00502     if (dim->Circular) {
00503       FLOAT32 wrap_distance = MAX_FLOAT32;
00504       if (*query < *lower)
00505         wrap_distance = *query + dim->Max - dim->Min - *upper;
00506       else if (*query > *upper)
00507         wrap_distance = *lower - (*query - (dim->Max - dim->Min));
00508       dimension_distance = MIN(dimension_distance, wrap_distance);
00509     }
00510 
00511     total_distance += dimension_distance * dimension_distance;
00512     if (total_distance >= radius_squared)
00513       return FALSE;
00514   }
00515   return TRUE;
00516 }
00517 
00518 
00519 /*---------------------------------------------------------------------------*/
00535 void Walk(KDTREE *tree, void_proc action, void *context,
00536           KDNODE *sub_tree, inT32 level) {
00537   (*action)(context, sub_tree->Data, level);
00538   if (sub_tree->Left != NULL)
00539     Walk(tree, action, context, sub_tree->Left, NextLevel(tree, level));
00540   if (sub_tree->Right != NULL)
00541     Walk(tree, action, context, sub_tree->Right, NextLevel(tree, level));
00542 }
00543 
00544 
00546 void InsertNodes(KDTREE *tree, KDNODE *nodes) {
00547   if (nodes == NULL)
00548     return;
00549 
00550   KDStore(tree, nodes->Key, nodes->Data);
00551   InsertNodes(tree, nodes->Left);
00552   InsertNodes(tree, nodes->Right);
00553 }
00554 
00556 void FreeSubTree(KDNODE *sub_tree) {
00557   if (sub_tree != NULL) {
00558     FreeSubTree(sub_tree->Left);
00559     FreeSubTree(sub_tree->Right);
00560     memfree(sub_tree);
00561   }
00562 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines