ASW



Loading...
Searching...
No Matches
moon.c++
Go to the documentation of this file.
1
21
22#include "moon.h"
23
25const double Moon::RAD = (3.1415926535897/180.0);
26const long Moon::IGREG = (15+31L*(10+12L*1582));
27const double Moon::MEAN_LUNAR_CYCLE = 29.53058868;
29
30double Moon::phase(int mon,int day,int year)
31{
32 // the new moon Julian date
33 long nm_jd = 0;
34 double nm_frac = 0.0;
35 // the 1st quarter Julian date
36 long fq_jd = 0;
37 double fq_frac = 0.0;
38 // the full moon Julian date
39 long fm_jd = 0;
40 double fm_frac = 0.0;
41 // the last quarter Julian date
42 long lq_jd = 0;
43 double lq_frac = 0.0;
44 // The Julian date entered
45 long jd = 0;
46 double frac = 0.0;
47 // The lunar phase
48 double ph = 0.0;
49 // The portion of a lunar phase which elapse per day
50 double phase_per_day = 1/(MEAN_LUNAR_CYCLE/4);
51 // 12.37 is the number of lunar cycles per year
52 // n then is the number of lunar cycles since 1900 and the year month entered
53 int n = (int)(12.37*((year-1900)+((mon-0.5)/12.0)));
54
55 // Get the Julian Date and make sure date entered is valid
56 if(!(jd = Calendar2Julian(mon,day,year))) return(-1.0);
57 // Now get the first date of the new moon of year mouth entered
58 flmoon(n,0,nm_jd,nm_frac);
59 // If it after the entered date backup one lunar cycle
60 if(jd < nm_jd) flmoon(--n,0,nm_jd,nm_frac);
61 // Now find the 1st querter
62 flmoon(n,1,fq_jd,fq_frac);
63 // If it's after or on the day entered
64 if(fq_jd >= jd) {
65 // Now calculate the phase which we now know is between the
66 // new moon and first quarter
67 if(abs((int)jd - nm_jd) < abs((int)jd - fq_jd)) {
68 // We are closer to the new moon so no phase offset needed
69 ph = (double)(((double)(jd) - ((double)nm_jd+nm_frac)) * phase_per_day);
70 if(ph < 0) ph = 4.0 + ph;
71 return(ph > 4.0 ? ph - 4.0 : ph); // Keep the value between 0-4
72 } else {
73 // we are closer to the 1st quarter so add it in
74 ph = 1.0+(double)(((double)(jd) - ((double)fq_jd+fq_frac)) * phase_per_day);
75 return(ph > 4.0 ? ph - 4.0 : ph); // Keep the value between 0-4
76 }
77 }
78 // Now find the full moon querter
79 flmoon(n,2,fm_jd,fm_frac);
80 // If it's after or on the day entered
81 if(fm_jd >= jd) {
82 // Now calculate the phase which we now know is between the
83 // first quarter and the full moon
84 if(abs((int)jd - fq_jd) < abs((int)jd - fm_jd)) {
85 // we are closer to the 1st quarter so add it in
86 ph = 1.0+(double)(((double)(jd) - ((double)fq_jd+fq_frac)) * phase_per_day);
87 return(ph > 4.0 ? ph - 4.0 : ph); // Keep the value between 0-4
88 } else {
89 // we are closer to the full moon so add it in
90 ph = 2.0+(double)(((double)(jd) - ((double)fm_jd+fm_frac)) * phase_per_day);
91 return(ph > 4.0 ? ph - 4.0 : ph); // Keep the value between 0-4
92 }
93 }
94 // Now find the last querter
95 flmoon(n,3,lq_jd,lq_frac);
96 // If it's after or on the day entered
97 if(lq_jd >= jd) {
98 // Now calculate the phase which we now know is between the
99 // full moon and last quarter
100 if(abs((int)jd - fm_jd) < abs((int)jd - lq_jd)) {
101 // we are closer to the full moon so add it in
102 ph = (2.0+(double)(((double)(jd) - ((double)fm_jd+fm_frac)) * phase_per_day));
103 return(ph > 4.0 ? ph - 4.0 : ph); // Keep the value between 0-4
104 } else {
105 // we are closer to the last quarter so add it in
106 ph = (3.0+(double)(((double)(jd) - ((double)lq_jd+lq_frac)) * phase_per_day));
107 return(ph > 4.0 ? ph - 4.0 : ph); // Keep the value between 0-4
108 }
109 }
110 // Now find the new moon querter
111 flmoon(++n,0,nm_jd,nm_frac);
112 // Now calculate the phase which we now know is after the last quarter
113 ph = (4.0+(double)(((double)(jd) - ((double)nm_jd+nm_frac)) * phase_per_day));
114 return(ph > 4.0 ? ph - 4.0 : ph); // Keep the value between 0-4
115
116} // End of phase()
117
119
120void Moon::nextphase(int& mon,int& day,int& year,int& hr,int& min,int nph)
121{
122 long jd = 0;
123 double djd = 0.0;
124 long ph_jd = 0;
125 double frac = 0.0;
126 int n = (int)(12.37*((year-1900)+((mon-0.5)/12.0)));
127 double intpart = 0.0;
128
129 jd = Calendar2Julian(mon,day,year);
130 djd = flmoon(n,nph,ph_jd,frac) + 0.5;
131 while(jd < ph_jd) {
132 djd = flmoon(--n,nph,ph_jd,frac) + 0.5;
133 }
134 while(jd > ph_jd) {
135 djd = flmoon(++n,nph,ph_jd,frac) + 0.5;
136 }
137
138 struct tm *tmpt;
139 time_t e;
140
141 e = time(NULL);
142 tmpt = localtime(&e);
143 djd += ((double)tmpt->tm_gmtoff * (1.0/86400.0));
144 if(tmpt->tm_isdst) djd -= (1.0/24.0);
145 ph_jd = (long)floor(djd);
146 if(isDST(jd)) {
147 djd += (1.0/24.0);
148 ph_jd = (long)floor(djd);
149 }
150 frac = djd - floor(djd);
151
152 Julian2Calendar(ph_jd,mon,day,year);
153 frac *= 24.0;
154 hr = (int)(frac >= 0.0 ? floor(frac) : ceil(frac-1.0));
155 frac -= (double)hr;
156 min = (int)floor(60*frac);
157
158} // End of nextphase()
159
161
162double Moon::flmoon(int n,int nph,long& jd,double& frac)
163{
164 int int_part = 0;
165 double lunar_cycles = n + ( nph / 4.0 ); // the total number lunar cycle
166 // nph = 4 is one lunar cycle
167 double t = lunar_cycles / 1236.85; // 1236.85 is the number of lunar cycle per Julian Century
168 double t2 = t * t; // Square for frequent use
169
170 // Sun's mean anomaly
171 double sun_anomaly = 359.2242 + ( 29.10535608 * lunar_cycles );
172
173 // Moon's mean anomaly
174 double moon_anomaly = 306.0253 + ( 385.81691806 * lunar_cycles ) + ( 0.010730 * t2 );
175
176 // Not sure of what's up here, but two of the numbers very interesting
177 // Notice that 2415020.75933 is used a referce epochs for mean time of lunar cycle which is 1900 Jan 1 at 6:13 AM
178 // And 29.53058868 is the "Synodic month" or the mean time in days between new moons.
179 double xtra = 0.75933 + ( 1.53058868 * lunar_cycles ) + ( ( ( 1.78e-4 ) - ( 1.55e-7 ) * t ) * t2 );
180
181 // Ok 2415020 is Julian date 1899 at noon + .75933 is the Julian date of a new moon
182 // 28 + 1.53058868 is mean time of a lunar cycle ,
183 // and 7 close to 7.38264717 a lunar phase but unlike
184 // the first two the tractional part dose not seem to be accounted for.
185 jd = 2415020 + ( 28L * n ) + ( 7L * nph );
186
187 // Looks like this is all being done to adjust the variations in the maen lunar cycle of 29.53058868
188 // Which from what I understand is due the moons orbit in relationship to the earths orbit around the sun.
189 if(nph == 0 || nph == 2) // New or Full - sun earth moon inline
190 xtra += ( ( 0.1734-3.93e-4 * t ) * sin(RAD*sun_anomaly) ) - ( 0.4068 * sin(RAD*moon_anomaly) );
191 else // 1st quarder last quarter - moon 90 deegree left or right of the earth and suns line
192 xtra += ( ( 0.1721-4.0e-4 * t ) * sin(RAD*sun_anomaly) ) - ( 0.6280 * sin(RAD*moon_anomaly) );
193
194 // This parts easy just put the integer and fractional parts right
195 int_part = (int)( xtra >= 0.0 ? floor(xtra) : ceil(xtra-1.0) );
196 jd += int_part;
197 frac = xtra - int_part;
198 return double(jd + frac);
199
200} // End of flmoon()
201
202
204
205void Moon::Julian2Calendar(long jd,int& mon,int& day,int& year)
206{
207 const long GREG = 2299161L;
208 long a = 0L;
209 long b = 0L;
210 long c = 0L;
211 long d = 0L;
212 long e = 0L;
213
214 if(jd >= GREG) {
215 a = (long)((((jd-1867216)-0.25)/36524.25));
216 a = (long)(jd+1+(long)a-(long)(0.25*(long)a));
217 } else {
218 a = jd;
219 }
220 b = a+1524;
221 c = (long)(6680+((b-2439870)-122.1)/365.25);
222 d = 365*c+(long)(0.25*c);
223 e = (long)((b-d)/30.6001);
224 day = (int)(b-d-(long)(30.6001*e));
225 mon = (int)(e-1);
226 if(mon > 12) mon -= 12;
227 year = (int)(c-4715);
228 if(mon > 2) --year;
229 if(year <= 0) --year;
230
231} // End of Julian2Calendar()
232
234
235long Moon::Calendar2Julian(int mon,int day,int year)
236{
237 long jul;
238 int ja,jy=year,jm;
239
240 if(jy == 0) return(0);
241 if(jy < 0) ++jy;
242 if(mon > 2) jm=mon+1;
243 else {
244 --jy;
245 jm=mon+13;
246 }
247 jul = (long)(floor(365.25*jy)+floor(30.6001*jm)+day+1720995);
248 if(day+31L*(mon+12L*year) >= IGREG) {
249 ja=(int)(0.01*jy);
250 jul += 2-ja+(int)(0.25*ja);
251 }
252 return(jul);
253
254} // End of Calendar2Julian()
255
257
258bool Moon::isDST(long jd)
259{
260 int m,d,y;
261
262 Julian2Calendar(jd,m,d,y);
263 return(isDST(m,d,y));
264
265} // End of isDST()
266
268
269bool Moon::isDST(int mon,int day,int year)
270{
271 struct tm tmp;
272 struct tm *tmpt;
273 time_t e;
274
275 e = time(NULL);
276 tmpt = localtime(&e);
277 tmp.tm_gmtoff = tmpt->tm_gmtoff;
278 tmp.tm_mon = mon - 1;
279 tmp.tm_mday = day;
280 tmp.tm_year = year - 1900;
281 tmp.tm_sec = 0;
282 tmp.tm_min = 0;
283 tmp.tm_hour = 3;
284 tmp.tm_isdst = -1;
285 e = mktime(&tmp);
286 tmpt = localtime(&e);
287 if(tmpt->tm_isdst) return(true);
288 return(false);
289
290} // End of isDST()
291
static long Calendar2Julian(int mon, int day, int year)
Definition: moon.c++:235
static double flmoon(int n, int nph, long &jd, double &frac)
Definition: moon.c++:162
static const long IGREG
Definition: moon.h:73
static const double RAD
Radians to degree convertion.
Definition: moon.h:70
static double phase(int mon, int day, int year)
Definition: moon.c++:30
static void nextphase(int &mon, int &day, int &year, int &hr, int &min, int nph)
Definition: moon.c++:120
static const double MEAN_LUNAR_CYCLE
Definition: moon.h:75
static bool isDST(long jd)
Definition: moon.c++:258
static void Julian2Calendar(long jd, int &mon, int &day, int &year)
Definition: moon.c++:205