00001 #ifndef rsdl_bins_txx_
00002 #define rsdl_bins_txx_
00003
00004
00005
00006
00007
00008 #include "rsdl_bins.h"
00009
00010 #include <vcl_cassert.h>
00011 #include <vcl_iostream.h>
00012 #include <vcl_cmath.h>
00013 #include <vcl_vector.h>
00014 #include <vcl_algorithm.h>
00015
00016
00017
00018
00019
00020
00021
00022 template<unsigned N, typename CoordType, typename ValueType>
00023 struct rsdl_bins_point_dist_entry
00024 {
00025 typedef rsdl_bins<N,CoordType,ValueType> bin_class;
00026 typedef rsdl_bins_bin_entry_type<N,CoordType,ValueType> bin_entry_type;
00027 typedef typename bin_class::coord_type coord_type;
00028 typedef typename bin_class::point_type point_type;
00029
00030 rsdl_bins_point_dist_entry( point_type const& query_pt,
00031 bin_entry_type const* entry );
00032
00033 inline bool operator<( rsdl_bins_point_dist_entry const& other ) const;
00034
00035 bin_entry_type const* entry_;
00036 coord_type dist_;
00037 };
00038
00039
00040
00041
00042
00043 template<unsigned N, typename C, typename V>
00044 rsdl_bins<N,C,V>::
00045 rsdl_bins( point_type const& min_coord,
00046 point_type const& max_coord,
00047 point_type const& bin_sizes )
00048 {
00049 dist_tol_ = 0.0;
00050
00051 int total_size = 1;
00052 for ( unsigned i=0; i < N; ++i ) {
00053 bin_size_[i] = bin_sizes[i];
00054 min_pt_[i] = min_coord[i];
00055 size_[i] = coord_to_bin( max_coord[i], i ) + 1;
00056 assert( size_[i] > 0 );
00057 total_size *= size_[i];
00058 }
00059
00060 bins_.resize( total_size );
00061 }
00062
00063
00064 template<unsigned N, typename C, typename V>
00065 void
00066 rsdl_bins<N,C,V>::
00067 set_distance_tolerance( coord_type const& tol )
00068 {
00069 dist_tol_ = tol;
00070 }
00071
00072
00073 template<unsigned N, typename C, typename V>
00074 void
00075 rsdl_bins<N,C,V>::
00076 clear()
00077 {
00078 typedef typename vcl_vector< bin_type >::iterator vec_iter;
00079
00080 for ( vec_iter i = bins_.begin(); i != bins_.end(); ++i ) {
00081 i->clear();
00082 }
00083 }
00084
00085
00086 template<unsigned N, typename C, typename V>
00087 void
00088 rsdl_bins<N,C,V>::
00089 add_point( point_type const& pt, value_type const& val )
00090 {
00091 bins_[ bin_index( pt ) ].push_back( bin_entry_type( pt, val ) );
00092 }
00093
00094
00095 template<unsigned N, typename C, typename V>
00096 bool
00097 rsdl_bins<N,C,V>::
00098 get_value( point_type const& pt, value_type& val ) const
00099 {
00100 typedef typename bin_index_vector::iterator ind_iter;
00101 typedef typename bin_type::const_iterator entry_iter;
00102
00103 coord_type dist_tol_sqr = dist_tol_*dist_tol_;
00104
00105
00106
00107
00108 bin_index_vector indices = bin_indices( pt );
00109 for ( ind_iter bi = indices.begin(); bi != indices.end(); ++bi ) {
00110 bin_type const& bin = bins_[*bi];
00111 for ( entry_iter ei = bin.begin(); ei != bin.end(); ++ei ) {
00112 if ( ei->equal( pt, dist_tol_sqr ) ) {
00113 val = ei->value_;
00114 return true;
00115 }
00116 }
00117 }
00118
00119
00120
00121 return false;
00122 }
00123
00124
00125 template<unsigned N, typename C, typename V>
00126 void
00127 rsdl_bins<N,C,V>::
00128 n_nearest( point_type const& pt,
00129 unsigned n,
00130 vcl_vector< value_type >& values ) const
00131 {
00132 n_nearest_impl( pt, n, values, 0 );
00133 }
00134
00135
00136 template<unsigned N, typename C, typename V>
00137 void
00138 rsdl_bins<N,C,V>::
00139 n_nearest( point_type const& pt,
00140 unsigned n,
00141 vcl_vector< point_type >& points,
00142 vcl_vector< value_type >& values ) const
00143 {
00144 n_nearest_impl( pt, n, values, &points );
00145 }
00146
00147
00148 template<unsigned N, typename C, typename V>
00149 bool
00150 rsdl_bins<N,C,V>::
00151 is_any_point_within_radius( point_type const& pt,
00152 coord_type const& radius ) const
00153 {
00154
00155
00156
00157 vcl_vector< value_type > values;
00158 points_within_radius( pt, radius, values );
00159
00160 return ! values.empty();
00161 }
00162
00163
00164 template<unsigned N, typename C, typename V>
00165 void
00166 rsdl_bins<N,C,V>::
00167 points_within_radius( point_type const& pt,
00168 coord_type const& radius,
00169 vcl_vector< value_type >& values ) const
00170 {
00171 points_within_radius_impl( pt, radius, values, 0 );
00172 }
00173
00174
00175 template<unsigned N, typename C, typename V>
00176 void
00177 rsdl_bins<N,C,V>::
00178 points_within_radius( point_type const& pt,
00179 coord_type const& radius,
00180 vcl_vector< point_type >& points,
00181 vcl_vector< value_type >& values ) const
00182 {
00183 points_within_radius_impl( pt, radius, values, &points );
00184 }
00185
00186
00187 template<unsigned N, typename C, typename V>
00188 void
00189 rsdl_bins<N,C,V>::
00190 points_in_bounding_box( point_type const& min_pt,
00191 point_type const& max_pt,
00192 vcl_vector< value_type >& values ) const
00193 {
00194 points_in_bounding_box_impl( min_pt, max_pt, values, 0 );
00195 }
00196
00197
00198 template<unsigned N, typename C, typename V>
00199 void
00200 rsdl_bins<N,C,V>::
00201 points_in_bounding_box( point_type const& min_pt,
00202 point_type const& max_pt,
00203 vcl_vector< point_type >& points,
00204 vcl_vector< value_type >& values ) const
00205 {
00206 points_in_bounding_box_impl( min_pt, max_pt, values, &points );
00207 }
00208
00209
00210
00211
00212
00213 template<unsigned N, typename C, typename V>
00214 int
00215 rsdl_bins<N,C,V>::
00216 coord_to_bin( coord_type x, unsigned d ) const
00217 {
00218 return int( vcl_floor( ( x - min_pt_[d] ) / bin_size_[d] ) );
00219 }
00220
00221
00222 template<unsigned N, typename C, typename V>
00223 void
00224 rsdl_bins<N,C,V>::
00225 point_to_bin( point_type const& pt, int ind[N] ) const
00226 {
00227 for ( unsigned d=0; d < N; ++d ) {
00228 ind[d] = coord_to_bin( pt[d], d );
00229 if ( ind[d] < 0 ) {
00230 ind[d] = 0;
00231 } else if ( ind[d] >= size_[d] ) {
00232 ind[d] = size_[d] - 1;
00233 }
00234 }
00235 }
00236
00237
00238 template<unsigned N, typename C, typename V>
00239 typename rsdl_bins<N,C,V>::bin_index_type
00240 rsdl_bins<N,C,V>::
00241 bin_index( point_type const& pt ) const
00242 {
00243 bin_index_type index = 0;
00244 bin_index_type skip = 1;
00245
00246 for ( unsigned d=0; d < N; ++d ) {
00247 int i = coord_to_bin( pt[d], d );
00248 if ( i < 0 ) {
00249 i = 0;
00250 } else if ( i >= size_[d] ) {
00251 i = size_[d] - 1;
00252 }
00253 index += i*skip;
00254 skip *= size_[d];
00255 }
00256
00257 return index;
00258 }
00259
00260
00261 template<unsigned N, typename C, typename V>
00262 typename rsdl_bins<N,C,V>::bin_index_type
00263 rsdl_bins<N,C,V>::
00264 bin_index( int bin[N] ) const
00265 {
00266 bin_index_type index = 0;
00267 bin_index_type skip = 1;
00268
00269 for ( unsigned d=0; d < N; ++d ) {
00270 assert( 0 <= bin[d] && bin[d] < size_[d] );
00271 index += bin[d]*skip;
00272 skip *= size_[d];
00273 }
00274
00275 return index;
00276 }
00277
00278
00279 template<unsigned N, typename C, typename V>
00280 typename rsdl_bins<N,C,V>::bin_index_vector
00281 rsdl_bins<N,C,V>::
00282 bin_indices( point_type const& pt ) const
00283 {
00284 bin_index_vector indices;
00285
00286 int bin_lo[N], bin_hi[N];
00287 point_to_bin( pt-dist_tol_, bin_lo );
00288 point_to_bin( pt+dist_tol_, bin_hi );
00289
00290 if ( bin_lo == bin_hi ) {
00291 indices.push_back( bin_index( bin_lo ) );
00292 } else {
00293 int cur[N];
00294 scan_region( bin_lo, bin_hi, cur, 0, indices );
00295 }
00296
00297 return indices;
00298 }
00299
00300
00301 template<unsigned N, typename C, typename V>
00302 void
00303 rsdl_bins<N,C,V>::
00304 n_nearest_impl( point_type const& pt,
00305 unsigned n,
00306 vcl_vector< value_type >& values,
00307 vcl_vector< point_type >* points ) const
00308 {
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332 static bool rsdl_bins_bug_warning_s = false;
00333 if( rsdl_bins_bug_warning_s ) {
00334 vcl_cerr << "Warning: results from current rsdl_bins<N,C,V>::n_nearest_impl"
00335 << "may be inaccurate. Please contact developers for details. " << vcl_endl;
00336 rsdl_bins_bug_warning_s = false;
00337 }
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348 bin_index_vector indices;
00349
00350
00351 int bin_lo[N], bin_hi[N], cur[N];
00352
00353 point_to_bin( pt, bin_lo );
00354 for (unsigned int i=0; i<N; ++i) bin_hi[i] = bin_lo[i];
00355
00356 bool still_looking = true;
00357 unsigned found = 0;
00358 do {
00359 found += scan_bdy( bin_lo, bin_hi, cur, 0, indices );
00360 if ( found >= n ) {
00361
00362
00363
00364
00365 unsigned k = (bin_hi[0] - bin_lo[0]) / 2;
00366
00367 unsigned f = unsigned( vcl_ceil( double(k+1) * vcl_sqrt(double(N)) - double(k) ) );
00368 for (unsigned j=0; j<f; ++j) {
00369 for (unsigned i=0; i<N; ++i) {
00370
00371 --bin_lo[i];
00372 ++bin_hi[i];
00373 }
00374 found += scan_bdy( bin_lo, bin_hi, cur, 0, indices );
00375 }
00376 still_looking = false;
00377 } else {
00378 bool some_dimension_in_bounds = false;
00379 for ( unsigned i=0; i < N; ++i ) {
00380 --bin_lo[i];
00381 ++bin_hi[i];
00382 if ( bin_lo[i] >= 0 || bin_hi[i] < size_[i] )
00383 some_dimension_in_bounds = true;
00384 }
00385
00386 if ( !some_dimension_in_bounds ) {
00387 still_looking = false;
00388 }
00389 }
00390 } while ( still_looking );
00391
00392
00393
00394
00395 typedef typename bin_index_vector::iterator ind_iter;
00396 typedef typename bin_type::const_iterator entry_iter;
00397
00398 vcl_vector< point_dist_entry > distances;
00399
00400 for ( ind_iter bi = indices.begin(); bi != indices.end(); ++bi ) {
00401 bin_type const& bin = bins_[*bi];
00402 for ( entry_iter ei = bin.begin(); ei != bin.end(); ++ei ) {
00403 distances.push_back( point_dist_entry( pt, &(*ei) ) );
00404 }
00405 }
00406
00407
00408
00409
00410 typedef typename vcl_vector< point_dist_entry >::iterator point_dist_iter;
00411
00412 point_dist_iter mid;
00413 if ( distances.size() > n ) {
00414 mid = distances.begin() + n;
00415 vcl_partial_sort( distances.begin(), mid, distances.end() );
00416 } else {
00417 mid = distances.end();
00418 }
00419
00420 #define support_points_outside_boundaries 0
00421 #if support_points_outside_boundaries
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432 double longest_distance = vcl_sqrt(double((mid-1)->dist_));
00433
00434
00435 double r = ((bin_hi[0] - bin_lo[0]) / 2) * bin_size_[0];
00436
00437
00438 if (longest_distance > r) {
00439 unsigned reg_incr = unsigned(vcl_ceil(longest_distance / bin_size_[0] - (bin_hi[0] - bin_lo[0])/2));
00440 for (unsigned j=0; j<reg_incr; ++j) {
00441 for (unsigned i=0; i<N; ++i) {
00442
00443 --bin_lo[i];
00444 ++bin_hi[i];
00445 }
00446 found += scan_bdy( bin_lo, bin_hi, cur, 0, indices );
00447 }
00448
00449 distances.clear();
00450 for ( ind_iter bi = indices.begin(); bi != indices.end(); ++bi ) {
00451 bin_type const& bin = bins_[*bi];
00452 for ( entry_iter ei = bin.begin(); ei != bin.end(); ++ei ) {
00453 distances.push_back( point_dist_entry( pt, &(*ei) ) );
00454 }
00455 }
00456
00457 if ( distances.size() > n ) {
00458 mid = distances.begin() + n;
00459 vcl_partial_sort( distances.begin(), mid, distances.end() );
00460 }
00461 else {
00462 mid = distances.end();
00463 }
00464 }
00465
00466 #endif // end of support points outside region boundaries logic
00467
00468 for ( point_dist_iter i = distances.begin(); i != mid; ++i ) {
00469 values.push_back( i->entry_->value_ );
00470 if ( points ) {
00471 points->push_back( i->entry_->point_ );
00472 }
00473 }
00474 }
00475
00476
00477 template<unsigned N, typename C, typename V>
00478 void
00479 rsdl_bins<N,C,V>::
00480 points_within_radius_impl( point_type const& pt,
00481 coord_type const& radius,
00482 vcl_vector< value_type >& values,
00483 vcl_vector< point_type >* points ) const
00484 {
00485
00486
00487
00488
00489
00490
00491 bin_index_vector indices;
00492
00493
00494 int bin_lo[N], bin_hi[N], cur[N];
00495
00496 point_to_bin( pt-radius, bin_lo );
00497 point_to_bin( pt+radius, bin_hi );
00498
00499 scan_region( bin_lo, bin_hi, cur, 0, indices );
00500
00501
00502
00503
00504 typedef typename bin_index_vector::iterator ind_iter;
00505 typedef typename bin_type::const_iterator entry_iter;
00506
00507 vcl_vector< point_dist_entry > distances;
00508
00509 coord_type rad_sqr = radius * radius;
00510 for ( ind_iter bi = indices.begin(); bi != indices.end(); ++bi ) {
00511 bin_type const& bin = bins_[*bi];
00512 for ( entry_iter ei = bin.begin(); ei != bin.end(); ++ei ) {
00513 coord_type dist_sqr = vnl_vector_ssd( pt, ei->point_ );
00514 if ( dist_sqr < rad_sqr ) {
00515 values.push_back( ei->value_ );
00516 if ( points ) {
00517 points->push_back( ei->point_ );
00518 }
00519 }
00520 }
00521 }
00522 }
00523
00524
00525 template<unsigned N, typename C, typename V>
00526 void
00527 rsdl_bins<N,C,V>::
00528 points_in_bounding_box_impl( point_type const& min_pt,
00529 point_type const& max_pt,
00530 vcl_vector< value_type >& values,
00531 vcl_vector< point_type >* points ) const
00532 {
00533
00534
00535
00536
00537
00538 bin_index_vector indices;
00539
00540
00541 int bin_lo[N], bin_hi[N], cur[N];
00542
00543 point_to_bin( min_pt, bin_lo );
00544 point_to_bin( max_pt, bin_hi );
00545
00546 scan_region( bin_lo, bin_hi, cur, 0, indices );
00547
00548
00549
00550
00551 typedef typename bin_index_vector::iterator ind_iter;
00552 typedef typename bin_type::const_iterator entry_iter;
00553
00554 vcl_vector< point_dist_entry > distances;
00555
00556 for ( ind_iter bi = indices.begin(); bi != indices.end(); ++bi ) {
00557 bin_type const& bin = bins_[*bi];
00558 for ( entry_iter ei = bin.begin(); ei != bin.end(); ++ei ) {
00559 bool in_range = true;
00560 for ( unsigned d=0; d < N; ++d ) {
00561 if ( ei->point_[d] < min_pt[d] || ei->point_[d] > max_pt[d] ) {
00562 in_range = false;
00563 break;
00564 }
00565 }
00566 if ( in_range ) {
00567 values.push_back( ei->value_ );
00568 if ( points ) {
00569 points->push_back( ei->point_ );
00570 }
00571 }
00572 }
00573 }
00574 }
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600 template<unsigned N, typename C, typename V>
00601 unsigned
00602 rsdl_bins<N,C,V>::
00603 scan_region( int lo[N], int hi[N], int cur[N], unsigned dim,
00604 bin_index_vector& indices ) const
00605 {
00606 unsigned found = 0;
00607
00608 if ( dim==N ) {
00609
00610 bin_index_type ind = bin_index( cur );
00611 indices.push_back( ind );
00612 found = bins_[ind].size();
00613 } else {
00614 int bx = vcl_max( lo[dim], 0 );
00615 int ex = vcl_min( hi[dim]+1, size_[dim] );
00616 for ( int x=bx; x < ex; ++x ) {
00617 cur[dim] = x;
00618 found += scan_region( lo, hi, cur, dim+1, indices );
00619 }
00620 }
00621
00622 return found;
00623 }
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642 template<unsigned N, typename C, typename V>
00643 unsigned
00644 rsdl_bins<N,C,V>::
00645 scan_bdy( int lo[N], int hi[N], int cur[N], unsigned dim,
00646 bin_index_vector& indices ) const
00647 {
00648 unsigned found = 0;
00649
00650
00651
00652
00653 if ( dim < N ) {
00654 int bx = vcl_max( lo[dim], 0 );
00655 int ex = vcl_min( hi[dim]+1, size_[dim] );
00656 int x = bx;
00657 if ( x==lo[dim] ) {
00658 cur[dim] = x;
00659 found += scan_region( lo, hi, cur, dim+1, indices );
00660 ++x;
00661 }
00662 for ( ; x < ex-1; ++x ) {
00663 cur[dim] = x;
00664 found += scan_bdy( lo, hi, cur, dim+1, indices );
00665 }
00666 if ( x==hi[dim] ) {
00667 cur[dim] = x;
00668 found += scan_region( lo, hi, cur, dim+1, indices );
00669 }
00670 }
00671
00672 return found;
00673 }
00674
00675
00676
00677
00678
00679
00680
00681 template<unsigned N, typename C, typename V>
00682 rsdl_bins_bin_entry_type<N,C,V>::
00683 rsdl_bins_bin_entry_type( point_type const& pt, const value_type val )
00684 : point_( pt ),
00685 value_( val )
00686 {
00687 }
00688
00689 template<unsigned N, typename C, typename V>
00690 bool
00691 rsdl_bins_bin_entry_type<N,C,V>::
00692 equal( point_type const& pt, double tol_sqr ) const
00693 {
00694 return vnl_vector_ssd( pt, point_ ) < tol_sqr;
00695 }
00696
00697
00698
00699
00700
00701
00702 template<unsigned N, typename C, typename V>
00703 rsdl_bins_point_dist_entry<N,C,V>::
00704 rsdl_bins_point_dist_entry( point_type const& query_pt,
00705 bin_entry_type const* entry )
00706 : entry_( entry ),
00707 dist_( vnl_vector_ssd( query_pt, entry->point_ ) )
00708 {
00709 }
00710
00711
00712 template<unsigned N, typename C, typename V>
00713 bool
00714 rsdl_bins_point_dist_entry<N,C,V>::
00715 operator<( rsdl_bins_point_dist_entry const& other ) const
00716 {
00717 return this->dist_ < other.dist_;
00718 }
00719
00720 #define INSTANTIATE_RSDL_BINS( n, V, C ) \
00721 template class rsdl_bins< n, V, C >; \
00722 template struct rsdl_bins_bin_entry_type< n, V, C >; \
00723 template struct rsdl_bins_point_dist_entry< n, V, C >
00724
00725 #endif // rsdl_bins_txx_