contrib/rpl/rsdl/rsdl_kd_tree.cxx

Go to the documentation of this file.
00001 // This is rpl/rsdl/rsdl_kd_tree.cxx
00002 #include "rsdl_kd_tree.h"
00003 
00004 #include <vcl_algorithm.h>
00005 #include <vcl_cassert.h>
00006 #include <vcl_cmath.h>
00007 #include <vcl_iostream.h>
00008 #include <vcl_utility.h>
00009 
00010 #include <vnl/vnl_math.h>
00011 #include <vnl/vnl_numeric_traits.h>
00012 
00013 #include <rsdl/rsdl_dist.h>
00014 
00015 
00016 rsdl_kd_tree::rsdl_kd_tree( const vcl_vector< rsdl_point >& points,
00017                             double min_angle,
00018                             int points_per_leaf )
00019   : points_(points), min_angle_(min_angle)
00020 {
00021   assert(points_per_leaf > 0);
00022 
00023   Nc_ = points_[0].num_cartesian();
00024   Na_ = points_[0].num_angular();
00025 
00026   //  0. Consistency check
00027 
00028   for ( unsigned int i=1; i<points_.size(); ++i ) {
00029     assert( Nc_ == points_[i].num_cartesian() );
00030     assert( Na_ == points_[i].num_angular() );
00031   }
00032 
00033   // 1.  Build the initial bounding box.
00034 
00035   rsdl_point low(Nc_, Na_), high(Nc_, Na_);
00036 
00037   // 1a. initialize the cartesian upper and lower limits
00038   if ( Nc_ > 0 ) {
00039     for ( unsigned int i=0; i<Nc_; ++i ) {
00040       low.cartesian(i)  = -vnl_numeric_traits<double>::maxval;
00041       high.cartesian(i) =  vnl_numeric_traits<double>::maxval;
00042     }
00043   }
00044 
00045   // 1b. initialize the angular upper and lower limits
00046   if ( Na_ > 0 ) {
00047     for ( unsigned int i=0; i<Na_; ++i ) {
00048       low.angular(i) = min_angle;
00049       high.angular(i) = min_angle + 2*vnl_math::pi;
00050     }
00051   }
00052 
00053   // 1c. create the bounding box
00054   rsdl_bounding_box box( low, high );
00055 #ifdef DEBUG
00056   vcl_cout << "Initial bounding box: " << box << vcl_endl;
00057 #endif
00058   // 2. create the vector of ids
00059   vcl_vector< int > indices( points_.size() );
00060   for ( unsigned int i=0; i<indices.size(); ++i ) indices[ i ] = i;
00061 
00062   leaf_count_ = internal_count_ = 0;
00063 
00064   // 3. call recursive function to do the real work
00065   root_ = build_kd_tree( points_per_leaf, box, 0, indices );
00066 }
00067 
00068 
00069 bool
00070 first_less( const vcl_pair<double,int>& left,
00071             const vcl_pair<double,int>& right )
00072 {
00073   return left.first < right.first;
00074 }
00075 
00076 
00077 rsdl_kd_node *
00078 rsdl_kd_tree::build_kd_tree( int points_per_leaf,
00079                              const rsdl_bounding_box& outer_box,
00080                              int depth,
00081                              vcl_vector< int >& indices )
00082 {
00083   assert(points_per_leaf > 0);
00084   unsigned int i;
00085 #ifdef DEBUG
00086   vcl_cout << "build_kd_tree:\n  ids:\n";
00087   for ( i=0; i<indices.size(); ++i )
00088     vcl_cout << " index: " << indices[i] << ",  point:  " << points_[ indices[i] ] << '\n';
00089   vcl_cout << "\n  outer bounding box:\n" << outer_box << vcl_endl;
00090 #endif
00091   // 1. Build the inner box.  This is not done inside the bounding box
00092   // class because of the indices.
00093 
00094   rsdl_bounding_box inner_box = this -> build_inner_box( indices );
00095 #ifdef DEBUG
00096   vcl_cout << "\n  inner bounding box:\n" << inner_box << vcl_endl;
00097 #endif
00098 
00099   // 2. If the number of points is small enough, create and return a leaf node.
00100 
00101   if ( indices.size() <= (unsigned int)points_per_leaf ) {
00102 #ifdef DEBUG
00103     vcl_cout << "making leaf node" << vcl_endl;
00104 #endif
00105     leaf_count_ ++ ;
00106     return new rsdl_kd_node ( outer_box, inner_box, depth, indices );
00107   }
00108 
00109   // 3. Find the dimension along which there is the greatest variation
00110   // in the points.
00111 
00112   bool use_cartesian;
00113   int dim;
00114   this->greatest_variation( indices, use_cartesian, dim );
00115 #ifdef DEBUG
00116   vcl_cout << "greatest_varation returned  use_cartesian = " << use_cartesian
00117            << ", dim = " << dim << vcl_endl;
00118 #endif
00119   // 4. Form and then sort a vector of temporary pairs, containing the
00120   // indices and the values along the selected dim of the data.
00121   // Sort by the values.
00122 
00123   vcl_vector< vcl_pair< double, int > > values( indices.size() );
00124   for ( i=0; i<indices.size(); ++i ) {
00125     if ( use_cartesian ) {
00126       values[i] = vcl_pair<double, int> ( points_[ indices[i] ].cartesian( dim ), indices[i] );
00127     }
00128     else  {
00129       values[i] = vcl_pair<double, int> ( points_[ indices[i] ].angular( dim ), indices[i] );
00130     }
00131   }
00132   vcl_sort( values.begin(), values.end(), first_less );
00133 #ifdef DEBUG
00134   vcl_cout << "\nsorted values/indices:\n";
00135   for ( i=0; i<values.size(); ++i )
00136     vcl_cout << i << ":  value = " << values[i].first << ", id = " << values[i].second << vcl_endl;
00137 #endif
00138   // 5. Partition the vector and the bounding box along the dimension.
00139 
00140   unsigned int med_loc = (indices.size()-1) / 2;
00141   double median_value = (values[med_loc].first + values[med_loc+1].first) / 2;
00142 #ifdef DEBUG
00143   vcl_cout << "med_loc = " << med_loc << ", median_value = " << median_value << vcl_endl;
00144 #endif
00145   rsdl_bounding_box left_outer_box( outer_box ), right_outer_box( outer_box );
00146   if ( use_cartesian ) {
00147     left_outer_box.max_cartesian( dim ) = median_value;
00148     right_outer_box.min_cartesian( dim ) = median_value;
00149   }
00150   else {
00151     left_outer_box.max_angular( dim ) = median_value;
00152     right_outer_box.min_angular( dim ) = median_value;
00153   }
00154 #ifdef DEBUG
00155   vcl_cout << "new bounding boxes:  left " << left_outer_box
00156            << "\n  right " << right_outer_box << vcl_endl;
00157 #endif
00158   vcl_vector< int > left_indices( med_loc+1 ), right_indices( indices.size()-med_loc-1 );
00159   for ( i=0; i<=med_loc; ++i ) left_indices[i] = values[i].second;
00160   for ( ; i<indices.size(); ++i ) right_indices[i-med_loc-1] = values[i].second;
00161 
00162   rsdl_kd_node * node = new rsdl_kd_node( outer_box, inner_box, depth );
00163   internal_count_ ++ ;
00164   node->left_ = this->build_kd_tree( points_per_leaf, left_outer_box, depth+1, left_indices );
00165   node->right_ = this->build_kd_tree( points_per_leaf, right_outer_box, depth+1, right_indices );
00166 
00167   return node;
00168 }
00169 
00170 
00171 rsdl_bounding_box
00172 rsdl_kd_tree :: build_inner_box( const vcl_vector< int >& indices )
00173 {
00174   assert( indices.size() > 0 );
00175   rsdl_point min_point( points_[ indices[ 0 ] ] );
00176   rsdl_point max_point( min_point );
00177 
00178   for (unsigned int i=1; i < indices.size(); ++ i ) {
00179     const rsdl_point& pt = points_[ indices[ i ] ];
00180 
00181     for ( unsigned int j=0; j < Nc_; ++ j ) {
00182       if ( pt.cartesian( j ) < min_point.cartesian( j ) )
00183         min_point.cartesian( j ) = pt.cartesian( j );
00184       if ( pt.cartesian( j ) > max_point.cartesian( j ) )
00185         max_point.cartesian( j ) = pt.cartesian( j );
00186     }
00187 
00188     for ( unsigned int j=0; j < Na_; ++ j ) {
00189       if ( pt.angular( j ) < min_point.angular( j ) )
00190         min_point.angular( j ) = pt.angular( j );
00191       if ( pt.angular( j ) > max_point.angular( j ) )
00192         max_point.angular( j ) = pt.angular( j );
00193     }
00194   }
00195   return rsdl_bounding_box( min_point, max_point );
00196 }
00197 
00198 
00199 void
00200 rsdl_kd_tree::greatest_variation( const vcl_vector<int>& indices,
00201                                   bool& use_cartesian,
00202                                   int& dim )
00203 {
00204   use_cartesian = true;
00205   bool initialized = false;
00206   double interval_size = 0.0;
00207 
00208   // 1. Check the Cartesian dimensions, if they exist
00209 
00210   for ( unsigned int i=0; i<Nc_; ++i ) {
00211     double min_v, max_v;
00212     min_v = max_v = points_[ indices[0] ].cartesian( i );
00213     for ( unsigned int j=1; j<indices.size(); ++j ) {
00214       double v = points_[ indices[j] ].cartesian( i );
00215       if ( v < min_v ) min_v = v;
00216       if ( v > max_v ) max_v = v;
00217     }
00218     if ( !initialized || max_v - min_v > interval_size ) {
00219       dim = i;
00220       interval_size = max_v - min_v;
00221       initialized = true;
00222     }
00223   }
00224 
00225   // 2. Check the angular dimensions, if they exist
00226 
00227   for ( unsigned int i=0; i<Na_; ++i ) {
00228     double min_v, max_v;
00229     min_v = max_v = points_[ indices[0] ].angular( i );
00230     for (unsigned int j=1; j<indices.size(); ++j ) {
00231       double v = points_[ indices[j] ].angular( i );
00232       if ( v < min_v ) min_v = v;
00233       if ( v > max_v ) max_v = v;
00234     }
00235     if ( !initialized || max_v - min_v > interval_size ) {
00236       dim = i;
00237       use_cartesian = false;
00238       interval_size = max_v - min_v;
00239       initialized = true;
00240     }
00241   }
00242 
00243   assert( initialized );
00244 }
00245 
00246 
00247 rsdl_kd_tree::~rsdl_kd_tree( )
00248 {
00249   destroy_tree( root_ );
00250 }
00251 
00252 void
00253 rsdl_kd_tree::destroy_tree( rsdl_kd_node*&  p )
00254 {
00255   if ( p ) {
00256     destroy_tree( p->left_ );
00257     destroy_tree( p->right_ );
00258     delete p;
00259     p = 0;
00260   }
00261 }
00262 
00263 
00264 void
00265 rsdl_kd_tree::n_nearest( const rsdl_point& query_point,
00266                          int n,
00267                          vcl_vector< rsdl_point >& closest_points,
00268                          vcl_vector< int >& closest_indices,
00269                          bool use_heap,
00270                          int max_leaves)
00271 {
00272   assert(n>0);
00273   assert( query_point.num_cartesian() == Nc_ );
00274   assert( query_point.num_angular() == Na_ );
00275 
00276   //if we are using approx query, then we must use heap
00277   assert(max_leaves == -1 || (max_leaves > 0 && use_heap));
00278 
00279   if ( closest_indices.size() != (unsigned int)n )
00280     closest_indices.resize( n );
00281   vcl_vector< double > sq_distances( n, 1e+10 );  // could cache for (slight) efficiency gain
00282   int num_found = 0;
00283 
00284   leaves_examined_ = internal_examined_ = 0;
00285 
00286   if ( use_heap )
00287     this->n_nearest_with_heap( query_point, n, root_, closest_indices, sq_distances, num_found, max_leaves );
00288   else
00289     this->n_nearest_with_stack( query_point, n, root_, closest_indices, sq_distances, num_found );
00290 #ifdef DEBUG
00291   vcl_cout << "\nAfter n_nearest, leaves_examined_ = " << leaves_examined_
00292            << ", fraction = " << float(leaves_examined_) / leaf_count_
00293            << "\n     internal_examined_ = " << internal_examined_
00294            << ", fraction = " << float(internal_examined_) / internal_count_ << vcl_endl;
00295 #endif
00296   assert(num_found >= 0);
00297   if ( closest_points.size() != (unsigned int)num_found )
00298     closest_points.resize( num_found );
00299 
00300   for ( int i=0; i<num_found; ++i ) {
00301     closest_points[i] = points_[ closest_indices[i] ];
00302   }
00303 }
00304 
00305 
00306 void
00307 rsdl_kd_tree::n_nearest_with_stack( const rsdl_point& query_point,
00308                                     int n,
00309                                     rsdl_kd_node* root,
00310                                     vcl_vector< int >& closest_indices,
00311                                     vcl_vector< double >& sq_distances,
00312                                     int & num_found )
00313 {
00314   assert(n>0);
00315 #ifdef DEBUG
00316   vcl_cout << "\n\n----------------\nn_nearest_with_stack" << vcl_endl;
00317 #endif
00318   vcl_vector< rsdl_kd_heap_entry  > stack_vec;
00319   stack_vec.reserve( 100 );    // way more than will ever be needed
00320   double left_box_sq_dist, right_box_sq_dist;
00321   double sq_dist;
00322   bool initial_path = true;
00323 
00324   //  Go down tree,
00325   rsdl_kd_node* current = root;
00326   sq_dist = 0;
00327 
00328   do {
00329 #ifdef DEBUG
00330     vcl_cout << "\ncurrent -- sq_dist " << sq_dist << ", depth: " << current->depth_
00331              << "\nouter_box: " << current->outer_box_
00332              << "\ninner_box: " << current->inner_box_
00333              << "\nstack size: " << stack_vec.size() << vcl_endl;
00334 #endif
00335     // if the distance is too large, skip node and take the next node
00336     // from the stack
00337 
00338     if ( num_found >= n && sq_dist >= sq_distances[ num_found-1 ] ) {
00339 #ifdef DEBUG
00340       vcl_cout << "skipping node" << vcl_endl;
00341 #endif
00342       if ( stack_vec.size() == 0 )
00343         return;  // DONE
00344       else {
00345         sq_dist = stack_vec[ stack_vec.size()-1 ].dist_;
00346         current = stack_vec[ stack_vec.size()-1 ].p_;
00347         stack_vec.pop_back();
00348       }
00349     }
00350 
00351     //  if this is a leaf node, update the set of closest points, and
00352     //  take the next node from the stack
00353 
00354     else if ( ! current->left_ ) {
00355 #ifdef DEBUG
00356       vcl_cout << "At a leaf" << vcl_endl;
00357 #endif
00358       leaves_examined_ ++ ;
00359       update_closest( query_point, n, current, closest_indices, sq_distances, num_found );
00360 
00361       //  If stack is empty then we're done.
00362       if ( stack_vec.size() == 0 )
00363         return;  // done
00364 
00365       //  If we're on the first path down the tree and if we can decide there
00366       //  is no possibility of any other closer point, then quit.
00367       else
00368       {
00369         if ( initial_path )
00370         {
00371 #ifdef DEBUG
00372           vcl_cout << "First leaf" << vcl_endl;
00373 #endif
00374           initial_path = false ;
00375           if ( this-> bounded_at_leaf( query_point, n, current, sq_distances, num_found ) )
00376             return; //  done
00377         }
00378 
00379         //  Pop the stack as the next location.
00380         sq_dist = stack_vec[ stack_vec.size()-1 ].dist_;
00381         current = stack_vec[ stack_vec.size()-1 ].p_;
00382         stack_vec.pop_back();
00383       }
00384     }
00385 
00386     else
00387     {
00388 #ifdef DEBUG
00389       vcl_cout << "Internal node" << vcl_endl;
00390 #endif
00391       internal_examined_ ++ ;
00392       left_box_sq_dist = rsdl_dist_sq( query_point, current->left_->inner_box_ );
00393       right_box_sq_dist = rsdl_dist_sq( query_point, current->right_->inner_box_ );
00394 #ifdef DEBUG
00395       vcl_cout << "left sq distance = " << left_box_sq_dist << vcl_endl
00396                << "right sq distance = " << right_box_sq_dist << vcl_endl;
00397 #endif
00398 
00399       if ( left_box_sq_dist < right_box_sq_dist )
00400       {
00401 #ifdef DEBUG
00402         vcl_cout << "going left, pushing right" << vcl_endl;
00403 #endif
00404         stack_vec.push_back( rsdl_kd_heap_entry( right_box_sq_dist, current->right_ ) );
00405         current = current->left_ ;
00406       }
00407       else {
00408 #ifdef DEBUG
00409         vcl_cout << "going right, pushing left" << vcl_endl;
00410 #endif
00411         stack_vec.push_back( rsdl_kd_heap_entry( left_box_sq_dist, current->left_ ) );
00412         current = current->right_ ;
00413       }
00414     }
00415   } while ( true );
00416 }
00417 
00418 
00419 void
00420 rsdl_kd_tree::n_nearest_with_heap( const rsdl_point& query_point,
00421                                    int n,
00422                                    rsdl_kd_node* root,
00423                                    vcl_vector< int >& closest_indices,
00424                                    vcl_vector< double >& sq_distances,
00425                                    int & num_found,
00426                                    int max_leaves)
00427 {
00428   assert(n>0);
00429 #ifdef DEBUG
00430   vcl_cout << "\n\n----------------\nn_nearest_with_heap" << vcl_endl;
00431 #endif
00432   vcl_vector< rsdl_kd_heap_entry > heap_vec;
00433   heap_vec.reserve( 100 );
00434   double left_box_sq_dist, right_box_sq_dist;
00435   double sq_dist;
00436 
00437   //  Go down tree,
00438   rsdl_kd_node* current = root;
00439   while ( current->left_ ) {
00440     internal_examined_ ++ ;
00441 
00442     if ( rsdl_dist_sq( query_point, current-> left_ -> outer_box_ ) < 1.0e-5 ) {
00443       right_box_sq_dist = rsdl_dist_sq( query_point, current->right_->inner_box_ );
00444       heap_vec.push_back( rsdl_kd_heap_entry( right_box_sq_dist, current->right_ ) );
00445       current = current->left_ ;
00446     }
00447     else {
00448       left_box_sq_dist = rsdl_dist_sq( query_point, current->left_->inner_box_ );
00449       heap_vec.push_back( rsdl_kd_heap_entry( left_box_sq_dist, current->left_ ) );
00450       current = current->right_ ;
00451     }
00452   }
00453   vcl_make_heap( heap_vec.begin(), heap_vec.end() );
00454   sq_dist = 0;
00455 
00456 #ifdef DEBUG
00457   vcl_cout << "\nAfter initial trip down the tree, here's the heap\n";
00458   for ( int i=0; i<heap_vec.size(); ++i )
00459     vcl_cout << "  " << i << ":  sq distance " << heap_vec[i].dist_
00460              << ", node depth " << heap_vec[i].p_->depth_ << vcl_endl;
00461 #endif
00462   bool first_leaf = true;
00463 
00464   do {
00465 #ifdef DEBUG
00466     vcl_cout << "\ncurrent -- sq_dist " << sq_dist << ", depth: " << current->depth_
00467              << "\nouter_box: " << current->outer_box_
00468              << "\ninner_box: " << current->inner_box_
00469              << "\nheap size: " << heap_vec.size() << vcl_endl;
00470 #endif
00471     if ( num_found < n || sq_dist < sq_distances[ num_found-1 ] ) {
00472       if ( ! current->left_ ) {  // a leaf node
00473 #ifdef DEBUG
00474         vcl_cout << "Leaf" << vcl_endl;
00475 #endif
00476         leaves_examined_ ++ ;
00477         update_closest( query_point, n, current, closest_indices, sq_distances, num_found );
00478         if ( first_leaf ) {  // check if we can quit just at this leaf node.
00479 #ifdef DEBUG
00480           vcl_cout << "First leaf" << vcl_endl;
00481 #endif
00482           first_leaf = false;
00483           if ( this-> bounded_at_leaf( query_point, n, current, sq_distances, num_found ) )
00484             return;
00485         }
00486         if (max_leaves != -1 && leaves_examined_ >= max_leaves)
00487           return;
00488       }
00489 
00490       else {
00491 #ifdef DEBUG
00492         vcl_cout << "Internal" << vcl_endl;
00493 #endif
00494         internal_examined_ ++ ;
00495 
00496         left_box_sq_dist = rsdl_dist_sq( query_point, current->left_->inner_box_ );
00497 #ifdef DEBUG
00498         vcl_cout << "left sq distance = " << left_box_sq_dist << vcl_endl;
00499 #endif
00500         if ( num_found < n || sq_distances[ num_found-1 ] > left_box_sq_dist ) {
00501 #ifdef DEBUG
00502           vcl_cout << "pushing left onto the heap" << vcl_endl;
00503 #endif
00504           heap_vec.push_back( rsdl_kd_heap_entry( left_box_sq_dist, current->left_ ) );
00505           vcl_push_heap( heap_vec.begin(), heap_vec.end() );
00506         };
00507 
00508         right_box_sq_dist = rsdl_dist_sq( query_point, current->right_->inner_box_ );
00509 #ifdef DEBUG
00510         vcl_cout << "right sq distance = " << right_box_sq_dist << vcl_endl;
00511 #endif
00512         if ( num_found < n || sq_distances[ num_found-1 ] > right_box_sq_dist ) {
00513 #ifdef DEBUG
00514           vcl_cout << "pushing right onto the heap" << vcl_endl;
00515 #endif
00516           heap_vec.push_back( rsdl_kd_heap_entry( right_box_sq_dist, current->right_ ) );
00517           vcl_push_heap( heap_vec.begin(), heap_vec.end() );
00518         }
00519       }
00520     }
00521 #ifdef DEBUG
00522     else vcl_cout << "skipping node" << vcl_endl;
00523 #endif
00524 
00525     if ( heap_vec.size() == 0 )
00526       return;
00527     else {
00528       vcl_pop_heap( heap_vec.begin(), heap_vec.end() );
00529       sq_dist = heap_vec[ heap_vec.size()-1 ].dist_;
00530       current = heap_vec[ heap_vec.size()-1 ].p_;
00531       heap_vec.pop_back();
00532     }
00533   } while ( true );
00534 }
00535 
00536 void
00537 rsdl_kd_tree::update_closest( const rsdl_point& query_point,
00538                               int n,
00539                               rsdl_kd_node* p,
00540                               vcl_vector< int >& closest_indices,
00541                               vcl_vector< double >& sq_distances,
00542                               int & num_found )
00543 {
00544   assert(n>0);
00545 #ifdef DEBUG
00546   vcl_cout << "Update_closest for leaf\n query_point = " << query_point
00547            << "\n inner bounding box =\n" << p->inner_box_
00548            << "\n sq_dist = " << rsdl_dist_sq( query_point, p->inner_box_ )
00549            << vcl_endl;
00550 #endif
00551 
00552   for ( unsigned int i=0; i < p->point_indices_.size(); ++i ) {  // check each id
00553     int id = p->point_indices_[i];
00554     double sq_dist = rsdl_dist_sq( query_point, points_[ id ] );
00555 #ifdef DEBUG
00556     vcl_cout << "  id = " << id << ", point = " << points_[ id ]
00557              << ", sq_dist = " << sq_dist << vcl_endl;
00558 #endif
00559 
00560     // if enough points have been found and the distance of this point is
00561     // too large then skip it.
00562 
00563     if ( num_found >= n && sq_dist >= sq_distances[ num_found-1 ] )
00564       continue;
00565 
00566     // Increment the num_found counter if fewer than the desired
00567     // number have already been found.
00568 
00569     if ( num_found < n ) {
00570       num_found ++;
00571     }
00572 
00573     // Insert the id and square distance in order.
00574 
00575     int j=num_found-2;
00576     while ( j >= 0 && sq_distances[j] > sq_dist ) {
00577       closest_indices[ j+1 ] = closest_indices[ j ];
00578       sq_distances[ j+1 ] = sq_distances[ j ];
00579       j -- ;
00580     }
00581     closest_indices[ j+1 ] = id;
00582     sq_distances[ j+1 ] = sq_dist;
00583   }
00584 #ifdef DEBUG
00585   vcl_cout << "  End of leaf computation, num_found =  " << num_found
00586            << ", and they are:\n";
00587   for ( int k=0; k<num_found; ++k )
00588     vcl_cout << "     " << k << ":  indices: " << closest_indices[ k ]
00589              << ", sq_dist " << sq_distances[ k ] << vcl_endl;
00590 #endif
00591 }
00592 
00593 
00594 //  If there are already n points (at the first leaf) and if a box
00595 //  drawn around the first point of half-width the distance of the
00596 //  n-th point fits inside the outer box of this node, then no points
00597 //  anywhere else in the tree will can replace any of the closest
00598 //  points.
00599 
00600 bool
00601 rsdl_kd_tree :: bounded_at_leaf ( const rsdl_point& query_point,
00602                                   int n,
00603                                   rsdl_kd_node* current,
00604                                   const vcl_vector< double >& sq_distances,
00605                                   int & num_found )
00606 {
00607   assert(n>0);
00608 #ifdef DEBUG
00609   vcl_cout << "bounded_at_leaf\n num_found = " << num_found << vcl_endl;
00610 #endif
00611 
00612   if ( num_found != n ) {
00613     return false;
00614   }
00615 
00616   double radius = vcl_sqrt( sq_distances[ n-1 ] );
00617 
00618   for ( unsigned int i = 0; i < Nc_; ++ i ) {
00619     double x = query_point.cartesian( i );
00620     if ( current -> outer_box_ . min_cartesian( i ) > x - radius ||
00621          current -> outer_box_ . max_cartesian( i ) < x + radius ) {
00622       return false;
00623     }
00624   }
00625 
00626   for ( unsigned int i = 0; i < Na_; ++ i ) {
00627     double a = query_point.angular( i );
00628     if ( current -> outer_box_ . min_angular( i ) > a - radius ||
00629          current -> outer_box_ . max_angular( i ) < a + radius ) {
00630       return false;
00631     }
00632   }
00633 
00634   return true;
00635 }
00636 
00637 
00638 //  Find all points within a query's bounding box
00639 void
00640 rsdl_kd_tree :: points_in_bounding_box( const rsdl_bounding_box& box,
00641                                         vcl_vector< rsdl_point >& points_in_box,
00642                                         vcl_vector< int >& indices_in_box )
00643 {
00644   points_in_box.clear();
00645   indices_in_box.clear();
00646   this -> points_in_bounding_box( root_, box, indices_in_box );
00647   for ( unsigned int i=0; i<indices_in_box.size(); ++i )
00648     points_in_box.push_back( this -> points_[ indices_in_box[i] ] );
00649 }
00650 
00651 
00652 void
00653 rsdl_kd_tree :: points_in_radius( const rsdl_point& query_point,
00654                                   double radius,
00655                                   vcl_vector< rsdl_point >& points_within_radius,
00656                                   vcl_vector< int >& indices_within_radius )
00657 {
00658   //  Form a bounding box of width 2*radius, centered at the point.
00659   //  Start by creating the corner points of this box.
00660   rsdl_point min_point( query_point.num_cartesian(), query_point.num_angular() );
00661   rsdl_point max_point( query_point.num_cartesian(), query_point.num_angular() );
00662 
00663   //  Fill in the cartesian values.
00664   for ( unsigned int i=0; i < query_point.num_cartesian(); ++i ) {
00665     min_point.cartesian( i ) = query_point.cartesian(i) - radius;
00666     max_point.cartesian( i ) = query_point.cartesian(i) + radius;
00667   }
00668 
00669   //  Fill in the angular values.  If the radius is at least pi then
00670   //  the whole range of angles will be covered.
00671   if ( radius >= vnl_math::pi ) {
00672     for ( unsigned int j=0; j < query_point.num_angular(); ++j ) {
00673       min_point.angular( j ) = this -> min_angle_;
00674       max_point.angular( j ) = this -> min_angle_ + 2 * vnl_math::pi;
00675     }
00676   }
00677   //  The radius is less than pi.  For each angular value, generate
00678   //  the min and max angular values.  Check both for wrap-around.
00679   else {
00680     for ( unsigned int j=0; j < query_point.num_angular(); ++j ) {
00681       double min_angle = query_point.angular(j) - radius;
00682       if ( min_angle < this -> min_angle_ )
00683         min_angle += 2 * vnl_math::pi;
00684       double max_angle = query_point.angular(j) + radius;
00685       if ( max_angle > this -> min_angle_ + 2 * vnl_math::pi )
00686         max_angle -= 2 * vnl_math::pi;
00687       min_point.angular( j ) = min_angle;
00688       max_point.angular( j ) = max_angle;
00689     }
00690   }
00691 
00692   //  Now, create the bounding box, and scratch vectors.
00693   rsdl_bounding_box box( min_point, max_point );
00694   vcl_vector< int > indices_in_box;
00695 
00696   //  Gather the points in the bounding box:
00697   this -> points_in_bounding_box( this -> root_, box, indices_in_box );
00698 
00699   //  Clear out the result vectors in preparation
00700   points_within_radius.clear();
00701   indices_within_radius.clear();
00702 
00703   //  Gather the points from the bounding box that are within the radius.
00704   double sq_radius = radius*radius;
00705   for ( unsigned int i=0; i < indices_in_box.size(); ++i ) {
00706     int index = indices_in_box[ i ];
00707     if ( rsdl_dist_sq( query_point, this -> points_[ index ] ) < sq_radius ) {
00708       points_within_radius.push_back( this -> points_[ index ] );
00709       indices_within_radius.push_back( index );
00710     }
00711   }
00712 }
00713 
00714 void
00715 rsdl_kd_tree :: points_in_bounding_box( rsdl_kd_node* current,
00716                                         const rsdl_bounding_box& box,
00717                                         vcl_vector< int >& indices_in_box )
00718 {
00719   if ( ! current -> left_ ) {
00720     for ( unsigned int i=0; i < current -> point_indices_ . size(); ++i ) {
00721       int index = current -> point_indices_[ i ];
00722       if ( rsdl_dist_point_in_box( this -> points_[ index ], box ) )
00723         indices_in_box.push_back( index );
00724     }
00725   }
00726   else {
00727     bool inside, intersects;
00728     rsdl_dist_box_relation( current -> inner_box_, box, inside, intersects );
00729     if ( inside )
00730       this -> report_all_in_subtree( current, indices_in_box );
00731     else if ( intersects ) {
00732       this -> points_in_bounding_box( current -> left_, box, indices_in_box );
00733       this -> points_in_bounding_box( current -> right_, box, indices_in_box );
00734     }
00735   }
00736 }
00737 
00738 void
00739 rsdl_kd_tree :: report_all_in_subtree( rsdl_kd_node* current,
00740                                        vcl_vector< int >& indices )
00741 {
00742   if ( current -> left_ ) {
00743     this -> report_all_in_subtree( current -> left_, indices );
00744     this -> report_all_in_subtree( current -> right_, indices );
00745   }
00746   else {
00747     for ( unsigned int i=0; i < current -> point_indices_ . size(); ++ i ) {
00748       indices.push_back( current -> point_indices_[ i ] );
00749     }
00750   }
00751 }

Generated on Mon Mar 8 05:26:58 2010 for contrib/rpl/rsdl by  doxygen 1.5.1