libkholidays
lunarphase.cpp00001
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 #include "config.h"
00035
00036 #include <kglobal.h>
00037 #include <klocale.h>
00038 #include <kdebug.h>
00039
00040 #include "lunarphase.h"
00041
00042 LunarPhase::LunarPhase( Hemisphere hemisphere )
00043 {
00044 mHemisphere = hemisphere;
00045 }
00046
00047 LunarPhase::~LunarPhase()
00048 {
00049 }
00050
00051 void LunarPhase::setHemisphere( Hemisphere hemisphere )
00052 {
00053 mHemisphere = hemisphere;
00054 }
00055
00056 LunarPhase::Hemisphere LunarPhase::hemisphere() const
00057 {
00058 return( mHemisphere );
00059 }
00060
00061 QString LunarPhase::hemisphereStr() const
00062 {
00063 return hemisphereName( mHemisphere );
00064 }
00065
00066 QString LunarPhase::hemisphereName( LunarPhase::Hemisphere hemisphere )
00067 {
00068 switch( hemisphere ) {
00069 case Northern:
00070 default:
00071 return( i18n( "Northern" ) );
00072 break;
00073 case Southern:
00074 return( i18n( "Southern" ) );
00075 break;
00076 }
00077 }
00078
00079 QString LunarPhase::phaseStr( const QDate &date ) const
00080 {
00081 return phaseName( phase( date ) );
00082 }
00083
00084 QString LunarPhase::phaseName( LunarPhase::Phase phase )
00085 {
00086 switch ( phase ) {
00087 case New:
00088 return( i18n( "New Moon" ) );
00089 break;
00090 case Full:
00091 return( i18n( "Full Moon" ) );
00092 break;
00093 case FirstQ:
00094 return( i18n( "First Quarter Moon" ) );
00095 break;
00096 case LastQ:
00097 return( i18n( "Last Quarter Moon" ) );
00098 break;
00099 default:
00100 case None:
00101 return( QString::null );
00102 break;
00103 }
00104 }
00105
00106 LunarPhase::Phase LunarPhase::phase( const QDate &date ) const
00107 {
00108 Phase retPhase = None;
00109
00110
00111 QTime noontime( 12, 0, 0 );
00112 QDateTime today( date, noontime );
00113 double todayPer = percentFull( today.toTime_t() );
00114 QDateTime yesterday( date.addDays(-1), noontime );
00115 double yesterdayPer = percentFull( yesterday.toTime_t() );
00116
00117 if ( ( todayPer < 0.50 ) && ( yesterdayPer > 0.50 ) ) {
00118 retPhase = New;
00119 } else if ( ( todayPer > 99.50 ) && ( yesterdayPer < 99.50 ) ) {
00120 retPhase = Full;
00121 } else {
00122
00123 QTime sqt( 0, 0, 0 );
00124 QDateTime start( date, sqt );
00125 double startPer = percentFull( start.toTime_t() );
00126
00127 QTime eqt( 23, 59, 59 );
00128 QDateTime end( date, eqt );
00129 double endPer = percentFull( end.toTime_t() );
00130
00131 if ( ( startPer <= 50 ) && ( endPer > 50 ) ) {
00132 if ( mHemisphere == Northern ) {
00133 retPhase = FirstQ;
00134 } else {
00135 retPhase = LastQ;
00136 }
00137 }
00138 if ( ( endPer <= 50 ) && ( startPer > 50 ) ) {
00139 if ( mHemisphere == Northern ) {
00140 retPhase = LastQ;
00141 } else {
00142 retPhase = FirstQ;
00143 }
00144 }
00145
00146
00147 }
00148 return( retPhase );
00149 }
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186 #if HAVE_SYS_CDEFS_H
00187 #include <sys/cdefs.h>
00188 #endif
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 #include <ctype.h>
00204 #if HAVE_ERR_H
00205 #include <err.h>
00206 #endif
00207 #include <math.h>
00208 #include <string.h>
00209 #include <stdlib.h>
00210 #include <time.h>
00211 #include <unistd.h>
00212
00213 #ifndef PI
00214 #define PI 3.14159265358979323846
00215 #endif
00216
00217
00218
00219
00220
00221
00222
00223 #define EPOCH_MINUS_1970 (20 * 365 + 5 - 1)
00224 #define EPSILONg 279.403303
00225 #define RHOg 282.768422
00226 #define ECCEN 0.016713
00227 #define lzero 318.351648
00228 #define Pzero 36.340410
00229 #define Nzero 318.510107
00230
00231
00232
00233
00234
00235 double LunarPhase::percentFull( uint tmpt ) const
00236 {
00237 double N, Msol, Ec, LambdaSol, l, Mm, Ev, Ac, A3, Mmprime;
00238 double A4, lprime, V, ldprime, D, Nm;
00239
00240 double days;
00241 days = ( tmpt - EPOCH_MINUS_1970 * 86400 ) / 86400.0;
00242
00243 N = 360 * days / 365.242191;
00244 adj360(&N);
00245 Msol = N + EPSILONg - RHOg;
00246 adj360(&Msol);
00247 Ec = 360 / PI * ECCEN * sin(degreesToRadians(Msol));
00248 LambdaSol = N + Ec + EPSILONg;
00249 adj360(&LambdaSol);
00250 l = 13.1763966 * days + lzero;
00251 adj360(&l);
00252 Mm = l - (0.1114041 * days) - Pzero;
00253 adj360(&Mm);
00254 Nm = Nzero - (0.0529539 * days);
00255 adj360(&Nm);
00256 Ev = 1.2739 * sin(degreesToRadians(2*(l - LambdaSol) - Mm));
00257 Ac = 0.1858 * sin(degreesToRadians(Msol));
00258 A3 = 0.37 * sin(degreesToRadians(Msol));
00259 Mmprime = Mm + Ev - Ac - A3;
00260 Ec = 6.2886 * sin(degreesToRadians(Mmprime));
00261 A4 = 0.214 * sin(degreesToRadians(2 * Mmprime));
00262 lprime = l + Ev + Ec - Ac + A4;
00263 V = 0.6583 * sin(degreesToRadians(2 * (lprime - LambdaSol)));
00264 ldprime = lprime + V;
00265 D = ldprime - LambdaSol;
00266 return(50.0 * (1 - cos(degreesToRadians(D))));
00267 }
00268
00269
00270
00271
00272
00273 double LunarPhase::degreesToRadians( double degree ) const
00274 {
00275 return( degree * PI / 180 );
00276 }
00277
00278
00279
00280
00281
00282 void LunarPhase::adj360( double *degree ) const
00283 {
00284 for( ;; )
00285 if( *degree < 0 )
00286 *degree += 360;
00287 else if( *degree > 360 )
00288 *degree -= 360;
00289 else
00290 break;
00291 }
|