Home  · Classes  · Annotated Classes  · Modules  · Members  · Namespaces  · Related Pages

BilinearInterpolation.h (Maintainer: Clemens Groepl)

Go to the documentation of this file.
00001 // -*- Mode: C++; tab-width: 2; -*-
00002 // vi: set ts=2:
00003 //
00004 // --------------------------------------------------------------------------
00005 //                   OpenMS Mass Spectrometry Framework
00006 // --------------------------------------------------------------------------
00007 //  Copyright (C) 2003-2008 -- Oliver Kohlbacher, Knut Reinert
00008 //
00009 //  This library is free software; you can redistribute it and/or
00010 //  modify it under the terms of the GNU Lesser General Public
00011 //  License as published by the Free Software Foundation; either
00012 //  version 2.1 of the License, or (at your option) any later version.
00013 //
00014 //  This library is distributed in the hope that it will be useful,
00015 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 //  Lesser General Public License for more details.
00018 //
00019 //  You should have received a copy of the GNU Lesser General Public
00020 //  License along with this library; if not, write to the Free Software
00021 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 //
00023 // --------------------------------------------------------------------------
00024 // $Maintainer: Clemens Groepl $
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         // apply the key transformations
00146         KeyType const pos_0 = key2index_0( arg_pos_0 );
00147         KeyType const pos_1 = key2index_1( arg_pos_1 );
00148 
00149 
00150         // ???? should use modf() here!
00151 
00152         int const size_0 = data_.rows();
00153         int const lower_0 = int( pos_0 ); // this rounds towards zero
00154         int const size_1 = data_.cols();
00155         int const lower_1 = int( pos_1 ); // this rounds towards zero
00156 
00157         // small pos_0
00158         if ( pos_0 <= 0 )
00159         {
00160           if ( lower_0 != 0 )
00161           {
00162             return 0;
00163           }
00164           else
00165           { // that is: -1 < pos_0 <= 0
00166 
00167             // small pos_1
00168             if ( pos_1 <= 0 )
00169             {
00170               if ( lower_1 != 0 )
00171               {
00172                 return 0;
00173               }
00174               else
00175               { // that is: -1 < pos_1 <= 0
00176                 return data_( 0, 0 ) * ( 1. + pos_0 ) * ( 1. + pos_1 ) ;
00177               }
00178             }
00179 
00180             // big pos_1
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             // mediumm pos_1
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         // big pos_0
00205         if ( lower_0 >= size_0 - 1 )
00206         {
00207           if ( lower_0 != size_0 - 1 )
00208           {
00209             return 0;
00210           }
00211           else
00212           { // that is: size_0 - 1 <= pos_0 < size_0
00213 
00214             // small pos_1
00215             if ( pos_1 <= 0 )
00216             {
00217               if ( lower_1 != 0 )
00218               {
00219                 return 0;
00220               }
00221               else
00222               { // that is: -1 < pos_1 <= 0
00223                 return data_( lower_0, 0 ) * ( size_0 - pos_0 ) * ( 1. + pos_1 ) ;
00224               }
00225             }
00226 
00227             // big pos_1
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             // mediumm pos_1
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         // medium pos_0
00253         {
00254           KeyType const factor_0 = pos_0 - KeyType( lower_0 );
00255           KeyType const factor_0_complement = 1. - factor_0;
00256 
00257           // small pos_1
00258           if ( pos_1 <= 0 )
00259           {
00260             if ( lower_1 != 0 )
00261             {
00262               return 0;
00263             }
00264             else
00265             { // that is: -1 < pos_1 <= 0
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           // big pos_1
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           // medium pos_0 and medium pos_1 --> "within" the matrix
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         // apply key transformation _0
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         // Small pos_0 ?
00330         if ( pos_0 < 0 )
00331         {
00332           if ( lower_0 )
00333           {
00334             return ;
00335           }
00336           else
00337           { // lower_0 == 0
00338 
00339             // apply key transformation _1
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             // Small pos_1 ?
00346             if ( pos_1 < 0 )
00347             {
00348               if ( lower_1 )
00349               {
00350                 return ;
00351               }
00352               else
00353               { // lower_1 == 0
00354                 data_( 0, 0 ) += arg_value * ( 1 + frac_0 ) * ( 1 + frac_1 );
00355                 return ;
00356               }
00357             }
00358             else // pos_1 >= 0
00359             {
00360               DiffType const back_1 = data_.cols() - 1;
00361               // big pos_1
00362               if ( lower_1 >= back_1 )
00363               {
00364                 if ( lower_1 != back_1 )
00365                 {
00366                   return ;
00367                 }
00368                 else // lower_1 == back_1
00369                 {
00370                   data_ ( 0, lower_1 ) += arg_value * ( 1 + frac_0 ) * ( 1 - frac_1 );
00371                   return ;
00372                 }
00373               }
00374               else
00375               {
00376                 // medium pos_1
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 // pos_0 >= 0
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 // lower_0 == back_0
00395             {
00396 
00397               KeyType const tmp_prod = arg_value * ( 1 - frac_0 );
00398 
00399               // apply key transformation _1
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               // Small pos_1 ?
00406               if ( pos_1 < 0 )
00407               {
00408                 if ( lower_1 )
00409                 {
00410                   return ;
00411                 }
00412                 else
00413                 { // lower_1 == 0
00414                   data_( lower_0, 0 ) += tmp_prod * ( 1 + frac_1 );
00415                   return ;
00416                 }
00417               }
00418               else // pos_1 >= 0
00419               {
00420                 DiffType const back_1 = data_.cols() - 1;
00421                 // big pos_1
00422                 if ( lower_1 >= back_1 )
00423                 {
00424                   if ( lower_1 != back_1 )
00425                   {
00426                     return ;
00427                   }
00428                   else // lower_1 == back_1
00429                   {
00430                     data_ ( lower_0, lower_1 ) += tmp_prod * ( 1 - frac_1 );
00431                     return ;
00432                   }
00433                 }
00434                 else
00435                 {
00436                   // medium pos_1
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 // lower_0 < back_0
00445           {
00446 
00447             // Medium pos_0 !
00448 
00449             // apply key transformation _1
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             // Small pos_1 ?
00456             if ( pos_1 < 0 )
00457             {
00458               if ( lower_1 )
00459               {
00460                 return ;
00461               }
00462               else
00463               { // lower_1 == 0
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 // pos_1 >= 0
00471             {
00472               DiffType const back_1 = data_.cols() - 1;
00473               // big pos_1
00474               if ( lower_1 >= back_1 )
00475               {
00476                 if ( lower_1 != back_1 )
00477                 {
00478                   return ;
00479                 }
00480                 else // lower_1 == back_1
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                 // Medium pos_1 !
00491 
00492                 // medium pos_0 and medium pos_1 --> "within" the matrix
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   } // namespace Math
00815 
00816 } // namespace OpenMS
00817 
00818 #endif // OPENMS_MATH_MISC_BILINEARINTERPOLATION_H

Generated Tue Apr 1 15:36:33 2008 -- using doxygen 1.5.4 OpenMS / TOPP 1.1