CommonTime.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: CommonTime.cpp 2965 2011-11-03 11:25:57Z martenstrom $"
00002 
00003 
00004 
00005 //============================================================================
00006 //
00007 //  This file is part of GPSTk, the GPS Toolkit.
00008 //
00009 //  The GPSTk is free software; you can redistribute it and/or modify
00010 //  it under the terms of the GNU Lesser General Public License as published
00011 //  by the Free Software Foundation; either version 2.1 of the License, or
00012 //  any later version.
00013 //
00014 //  The GPSTk 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
00017 //  GNU 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 GPSTk; if not, write to the Free Software Foundation,
00021 //  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 //  
00023 //  Copyright 2004, The University of Texas at Austin
00024 //
00025 //============================================================================
00026 
00027 #include "CommonTime.hpp"
00028 #include "TimeConstants.hpp"
00029 
00030 #include "MathBase.hpp"
00031 #include "StringUtils.hpp"
00032 
00033 namespace gpstk
00034 {
00035       // 'julian day' of earliest epoch expressible by CommonTime; 1/1/4713 B.C.
00036    const long CommonTime::BEGIN_LIMIT_JDAY = 0;
00037       // 'julian day' of latest 'julian day' expressible by CommonTime, 
00038       // 1/1/4713 A.D.
00039    const long CommonTime::END_LIMIT_JDAY = 3442448;
00040 
00041       // earliest representable CommonTime
00042    const CommonTime 
00043    CommonTime::BEGINNING_OF_TIME( CommonTime::BEGIN_LIMIT_JDAY, 0, 0.0 );
00044       // latest representable CommonTime
00045    const CommonTime 
00046    CommonTime::END_OF_TIME( CommonTime::END_LIMIT_JDAY, 0, 0.0 ) ;
00047 
00048    CommonTime::CommonTime( const CommonTime& right )
00049       throw()
00050          : m_day( right.m_day ), m_msod( right.m_msod ), m_fsod( right.m_fsod )
00051    {}
00052 
00053    CommonTime& CommonTime::operator=( const CommonTime& right )
00054       throw()
00055    {
00056       m_day = right.m_day;
00057       m_msod = right.m_msod;
00058       m_fsod = right.m_fsod;
00059       return *this; 
00060    }
00061 
00062    CommonTime& CommonTime::set( long day,
00063                                 long sod,
00064                                 double fsod )
00065       throw( gpstk::InvalidParameter )
00066    {
00067          // Use temp variables so that we don't modify our
00068          // data members until we know these values are good.
00069       if( day < BEGIN_LIMIT_JDAY || day > END_LIMIT_JDAY )
00070       {
00071          gpstk::InvalidParameter ip( "Invalid day: " 
00072                                      + gpstk::StringUtils::asString( day ) );
00073          GPSTK_THROW( ip );
00074       }
00075       
00076       if( sod < 0 || sod >= SEC_PER_DAY )
00077       {
00078          gpstk::InvalidParameter ip( "Invalid seconds of day: "
00079                                      + gpstk::StringUtils::asString( sod ) );
00080          GPSTK_THROW( ip );
00081       }
00082       
00083       if( fsod < 0.0 || fsod >= 1 )
00084       {
00085          gpstk::InvalidParameter ip( "Invalid fractional-seconds: "
00086                                      + gpstk::StringUtils::asString( fsod ) );
00087          GPSTK_THROW( ip );
00088       }
00089 
00090          // get the number of milliseconds in the fractional seconds argument
00091       long msec = static_cast<long>( fsod * MS_PER_SEC );
00092       
00093          // subtract whole milliseconds to obtain the "fractional milliseconds"
00094       fsod -= static_cast<double>( msec ) * SEC_PER_MS;
00095 
00096       m_day  = day;
00097       m_msod = sod * MS_PER_SEC + msec;
00098       m_fsod = fsod;
00099 
00100       return *this;
00101    }
00102 
00103    CommonTime& CommonTime::set( long day,
00104                                 double sod )
00105       throw( gpstk::InvalidParameter )
00106    {
00107          // separate whole and fractional seconds, then use set()
00108       long sec = static_cast<long>( sod );
00109       sod -= sec;
00110 
00111       return set( day, sec, sod );
00112    }
00113 
00114    CommonTime& CommonTime::set( double day = 0.0 )
00115       throw( gpstk::InvalidParameter )
00116    {
00117          // separate whole and fractional days
00118       long lday = static_cast<long>( day );
00119       double sec = ( day - lday ) * SEC_PER_DAY;
00120       return set( lday, sec );
00121    }
00122 
00123    CommonTime& CommonTime::setInternal( long day,
00124                                         long msod,
00125                                         double fsod )
00126       throw( gpstk::InvalidParameter )
00127    {
00128       if( day < BEGIN_LIMIT_JDAY || day > END_LIMIT_JDAY )
00129       {
00130          gpstk::InvalidParameter ip( "Invalid day: " 
00131                                      + gpstk::StringUtils::asString( day ) );
00132          GPSTK_THROW( ip );
00133       }
00134       
00135       if( msod < 0 || msod >= MS_PER_DAY )
00136       {
00137          gpstk::InvalidParameter ip( "Invalid milliseconds of day: "
00138                                      + gpstk::StringUtils::asString( msod ) );
00139          GPSTK_THROW( ip );
00140       }
00141       
00142       if( fsod < 0.0 || fsod >= SEC_PER_MS )
00143       {
00144          gpstk::InvalidParameter ip( "Invalid fractional-milliseconds: "
00145                                      + gpstk::StringUtils::asString( fsod ) );
00146          GPSTK_THROW( ip );
00147       }
00148       
00149       m_day = day;
00150       m_msod = msod;
00151       m_fsod = fsod;
00152       
00153       return *this;
00154    }
00155 
00156    void CommonTime::get( long& day, 
00157                          long& sod,
00158                          double& fsod ) const
00159       throw()
00160    {
00161       day = m_day;
00162       sod = m_msod / MS_PER_SEC;
00163       long msec = m_msod - sod * MS_PER_SEC;  // m_msod % MS_PER_SEC
00164       fsod = static_cast<double>( msec ) * SEC_PER_MS + m_fsod;
00165    }
00166    
00167    void CommonTime::get( long& day,
00168                          double& sod ) const
00169       throw()
00170    {
00171       day = m_day;
00172       sod = (double)m_msod / MS_PER_SEC + m_fsod;
00173    }
00174    
00175    void CommonTime::get( double& day ) const
00176       throw()
00177    {
00178          // convert everything to days
00179       day = static_cast<double>( m_day ) + 
00180          static_cast<double>( m_msod ) / MS_PER_DAY +
00181          m_fsod / SEC_PER_DAY;
00182    }
00183 
00184    double CommonTime::getDays() const
00185       throw()
00186    {
00187       double day;
00188       get( day );
00189       return day;
00190    }
00191    
00192    double CommonTime::getSecondOfDay() const
00193       throw()
00194    {
00195       long day;
00196       double sod;
00197       get( day, sod );
00198       return sod;
00199    }
00200 
00201    double CommonTime::operator-( const CommonTime& right ) const
00202       throw()
00203    {
00204       return ( SEC_PER_DAY * static_cast<double>( m_day - right.m_day ) +
00205                SEC_PER_MS * static_cast<double>( m_msod - right.m_msod ) + 
00206                m_fsod - right.m_fsod  ) ;
00207    }
00208    
00209    CommonTime CommonTime::operator+( double sec ) const
00210       throw( gpstk::InvalidRequest )
00211    {
00212       return CommonTime( *this ).addSeconds( sec );
00213    }
00214 
00215    CommonTime CommonTime::operator-( double sec ) const
00216       throw( gpstk::InvalidRequest )
00217    {
00218       return CommonTime( *this ).addSeconds( -sec );
00219    }
00220    
00221    CommonTime& CommonTime::operator+=( double sec )
00222       throw( gpstk::InvalidRequest )
00223    {
00224       addSeconds( sec );
00225       return *this;
00226    }
00227    
00228    CommonTime& CommonTime::operator-=( double sec )
00229       throw( gpstk::InvalidRequest )
00230    {
00231       addSeconds( -sec );
00232       return *this;
00233    }
00234 
00235    CommonTime& CommonTime::addSeconds( double seconds )
00236       throw( InvalidRequest )
00237    {
00238       long days=0, ms=0;
00239       if ( ABS(seconds) >= SEC_PER_DAY )
00240       {
00241          days = static_cast<long>( seconds * DAY_PER_SEC );
00242          seconds -= days * SEC_PER_DAY;
00243       }
00244 
00245       if ( ABS(seconds) >= SEC_PER_MS )
00246       {
00247          ms = static_cast<long>( seconds * MS_PER_SEC );
00248          seconds -= static_cast<double>( ms ) / MS_PER_SEC;
00249       }
00250 
00251       add(days, ms, seconds);
00252       return *this;
00253    }
00254 
00255    CommonTime& CommonTime::addSeconds( long seconds )
00256       throw( gpstk::InvalidRequest )
00257    {
00258       long days( 0 );
00259       if( ABS( seconds ) > SEC_PER_DAY )
00260       {
00261          days = seconds / SEC_PER_DAY;
00262          seconds -= days * SEC_PER_DAY;  // seconds %= SEC_PER_DAY
00263       }
00264       add( days, seconds * MS_PER_SEC, 0. );
00265       
00266          // How about this?
00267          // add( seconds / SEC_PER_DAY,
00268          //      seconds % SEC_PER_DAY * MS_PER_SEC,
00269          //      0 );
00270 
00271       return *this;
00272    }
00273 
00274    CommonTime& CommonTime::addDays( long days )
00275       throw( gpstk::InvalidRequest )
00276    {
00277       add( days, 0, 0.0 );
00278       return *this;
00279    }
00280    
00281    CommonTime& CommonTime::addMilliseconds( long msec )
00282       throw( InvalidRequest )
00283    {
00284       add( 0, msec, 0.0 );
00285       return *this;
00286    }
00287 
00288    bool CommonTime::operator==( const CommonTime& right ) const
00289       throw()
00290    {
00291       return (m_day == right.m_day &&
00292               m_msod == right.m_msod &&
00293               m_fsod == right.m_fsod );
00294    }
00295 
00296    bool CommonTime::operator!=( const CommonTime& right ) const
00297       throw()
00298    {
00299       return !operator==(right);
00300    }
00301 
00302    bool CommonTime::operator<( const CommonTime& right ) const
00303       throw()
00304    {
00305       if (m_day < right.m_day)
00306          return true;
00307       if (m_day > right.m_day)
00308          return false;
00309 
00310       if (m_msod < right.m_msod)
00311          return true;
00312       if (m_msod > right.m_msod)
00313          return false;
00314       
00315       if (m_fsod < right.m_fsod)
00316          return true;
00317       
00318       return false;
00319    }
00320 
00321    bool CommonTime::operator>( const CommonTime& right ) const
00322       throw()
00323    {
00324       return !operator <=(right);
00325    }
00326 
00327    bool CommonTime::operator<=( const CommonTime& right ) const
00328       throw()
00329    {
00330       return (operator<(right) || operator==(right));
00331    }
00332 
00333    bool CommonTime::operator>=( const CommonTime& right ) const
00334       throw()
00335    {
00336       return !operator<(right);
00337    }
00338 
00339    std::string CommonTime::asString() const
00340       throw()
00341    {
00342       using namespace std;
00343       ostringstream oss;
00344       oss << setfill('0') 
00345           << setw(7) << m_day << " "
00346           << setw(8) << m_msod << " "
00347           << fixed << setprecision(15) << setw(17) << m_fsod;
00348       return oss.str();
00349    }
00350 
00352    bool CommonTime::add( long days, 
00353                          long msod,
00354                          double fsod )
00355       throw()
00356    {
00357       m_day += days;
00358       m_msod += msod;
00359       m_fsod += fsod;
00360       return normalize();
00361    }
00362                                 
00363    bool CommonTime::normalize()
00364       throw()
00365    {
00366       if( ABS( m_fsod ) >= SEC_PER_MS )
00367       {
00368          long ms = static_cast<long>( m_fsod * MS_PER_SEC );
00369          m_msod += ms;
00370          m_fsod -= static_cast<double>( ms ) * SEC_PER_MS;
00371       }
00372       
00373       if( ABS( m_msod ) >= MS_PER_DAY )
00374       {
00375          long day = m_msod / MS_PER_DAY;
00376          m_day += day;
00377          m_msod -= day * MS_PER_DAY;
00378       }
00379 
00380       if( ABS(m_fsod) < 1e-15 )
00381       {
00382          m_fsod = 0.0;
00383       }
00384       
00385       if( m_fsod < 0 )
00386       {
00387          m_fsod += SEC_PER_MS;
00388          --m_msod;
00389       }
00390       
00391       if( m_msod < 0 )
00392       {
00393          m_msod = m_msod + MS_PER_DAY;
00394          --m_day;
00395       }
00396       
00397       return ( ( m_day >= BEGIN_LIMIT_JDAY ) && 
00398                ( m_day <  END_LIMIT_JDAY ) );
00399    }
00400 
00401    std::ostream& operator<<(std::ostream& o, const CommonTime& ct)
00402    {
00403       o << ct.asString();
00404       return o;
00405    }
00406 
00407 } // namespace

Generated on Wed Feb 8 03:30:58 2012 for GPS ToolKit Software Library by  doxygen 1.3.9.1