Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

guma_rkdtree.h

Go to the documentation of this file.
00001 /* LIBGUL - Geometry Utility Library
00002  * Copyright (C) 1998-1999 Norbert Irmer
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Library General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Library General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Library General Public
00015  * License along with this library; if not, write to the
00016  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017  * Boston, MA 02111-1307, USA.
00018  */
00019  
00020 #ifndef GUMA_RKDTREE_H
00021 #define GUMA_RKDTREE_H
00022 
00023 namespace guma {
00024 
00025 // this struct is used to preserve the identity of points (since different
00026 // points may have the same coordinates
00027 template< class U, class V >
00028 class kdrec : public gul::pool_object
00029 {
00030 public:
00031   const U *m_base;
00032   kdrec( const U *base ) { m_base = base; }
00033   const V& operator[]( size_t i) const { return (*m_base)[i]; } 
00034 };
00035 
00036 // object for the nodes of a kd-tree
00037 template< class U, class V >
00038 class kdtnode : public gul::pool_object
00039 {
00040 public:
00041   int                               m_disc;   // discriminant
00042   gul::List< gul::ListNode< kdrec<U,V> > > m_recs;
00043   int                               m_nelems;
00044 
00045   kdtnode     *m_left;   // left subtree
00046   kdtnode     *m_right;  // right subtree
00047   kdtnode     *m_parent; // to travel from a node to the root of the tree
00048 
00049   kdtnode( const kdrec<U,V>& rec, int disc )
00050   {
00051     m_disc = disc;
00052     m_recs.Append( new gul::ListNode< kdrec<U,V> >(rec) );
00053     m_left = m_right = m_parent = 0;
00054     m_nelems = 1;
00055   }
00056   kdtnode( gul::List< gul::ListNode< kdrec<U,V> > >& recs, int disc )
00057   {
00058     m_disc = disc;
00059     m_recs = recs;
00060     m_left = m_right = m_parent = 0;
00061     m_nelems = 1;
00062   }
00063   const V& key() const
00064   {
00065     return m_recs.First()->el[m_disc];
00066   }
00067   void add_rec( const kdrec<U,V>& rec )
00068   {
00069     m_recs.Append( new gul::ListNode< kdrec<U,V> >(rec) );
00070   }
00071   void update()
00072   {
00073     m_nelems = 1;
00074     if( m_left ) m_nelems += m_left->m_nelems;
00075     if( m_right ) m_nelems += m_right->m_nelems;
00076     if( m_parent ) m_parent->update();
00077   }
00078   void set_left( kdtnode *left )
00079   {
00080     m_left = left;
00081     if( m_left ) m_left->m_parent = this;
00082     update();
00083   }
00084   void set_right( kdtnode *right )
00085   {
00086     m_right = right;
00087     if( m_right ) m_right->m_parent = this;
00088     update();
00089   }
00090   void set_childs( kdtnode *left, kdtnode *right )
00091   {
00092     m_left = left;
00093     if( m_left ) m_left->m_parent = this;
00094     m_right = right;
00095     if( m_right ) m_right->m_parent = this;
00096     update();
00097   }
00098   void unlink( kdtnode **left, kdtnode **right, 
00099                gul::List< gul::ListNode< kdrec<U,V> > >& L)
00100   {
00101     L += m_recs;
00102 
00103     *left = m_left;   
00104     if( m_left ) 
00105     {
00106       m_left->m_parent = 0;
00107       m_left = 0;
00108     }
00109     *right = m_right;   
00110     if( m_right ) 
00111     {
00112       m_right->m_parent = 0;
00113       m_right = 0;
00114     }
00115     if( m_parent )
00116     {
00117       if( m_parent->m_left == this )
00118         m_parent->m_left = 0;
00119       if( m_parent->m_right == this )
00120         m_parent->m_right = 0;
00121       m_parent->update();
00122       m_parent = 0;
00123     }
00124   }
00125   ~kdtnode()
00126   {
00127     if( m_left ) 
00128     {
00129       m_left->m_parent = 0;
00130       delete m_left;
00131     }
00132     if( m_right ) 
00133     {
00134       m_right->m_parent = 0;
00135       delete m_right;
00136     }
00137     if( m_parent )
00138     {
00139       if( m_parent->m_left == this )
00140         m_parent->m_left = 0;
00141       if( m_parent->m_right == this )
00142         m_parent->m_right = 0;
00143       m_parent->update();
00144     }
00145   }
00146   // debugging functions
00147   void height( int cur_height, int *max_height, 
00148                int *avg_count, double *avg_sum );
00149   void dump(int dim,int space);
00150 };
00151 
00152 // struct for returning results of nearest neighbor search
00153 template< class U, class V >
00154 class kdnnrec : public gul::pool_object
00155 {
00156 public:
00157   V                                         m_dist;
00158   gul::List< gul::ListNode< kdrec<U,V> > >  m_recs; // a list, since duplicate 
00159                 // records or records with the same distance are possible
00160   kdnnrec() { }
00161     
00162   kdnnrec( const V& dist, const kdrec<U,V>& rec )
00163   {
00164     m_dist = dist;
00165     m_recs.Append( new gul::ListNode< kdrec<U,V> >(rec) );
00166   }
00167   kdnnrec<U,V>& operator=( kdnnrec<U,V>& other )
00168   {
00169     if( this == &other ) return *this;
00170 
00171     m_dist = other.m_dist;
00172     m_recs = other.m_recs;
00173     return *this;
00174   }
00175   // debugging functions
00176   GULAPI void dump( int dim );
00177 };
00178 
00179 // these objects are used internally while finding nearest neighbors
00180 template< class U, class V >
00181 class kdtsnode : public gul::pool_object
00182 {
00183 public:
00184   const kdtnode<U,V>  *m_n;
00185   gul::Ptr<V>          m_D;
00186   V                    m_d;
00187   kdtsnode( const kdtnode<U,V> *n, const gul::Ptr<V>& D, V d )
00188   {
00189     m_n = n;
00190     m_D = D;
00191     m_d = d;
00192   } 
00193 };
00194 
00195 template< class U, class V >
00196 class kdtsearch : public gul::pool_object
00197 {
00198 public:
00199   int                                   m_dim;
00200   int                                   m_nNeighbors;
00201   V                                     m_maxDist;
00202   gul::Map< kdnnrec<U,V> >              m_neighbors;
00203   int                                   m_maxNeighbors;
00204 
00205   // important: maxNeighbors must be at least 1 !!!
00206   kdtsearch( int dim, int maxNeighbors )
00207   {
00208     m_dim = dim;
00209     m_nNeighbors = 0;
00210     m_maxNeighbors = maxNeighbors;
00211   }
00212   void scan_records( 
00213              const U& P, const gul::List< gul::ListNode< kdrec<U,V> > >& recs );
00214   void process_node( const U& P, const kdtnode<U,V> *n, const gul::Ptr<V>& D, V d, 
00215                      gul::List< gul::ListNode< kdtsnode<U,V> > >& stack );
00216   
00217   static int compare_key_to_node( V *k, kdnnrec<U,V> *r );
00218   V length( const gul::Ptr<V>& P );
00219 };
00220 
00221 
00222 /* ------------------------------------------------------------------------
00223   class with base functionality (but without a special random number generator)
00224 -------------------------------------------------------------------------*/
00225 template< class U, class V >
00226 class rkdtree_base : public gul::pool_object
00227 {
00228 public:
00229   int           m_dim;
00230   kdtnode<U,V> *m_root;
00231 
00232   rkdtree_base( int dim ) { m_dim = dim; m_root = 0; }
00233   ~rkdtree_base() { delete m_root; }
00234 
00235   // the array M has to be reserved by the caller
00236   GULAPI int nearest_neighbors(  const U& P, int m, gul::Ptr< kdnnrec<U,V> >& M  );
00237 
00238   void split_recs(  
00239     gul::List< gul::ListNode< kdrec<U,V> > >& recs, const V& key, int i, 
00240     gul::List< gul::ListNode< kdrec<U,V> > >& recs1, 
00241     gul::List< gul::ListNode< kdrec<U,V> > >& recs2,
00242     gul::List< gul::ListNode< kdrec<U,V> > >& C );
00243   void split_recs(  
00244     gul::List< gul::ListNode< kdrec<U,V> > >& recs, const U& X, int i, 
00245     gul::List< gul::ListNode< kdrec<U,V> > >& recs1,
00246     gul::List< gul::ListNode< kdrec<U,V> > >& recs2,
00247     gul::List< gul::ListNode< kdrec<U,V> > >& C )
00248   {
00249     split_recs( recs, X[i], i, recs1, recs2, C );
00250   }
00251 
00252   // debugging functions
00253   GULAPI void dump_statistics();
00254   GULAPI void dump_tree();
00255 };
00256 
00257 /*--------------------------------------------------------------------------
00258   randomized kd-tree
00259 --------------------------------------------------------------------------*/
00260 template< class U, class V, class Rand >
00261 class rkdtree : public rkdtree_base<U,V>
00262 {
00263 public:
00264   rkdtree( int dim ) : rkdtree_base<U,V>(dim) { }
00265   ~rkdtree() { }
00266 
00267   void insert( const U *rec ) { m_root = insert(m_root, kdrec<U,V>(rec)); }
00268   void remove( const U *rec, gul::List< gul::ListNode< kdrec<U,V> > >& outrecs ) 
00269   { 
00270     m_root = remove(m_root, kdrec<U,V>(rec), outrecs);
00271   }
00272 
00273   GULAPI kdtnode<U,V> *insert( kdtnode<U,V> *T, const kdrec<U,V>& rec );
00274   GULAPI kdtnode<U,V> *remove( 
00275                  kdtnode<U,V> *T, 
00276                  const kdrec<U,V>& rec,
00277                  gul::List< gul::ListNode< kdrec<U,V> > >& outrecs );
00278 
00279   void split( kdtnode<U,V> *T, const V& key, int i, 
00280               kdtnode<U,V> **retL, kdtnode<U,V> **retR, 
00281               gul::List< gul::ListNode< kdrec<U,V> > >& C );
00282   void split( kdtnode<U,V> *T, const kdrec<U,V>& X, int i, 
00283               kdtnode<U,V> **retL, kdtnode<U,V> **retR, 
00284               gul::List< gul::ListNode< kdrec<U,V> > >& C ) 
00285   {
00286     split( T, X[i], i, retL, retR, C );
00287   }
00288 
00289   kdtnode<U,V> *join( kdtnode<U,V> *A, kdtnode<U,V> *B, int i );
00290 };
00291 
00292 }
00293 
00294 #endif
00295 

Generated on Mon Jan 21 04:17:35 2002 for GUL 0.6 - Geometry Utility Library by doxygen1.2.13.1 written by Dimitri van Heesch, © 1997-2001