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
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef OPENMS_MATH_MISC_BILINEARINTERPOLATION_H
00036 #define OPENMS_MATH_MISC_BILINEARINTERPOLATION_H
00037
00038 #include <OpenMS/DATASTRUCTURES/Matrix.h>
00039
00040 namespace OpenMS
00041 {
00042
00043 namespace Math
00044 {
00045
00072 template <typename Key = double, typename Value = Key>
00073 class BilinearInterpolation
00074 {
00075
00076 public:
00077
00079
00080 typedef Value value_type;
00081
00082 typedef Key key_type;
00083 typedef Matrix<value_type> container_type;
00084
00085 typedef value_type ValueType;
00086 typedef key_type KeyType;
00087 typedef container_type ContainerType;
00089
00090 public:
00091
00095
00097 BilinearInterpolation() :
00098 scale_0_(1),
00099 offset_0_(0),
00100 scale_1_(1),
00101 offset_1_(0),
00102 inside_0_(0),
00103 outside_0_(0),
00104 inside_1_(0),
00105 outside_1_(0),
00106 data_()
00107 {}
00108
00110 BilinearInterpolation(BilinearInterpolation const & arg) :
00111 scale_0_(arg.scale_0_),
00112 offset_0_(arg.offset_0_),
00113 scale_1_(arg.scale_1_),
00114 offset_1_(arg.offset_1_),
00115 inside_0_(arg.inside_0_),
00116 outside_0_(arg.outside_0_),
00117 inside_1_(arg.inside_1_),
00118 outside_1_(arg.outside_1_),
00119 data_(arg.data_)
00120 {}
00121
00123 BilinearInterpolation & operator=(BilinearInterpolation const & arg)
00124 {
00125 if (&arg == this)
00126 return *this;
00127
00128 scale_0_ = arg.scale_0_;
00129 offset_0_ = arg.offset_0_;
00130 scale_1_ = arg.scale_1_;
00131 offset_1_ = arg.offset_1_;
00132 inside_0_ = arg.inside_0_;
00133 outside_1_ = arg.outside_1_;
00134 inside_1_ = arg.inside_1_;
00135 outside_0_ = arg.outside_0_;
00136 data_ = arg.data_;
00137 return *this;
00138 }
00139
00141 ~BilinearInterpolation()
00142 {}
00143
00145
00146
00147
00149
00150
00152 ValueType value(KeyType arg_pos_0, KeyType arg_pos_1) const
00153 {
00154
00155 KeyType const pos_0 = key2index_0(arg_pos_0);
00156 KeyType const pos_1 = key2index_1(arg_pos_1);
00157
00158
00159
00160 SignedSize const size_0 = data_.rows();
00161 SignedSize const lower_0 = SignedSize(pos_0);
00162 SignedSize const size_1 = data_.cols();
00163 SignedSize const lower_1 = SignedSize(pos_1);
00164
00165
00166 if (pos_0 <= 0)
00167 {
00168 if (lower_0 != 0)
00169 {
00170 return 0;
00171 }
00172 else
00173 {
00174 if (pos_1 <= 0)
00175 {
00176 if (lower_1 != 0)
00177 {
00178 return 0;
00179 }
00180 else
00181 {
00182 return data_(0, 0) * (1. + pos_0) * (1. + pos_1);
00183 }
00184 }
00185
00186
00187 if (lower_1 >= size_1 - 1)
00188 {
00189 if (lower_1 != size_1 - 1)
00190 {
00191 return 0;
00192 }
00193 else
00194 {
00195 return data_(0, lower_1) * (1. + pos_0) * (size_1 - pos_1);
00196 }
00197 }
00198
00199
00200 KeyType const factor_1 = pos_1 - KeyType(lower_1);
00201 KeyType const factor_1_complement = KeyType(1.) - factor_1;
00202 return (
00203 data_(0, lower_1 + 1) * factor_1 +
00204 data_(0, lower_1) * factor_1_complement
00205 ) * (1. + pos_0);
00206 }
00207 }
00208
00209
00210 if (lower_0 >= size_0 - 1)
00211 {
00212 if (lower_0 != size_0 - 1)
00213 {
00214 return 0;
00215 }
00216 else
00217 {
00218 if (pos_1 <= 0)
00219 {
00220 if (lower_1 != 0)
00221 {
00222 return 0;
00223 }
00224 else
00225 {
00226 return data_(lower_0, 0) * (size_0 - pos_0) * (1. + pos_1);
00227 }
00228 }
00229
00230
00231 if (lower_1 >= size_1 - 1)
00232 {
00233 if (lower_1 != size_1 - 1)
00234 {
00235 return 0;
00236 }
00237 else
00238 {
00239 return data_(lower_0, lower_1) * (size_0 - pos_0) * (size_1 - pos_1);
00240 }
00241 }
00242
00243
00244 KeyType const factor_1 = pos_1 - KeyType(lower_1);
00245 KeyType const factor_1_complement = KeyType(1.) - factor_1;
00246 return (
00247 data_(lower_0, lower_1 + 1) * factor_1 +
00248 data_(lower_0, lower_1) * factor_1_complement
00249 )
00250 * (size_0 - pos_0);
00251 }
00252 }
00253
00254
00255 {
00256 KeyType const factor_0 = pos_0 - KeyType(lower_0);
00257 KeyType const factor_0_complement = KeyType(1.) - factor_0;
00258
00259
00260 if (pos_1 <= 0)
00261 {
00262 if (lower_1 != 0)
00263 {
00264 return 0;
00265 }
00266 else
00267 {
00268 return (
00269 data_(lower_0 + 1, 0) * factor_0
00270 +
00271 data_(lower_0, 0) * factor_0_complement
00272 )
00273 * (1. + pos_1);
00274 }
00275 }
00276
00277
00278 if (lower_1 >= size_1 - 1)
00279 {
00280 if (lower_1 != size_1 - 1)
00281 {
00282 return 0;
00283 }
00284 else
00285 {
00286 return (
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 = KeyType(1.) - factor_1;
00296
00297
00298 return (
00299 data_(lower_0 + 1, lower_1 + 1) * factor_0
00300 +
00301 data_(lower_0, lower_1 + 1) * factor_0_complement
00302 )
00303 * factor_1
00304 +
00305 (
00306 data_(lower_0 + 1, lower_1) * factor_0
00307 +
00308 data_(lower_0, lower_1) * factor_0_complement
00309 )
00310 * factor_1_complement;
00311 }
00312 }
00313
00317 void addValue(KeyType arg_pos_0, KeyType arg_pos_1, ValueType arg_value)
00318 {
00319
00320 typedef typename container_type::difference_type DiffType;
00321
00322
00323 KeyType const pos_0 = key2index_0(arg_pos_0);
00324 KeyType lower_0_key;
00325 KeyType const frac_0 = std::modf(pos_0, &lower_0_key);
00326 DiffType const lower_0 = DiffType(lower_0_key);
00327
00328
00329 if (pos_0 < 0)
00330 {
00331 if (lower_0)
00332 {
00333 return;
00334 }
00335 else
00336 {
00337 KeyType const pos_1 = key2index_1(arg_pos_1);
00338 KeyType lower_1_key;
00339 KeyType const frac_1 = std::modf(pos_1, &lower_1_key);
00340 DiffType const lower_1 = DiffType(lower_1_key);
00341
00342
00343 if (pos_1 < 0)
00344 {
00345 if (lower_1)
00346 {
00347 return;
00348 }
00349 else
00350 {
00351 data_(0, 0) += arg_value * (1 + frac_0) * (1 + frac_1);
00352 return;
00353 }
00354 }
00355 else
00356 {
00357 DiffType const back_1 = data_.cols() - 1;
00358
00359 if (lower_1 >= back_1)
00360 {
00361 if (lower_1 != back_1)
00362 {
00363 return;
00364 }
00365 else
00366 {
00367 data_(0, lower_1) += arg_value * (1 + frac_0) * (1 - frac_1);
00368 return;
00369 }
00370 }
00371 else
00372 {
00373
00374 KeyType const tmp_prod = KeyType(arg_value * (1. + frac_0));
00375 data_(0, lower_1 + 1) += tmp_prod * frac_1;
00376 data_(0, lower_1) += tmp_prod * (1. - frac_1);
00377 return;
00378 }
00379 }
00380 }
00381 }
00382 else
00383 {
00384 DiffType const back_0 = data_.rows() - 1;
00385 if (lower_0 >= back_0)
00386 {
00387 if (lower_0 != back_0)
00388 {
00389 return;
00390 }
00391 else
00392 {
00393
00394 KeyType const tmp_prod = KeyType(arg_value * (1. - frac_0));
00395
00396
00397 KeyType const pos_1 = key2index_1(arg_pos_1);
00398 KeyType lower_1_key;
00399 KeyType const frac_1 = std::modf(pos_1, &lower_1_key);
00400 DiffType const lower_1 = DiffType(lower_1_key);
00401
00402
00403 if (pos_1 < 0)
00404 {
00405 if (lower_1)
00406 {
00407 return;
00408 }
00409 else
00410 {
00411 data_(lower_0, 0) += tmp_prod * (1 + frac_1);
00412 return;
00413 }
00414 }
00415 else
00416 {
00417 DiffType const back_1 = data_.cols() - 1;
00418
00419 if (lower_1 >= back_1)
00420 {
00421 if (lower_1 != back_1)
00422 {
00423 return;
00424 }
00425 else
00426 {
00427 data_(lower_0, lower_1) += tmp_prod * (1 - frac_1);
00428 return;
00429 }
00430 }
00431 else
00432 {
00433
00434 data_(lower_0, lower_1 + 1) += tmp_prod * frac_1;
00435 data_(lower_0, lower_1) += tmp_prod * (1 - frac_1);
00436 return;
00437 }
00438 }
00439 }
00440 }
00441 else
00442 {
00443
00444
00445
00446
00447 KeyType const pos_1 = key2index_1(arg_pos_1);
00448 KeyType lower_1_key;
00449 KeyType const frac_1 = std::modf(pos_1, &lower_1_key);
00450 DiffType const lower_1 = DiffType(lower_1_key);
00451
00452
00453 if (pos_1 < 0)
00454 {
00455 if (lower_1)
00456 {
00457 return;
00458 }
00459 else
00460 {
00461 KeyType const tmp_prod = KeyType(arg_value * (1 + frac_1));
00462 data_(lower_0 + 1, 0) += tmp_prod * frac_0;
00463 data_(lower_0, 0) += tmp_prod * (1 - frac_0);
00464 return;
00465 }
00466 }
00467 else
00468 {
00469 DiffType const back_1 = data_.cols() - 1;
00470
00471 if (lower_1 >= back_1)
00472 {
00473 if (lower_1 != back_1)
00474 {
00475 return;
00476 }
00477 else
00478 {
00479 KeyType const tmp_prod = KeyType(arg_value * (1 - frac_1));
00480 data_(lower_0 + 1, lower_1) += tmp_prod * frac_0;
00481 data_(lower_0, lower_1) += tmp_prod * (1 - frac_0);
00482 return;
00483 }
00484 }
00485 else
00486 {
00487
00488
00489
00490 KeyType tmp_prod = KeyType(arg_value * frac_0);
00491 data_(lower_0 + 1, lower_1 + 1) += tmp_prod * frac_1;
00492 data_(lower_0 + 1, lower_1) += tmp_prod * (1 - frac_1);
00493 tmp_prod = KeyType(arg_value * (1 - frac_0));
00494 data_(lower_0, lower_1 + 1) += tmp_prod * frac_1;
00495 data_(lower_0, lower_1) += tmp_prod * (1 - frac_1);
00496 return;
00497 }
00498 }
00499 }
00500 }
00501 }
00502
00504
00505
00506
00508
00509
00511 ContainerType & getData()
00512 {
00513 return data_;
00514 }
00515
00517 ContainerType const & getData() const
00518 {
00519 return data_;
00520 }
00521
00527 template <typename SourceContainer>
00528 void setData(SourceContainer const & data)
00529 {
00530 data_ = data;
00531 }
00532
00534 bool empty() const
00535 {
00536 return data_.empty();
00537 }
00538
00540
00541
00542
00544
00545
00547 KeyType key2index_0(KeyType pos) const
00548 {
00549 if (scale_0_)
00550 {
00551 pos -= offset_0_;
00552 pos /= scale_0_;
00553 return pos;
00554 }
00555 else
00556 {
00557 return 0;
00558 }
00559 }
00560
00562 KeyType index2key_0(KeyType pos) const
00563 {
00564 pos *= scale_0_;
00565 pos += offset_0_;
00566 return pos;
00567 }
00568
00570 KeyType key2index_1(KeyType pos) const
00571 {
00572 if (scale_1_)
00573 {
00574 pos -= offset_1_;
00575 pos /= scale_1_;
00576 return pos;
00577 }
00578 else
00579 {
00580 return 0;
00581 }
00582 }
00583
00585 KeyType index2key_1(KeyType pos) const
00586 {
00587 pos *= scale_1_;
00588 pos += offset_1_;
00589 return pos;
00590 }
00591
00593 KeyType const & getScale_0() const
00594 {
00595 return scale_0_;
00596 }
00597
00599 KeyType const & getScale_1() const
00600 {
00601 return scale_1_;
00602 }
00603
00609 void setScale_0(KeyType const & scale)
00610 {
00611 scale_0_ = scale;
00612 }
00613
00619 void setScale_1(KeyType const & scale)
00620 {
00621 scale_1_ = scale;
00622 }
00623
00625 KeyType const & getOffset_0() const
00626 {
00627 return offset_0_;
00628 }
00629
00631 KeyType const & getOffset_1() const
00632 {
00633 return offset_1_;
00634 }
00635
00642 void setOffset_0(KeyType const & offset)
00643 {
00644 offset_0_ = offset;
00645 }
00646
00653 void setOffset_1(KeyType const & offset)
00654 {
00655 offset_1_ = offset;
00656 }
00657
00671 void setMapping_0(KeyType const & scale, KeyType const & inside_low, KeyType const & outside_low)
00672 {
00673 scale_0_ = scale;
00674 inside_0_ = inside_low;
00675 outside_0_ = outside_low;
00676 offset_0_ = outside_low - scale * inside_low;
00677 return;
00678 }
00679
00686 void setMapping_0(KeyType const & inside_low, KeyType const & outside_low,
00687 KeyType const & inside_high, KeyType const & outside_high)
00688 {
00689 if (inside_high != inside_low)
00690 {
00691 setMapping_0((outside_high - outside_low) / (inside_high - inside_low),
00692 inside_low, outside_low);
00693 }
00694 else
00695 {
00696 setMapping_0(0, inside_low, outside_low);
00697 }
00698 return;
00699 }
00700
00714 void setMapping_1(KeyType const & scale, KeyType const & inside_low, KeyType const & outside_low)
00715 {
00716 scale_1_ = scale;
00717 inside_1_ = inside_low;
00718 outside_1_ = outside_low;
00719 offset_1_ = outside_low - scale * inside_low;
00720 return;
00721 }
00722
00729 void setMapping_1(KeyType const & inside_low, KeyType const & outside_low,
00730 KeyType const & inside_high, KeyType const & outside_high)
00731 {
00732 if (inside_high != inside_low)
00733 {
00734 setMapping_1((outside_high - outside_low) / (inside_high - inside_low),
00735 inside_low, outside_low);
00736 }
00737 else
00738 {
00739 setMapping_1(0, inside_low, outside_low);
00740 }
00741 return;
00742 }
00743
00745 KeyType const & getInsideReferencePoint_0() const
00746 {
00747 return inside_0_;
00748 }
00749
00751 KeyType const & getInsideReferencePoint_1() const
00752 {
00753 return inside_1_;
00754 }
00755
00757 KeyType const & getOutsideReferencePoint_0() const
00758 {
00759 return outside_0_;
00760 }
00761
00763 KeyType const & getOutsideReferencePoint_1() const
00764 {
00765 return outside_1_;
00766 }
00767
00769 KeyType supportMin_0() const
00770 {
00771 return index2key_0(empty() ? KeyType(0.) : KeyType(-1.));
00772 }
00773
00775 KeyType supportMin_1() const
00776 {
00777 return index2key_1(empty() ? KeyType(0.) : KeyType(-1.));
00778 }
00779
00781 KeyType supportMax_0() const
00782 {
00783 return index2key_0(KeyType(data_.rows()));
00784 }
00785
00787 KeyType supportMax_1() const
00788 {
00789 return index2key_1(KeyType(data_.cols()));
00790 }
00791
00793
00794 protected:
00795
00798 KeyType scale_0_;
00799 KeyType offset_0_;
00800 KeyType scale_1_;
00801 KeyType offset_1_;
00802 KeyType inside_0_;
00803 KeyType outside_0_;
00804 KeyType inside_1_;
00805 KeyType outside_1_;
00806 ContainerType data_;
00808 };
00809
00810 }
00811
00812 }
00813
00814 #endif // OPENMS_MATH_MISC_BILINEARINTERPOLATION_H