00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef OPENMS_MATH_MISC_BILINEARINTERPOLATION_H
00028 #define OPENMS_MATH_MISC_BILINEARINTERPOLATION_H
00029
00030 #include <OpenMS/DATASTRUCTURES/Matrix.h>
00031
00032 namespace OpenMS
00033 {
00034
00035 namespace Math
00036 {
00037
00064 template < typename Key = double, typename Value = Key >
00065 class BilinearInterpolation
00066 {
00067
00068 public:
00069
00071
00072 typedef Value value_type;
00073
00074 typedef Key key_type;
00075 typedef Matrix < value_type > container_type;
00076
00077 typedef value_type ValueType;
00078 typedef key_type KeyType;
00079 typedef container_type ContainerType;
00081
00082 public:
00083
00087
00089 BilinearInterpolation ()
00090 : scale_0_ (1),
00091 offset_0_ (0),
00092 scale_1_ (1),
00093 offset_1_ (0),
00094 inside_0_ (0),
00095 outside_0_ (0),
00096 inside_1_ (0),
00097 outside_1_ (0),
00098 data_ ()
00099 {}
00100
00102 BilinearInterpolation ( BilinearInterpolation const & arg )
00103 : scale_0_ ( arg.scale_0_ ),
00104 offset_0_ ( arg.offset_0_ ),
00105 scale_1_ ( arg.scale_1_ ),
00106 offset_1_ ( arg.offset_1_ ),
00107 inside_0_ ( arg.inside_0_ ),
00108 outside_0_ ( arg.outside_0_ ),
00109 inside_1_ ( arg.inside_1_ ),
00110 outside_1_ ( arg.outside_1_ ),
00111 data_ ( arg.data_ )
00112 {}
00113
00115 BilinearInterpolation & operator= ( BilinearInterpolation const & arg )
00116 {
00117 if ( &arg == this )
00118 return * this;
00119 scale_0_ = arg.scale_0_;
00120 offset_0_ = arg.offset_0_;
00121 scale_1_ = arg.scale_1_;
00122 offset_1_ = arg.offset_1_;
00123 inside_0_ = arg.inside_0_;
00124 outside_1_ = arg.outside_1_;
00125 inside_1_ = arg.inside_1_;
00126 outside_0_ = arg.outside_0_;
00127 data_ = arg.data_;
00128 return *this;
00129 }
00130
00132 ~BilinearInterpolation ()
00133 {}
00134
00136
00137
00138
00140
00141
00143 ValueType value ( KeyType arg_pos_0, KeyType arg_pos_1 ) const
00144 {
00145
00146 KeyType const pos_0 = key2index_0( arg_pos_0 );
00147 KeyType const pos_1 = key2index_1( arg_pos_1 );
00148
00149
00150
00151
00152 int const size_0 = data_.rows();
00153 int const lower_0 = int( pos_0 );
00154 int const size_1 = data_.cols();
00155 int const lower_1 = int( pos_1 );
00156
00157
00158 if ( pos_0 <= 0 )
00159 {
00160 if ( lower_0 != 0 )
00161 {
00162 return 0;
00163 }
00164 else
00165 {
00166
00167
00168 if ( pos_1 <= 0 )
00169 {
00170 if ( lower_1 != 0 )
00171 {
00172 return 0;
00173 }
00174 else
00175 {
00176 return data_( 0, 0 ) * ( 1. + pos_0 ) * ( 1. + pos_1 ) ;
00177 }
00178 }
00179
00180
00181 if ( lower_1 >= size_1 - 1 )
00182 {
00183 if ( lower_1 != size_1 - 1 )
00184 {
00185 return 0;
00186 }
00187 else
00188 {
00189 return data_ ( 0, lower_1 ) * ( 1. + pos_0 ) * ( size_1 - pos_1 );
00190 }
00191 }
00192
00193
00194 KeyType const factor_1 = pos_1 - KeyType( lower_1 );
00195 KeyType const factor_1_complement = 1. - factor_1;
00196 return
00197 (
00198 data_ ( 0, lower_1 + 1 ) * factor_1 +
00199 data_ ( 0, lower_1 ) * factor_1_complement
00200 ) * ( 1. + pos_0 );
00201 }
00202 }
00203
00204
00205 if ( lower_0 >= size_0 - 1 )
00206 {
00207 if ( lower_0 != size_0 - 1 )
00208 {
00209 return 0;
00210 }
00211 else
00212 {
00213
00214
00215 if ( pos_1 <= 0 )
00216 {
00217 if ( lower_1 != 0 )
00218 {
00219 return 0;
00220 }
00221 else
00222 {
00223 return data_( lower_0, 0 ) * ( size_0 - pos_0 ) * ( 1. + pos_1 ) ;
00224 }
00225 }
00226
00227
00228 if ( lower_1 >= size_1 - 1 )
00229 {
00230 if ( lower_1 != size_1 - 1 )
00231 {
00232 return 0;
00233 }
00234 else
00235 {
00236 return data_ ( lower_0, lower_1 ) * ( size_0 - pos_0 ) * ( size_1 - pos_1 );
00237 }
00238 }
00239
00240
00241 KeyType const factor_1 = pos_1 - KeyType( lower_1 );
00242 KeyType const factor_1_complement = 1. - factor_1;
00243 return
00244 (
00245 data_ ( lower_0, lower_1 + 1 ) * factor_1 +
00246 data_ ( lower_0, lower_1 ) * factor_1_complement
00247 )
00248 * ( size_0 - pos_0 );
00249 }
00250 }
00251
00252
00253 {
00254 KeyType const factor_0 = pos_0 - KeyType( lower_0 );
00255 KeyType const factor_0_complement = 1. - factor_0;
00256
00257
00258 if ( pos_1 <= 0 )
00259 {
00260 if ( lower_1 != 0 )
00261 {
00262 return 0;
00263 }
00264 else
00265 {
00266 return
00267 (
00268 data_( lower_0 + 1, 0 ) * factor_0
00269 +
00270 data_( lower_0, 0 ) * factor_0_complement
00271 )
00272 * ( 1. + pos_1 ) ;
00273 }
00274 }
00275
00276
00277 if ( lower_1 >= size_1 - 1 )
00278 {
00279 if ( lower_1 != size_1 - 1 )
00280 {
00281 return 0;
00282 }
00283 else
00284 {
00285 return
00286 (
00287 data_( lower_0 + 1, lower_1 ) * factor_0
00288 +
00289 data_( lower_0, lower_1 ) * factor_0_complement
00290 )
00291 * ( size_1 - pos_1 );
00292 }
00293 }
00294 KeyType const factor_1 = pos_1 - KeyType( lower_1 );
00295 KeyType const factor_1_complement = 1. - factor_1;
00296
00297
00298 return
00299 (
00300 data_( lower_0 + 1, lower_1 + 1 ) * factor_0
00301 +
00302 data_( lower_0, lower_1 + 1 ) * factor_0_complement
00303 )
00304 * factor_1
00305 +
00306 (
00307 data_( lower_0 + 1, lower_1 ) * factor_0
00308 +
00309 data_( lower_0, lower_1 ) * factor_0_complement
00310 )
00311 * factor_1_complement;
00312 }
00313 }
00314
00318 void addValue ( KeyType arg_pos_0, KeyType arg_pos_1, ValueType arg_value )
00319 {
00320
00321 typedef typename container_type::difference_type DiffType;
00322
00323
00324 KeyType const pos_0 = key2index_0( arg_pos_0 );
00325 KeyType lower_0_key;
00326 KeyType const frac_0 = std::modf( pos_0, &lower_0_key );
00327 DiffType const lower_0 = DiffType( lower_0_key );
00328
00329
00330 if ( pos_0 < 0 )
00331 {
00332 if ( lower_0 )
00333 {
00334 return ;
00335 }
00336 else
00337 {
00338
00339
00340 KeyType const pos_1 = key2index_1( arg_pos_1 );
00341 KeyType lower_1_key;
00342 KeyType const frac_1 = std::modf( pos_1, &lower_1_key );
00343 DiffType const lower_1 = DiffType( lower_1_key );
00344
00345
00346 if ( pos_1 < 0 )
00347 {
00348 if ( lower_1 )
00349 {
00350 return ;
00351 }
00352 else
00353 {
00354 data_( 0, 0 ) += arg_value * ( 1 + frac_0 ) * ( 1 + frac_1 );
00355 return ;
00356 }
00357 }
00358 else
00359 {
00360 DiffType const back_1 = data_.cols() - 1;
00361
00362 if ( lower_1 >= back_1 )
00363 {
00364 if ( lower_1 != back_1 )
00365 {
00366 return ;
00367 }
00368 else
00369 {
00370 data_ ( 0, lower_1 ) += arg_value * ( 1 + frac_0 ) * ( 1 - frac_1 );
00371 return ;
00372 }
00373 }
00374 else
00375 {
00376
00377 KeyType const tmp_prod = arg_value * ( 1 + frac_0 );
00378 data_ ( 0, lower_1 + 1 ) += tmp_prod * frac_1;
00379 data_ ( 0, lower_1 ) += tmp_prod * ( 1 - frac_1 );
00380 return ;
00381 }
00382 }
00383 }
00384 }
00385 else
00386 {
00387 DiffType const back_0 = data_.rows() - 1;
00388 if ( lower_0 >= back_0 )
00389 {
00390 if ( lower_0 != back_0 )
00391 {
00392 return ;
00393 }
00394 else
00395 {
00396
00397 KeyType const tmp_prod = arg_value * ( 1 - frac_0 );
00398
00399
00400 KeyType const pos_1 = key2index_1( arg_pos_1 );
00401 KeyType lower_1_key;
00402 KeyType const frac_1 = std::modf( pos_1, &lower_1_key );
00403 DiffType const lower_1 = DiffType( lower_1_key );
00404
00405
00406 if ( pos_1 < 0 )
00407 {
00408 if ( lower_1 )
00409 {
00410 return ;
00411 }
00412 else
00413 {
00414 data_( lower_0, 0 ) += tmp_prod * ( 1 + frac_1 );
00415 return ;
00416 }
00417 }
00418 else
00419 {
00420 DiffType const back_1 = data_.cols() - 1;
00421
00422 if ( lower_1 >= back_1 )
00423 {
00424 if ( lower_1 != back_1 )
00425 {
00426 return ;
00427 }
00428 else
00429 {
00430 data_ ( lower_0, lower_1 ) += tmp_prod * ( 1 - frac_1 );
00431 return ;
00432 }
00433 }
00434 else
00435 {
00436
00437 data_ ( lower_0, lower_1 + 1 ) += tmp_prod * frac_1;
00438 data_ ( lower_0, lower_1 ) += tmp_prod * ( 1 - frac_1 );
00439 return ;
00440 }
00441 }
00442 }
00443 }
00444 else
00445 {
00446
00447
00448
00449
00450 KeyType const pos_1 = key2index_1( arg_pos_1 );
00451 KeyType lower_1_key;
00452 KeyType const frac_1 = std::modf( pos_1, &lower_1_key );
00453 DiffType const lower_1 = DiffType( lower_1_key );
00454
00455
00456 if ( pos_1 < 0 )
00457 {
00458 if ( lower_1 )
00459 {
00460 return ;
00461 }
00462 else
00463 {
00464 KeyType const tmp_prod = arg_value * ( 1 + frac_1 );
00465 data_( lower_0 + 1, 0 ) += tmp_prod * frac_0;
00466 data_( lower_0, 0 ) += tmp_prod * ( 1 - frac_0 );
00467 return ;
00468 }
00469 }
00470 else
00471 {
00472 DiffType const back_1 = data_.cols() - 1;
00473
00474 if ( lower_1 >= back_1 )
00475 {
00476 if ( lower_1 != back_1 )
00477 {
00478 return ;
00479 }
00480 else
00481 {
00482 KeyType const tmp_prod = arg_value * ( 1 - frac_1 );
00483 data_ ( lower_0 + 1, lower_1 ) += tmp_prod * frac_0;
00484 data_ ( lower_0, lower_1 ) += tmp_prod * ( 1 - frac_0 );
00485 return ;
00486 }
00487 }
00488 else
00489 {
00490
00491
00492
00493 KeyType tmp_prod = arg_value * frac_0;
00494 data_( lower_0 + 1, lower_1 + 1 ) += tmp_prod * frac_1;
00495 data_( lower_0 + 1, lower_1 ) += tmp_prod * ( 1 - frac_1 );
00496 tmp_prod = arg_value * ( 1 - frac_0 );
00497 data_( lower_0, lower_1 + 1 ) += tmp_prod * frac_1;
00498 data_( lower_0, lower_1 ) += tmp_prod * ( 1 - frac_1 );
00499 return ;
00500 }
00501 }
00502 }
00503 }
00504 }
00505
00507
00508
00509
00511
00512
00514 ContainerType & getData ()
00515 {
00516 return data_;
00517 }
00518
00520 ContainerType const & getData () const
00521 {
00522 return data_;
00523 }
00524
00530 template < typename SourceContainer >
00531 void setData ( SourceContainer const & data )
00532 {
00533 data_ = data;
00534 }
00535
00536
00538 bool empty () const
00539 {
00540 return data_.empty();
00541 }
00542
00544
00545
00546
00548
00549
00551 KeyType key2index_0 ( KeyType pos ) const
00552 {
00553 if ( scale_0_ )
00554 {
00555 pos -= offset_0_;
00556 pos /= scale_0_;
00557 return pos;
00558 }
00559 else
00560 {
00561 return 0;
00562 }
00563 }
00564
00566 KeyType index2key_0 ( KeyType pos ) const
00567 {
00568 pos *= scale_0_;
00569 pos += offset_0_;
00570 return pos;
00571 }
00572
00574 KeyType key2index_1 ( KeyType pos ) const
00575 {
00576 if ( scale_1_ )
00577 {
00578 pos -= offset_1_;
00579 pos /= scale_1_;
00580 return pos;
00581 }
00582 else
00583 {
00584 return 0;
00585 }
00586 }
00587
00589 KeyType index2key_1 ( KeyType pos ) const
00590 {
00591 pos *= scale_1_;
00592 pos += offset_1_;
00593 return pos;
00594 }
00595
00597 KeyType const & getScale_0 () const
00598 {
00599 return scale_0_;
00600 }
00601
00603 KeyType const & getScale_1 () const
00604 {
00605 return scale_1_;
00606 }
00607
00613 void setScale_0 ( KeyType const & scale )
00614 {
00615 scale_0_ = scale;
00616 }
00617
00623 void setScale_1 ( KeyType const & scale )
00624 {
00625 scale_1_ = scale;
00626 }
00627
00629 KeyType const & getOffset_0 () const
00630 {
00631 return offset_0_;
00632 }
00633
00635 KeyType const & getOffset_1 () const
00636 {
00637 return offset_1_;
00638 }
00639
00646 void setOffset_0 ( KeyType const & offset )
00647 {
00648 offset_0_ = offset;
00649 }
00650
00657 void setOffset_1 ( KeyType const & offset )
00658 {
00659 offset_1_ = offset;
00660 }
00661
00675 void setMapping_0 ( KeyType const & scale, KeyType const & inside_low, KeyType const & outside_low )
00676 {
00677 scale_0_ = scale;
00678 inside_0_ = inside_low;
00679 outside_0_ = outside_low;
00680 offset_0_ = outside_low - scale * inside_low;
00681 return ;
00682 }
00683
00690 void setMapping_0 ( KeyType const & inside_low, KeyType const & outside_low,
00691 KeyType const & inside_high, KeyType const & outside_high )
00692 {
00693 if ( inside_high != inside_low )
00694 {
00695 setMapping_0 ( ( outside_high - outside_low ) / ( inside_high - inside_low ),
00696 inside_low, outside_low );
00697 }
00698 else
00699 {
00700 setMapping_0 ( 0, inside_low, outside_low );
00701 }
00702 return;
00703 }
00704
00718 void setMapping_1 ( KeyType const & scale, KeyType const & inside_low, KeyType const & outside_low )
00719 {
00720 scale_1_ = scale;
00721 inside_1_ = inside_low;
00722 outside_1_ = outside_low;
00723 offset_1_ = outside_low - scale * inside_low;
00724 return ;
00725 }
00726
00733 void setMapping_1 ( KeyType const & inside_low, KeyType const & outside_low,
00734 KeyType const & inside_high, KeyType const & outside_high )
00735 {
00736 if ( inside_high != inside_low )
00737 {
00738 setMapping_1 ( ( outside_high - outside_low ) / ( inside_high - inside_low ),
00739 inside_low, outside_low );
00740 }
00741 else
00742 {
00743 setMapping_1 ( 0, inside_low, outside_low );
00744 }
00745 return;
00746 }
00747
00749 KeyType const & getInsideReferencePoint_0 () const
00750 {
00751 return inside_0_;
00752 }
00753
00755 KeyType const & getInsideReferencePoint_1 () const
00756 {
00757 return inside_1_;
00758 }
00759
00761 KeyType const & getOutsideReferencePoint_0 () const
00762 {
00763 return outside_0_;
00764 }
00765
00767 KeyType const & getOutsideReferencePoint_1 () const
00768 {
00769 return outside_1_;
00770 }
00771
00773 KeyType supportMin_0() const
00774 {
00775 return index2key_0 ( empty() ? 0 : -1 );
00776 }
00777
00779 KeyType supportMin_1() const
00780 {
00781 return index2key_1 ( empty() ? 0 : -1 );
00782 }
00783
00785 KeyType supportMax_0() const
00786 {
00787 return index2key_0 ( data_.rows() );
00788 }
00789
00791 KeyType supportMax_1() const
00792 {
00793 return index2key_1 ( data_.cols() );
00794 }
00795
00797
00798 protected:
00799
00802 KeyType scale_0_;
00803 KeyType offset_0_;
00804 KeyType scale_1_;
00805 KeyType offset_1_;
00806 KeyType inside_0_;
00807 KeyType outside_0_;
00808 KeyType inside_1_;
00809 KeyType outside_1_;
00810 ContainerType data_;
00812 };
00813
00814 }
00815
00816 }
00817
00818 #endif // OPENMS_MATH_MISC_BILINEARINTERPOLATION_H