00001
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
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
00034
00035 rsdl_point low(Nc_, Na_), high(Nc_, Na_);
00036
00037
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
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
00054 rsdl_bounding_box box( low, high );
00055 #ifdef DEBUG
00056 vcl_cout << "Initial bounding box: " << box << vcl_endl;
00057 #endif
00058
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
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
00092
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
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
00110
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
00120
00121
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
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
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
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
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 );
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 );
00320 double left_box_sq_dist, right_box_sq_dist;
00321 double sq_dist;
00322 bool initial_path = true;
00323
00324
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
00336
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;
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
00352
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
00362 if ( stack_vec.size() == 0 )
00363 return;
00364
00365
00366
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;
00377 }
00378
00379
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
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_ ) {
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 ) {
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 ) {
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
00561
00562
00563 if ( num_found >= n && sq_dist >= sq_distances[ num_found-1 ] )
00564 continue;
00565
00566
00567
00568
00569 if ( num_found < n ) {
00570 num_found ++;
00571 }
00572
00573
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
00595
00596
00597
00598
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
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
00659
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
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
00670
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
00678
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
00693 rsdl_bounding_box box( min_point, max_point );
00694 vcl_vector< int > indices_in_box;
00695
00696
00697 this -> points_in_bounding_box( this -> root_, box, indices_in_box );
00698
00699
00700 points_within_radius.clear();
00701 indices_within_radius.clear();
00702
00703
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 }