1
/* (C) Mike Henderson <mghenderson@lanl.gov>.
3
* I've converted to glib types, removed unused variables and
4
* piped the whole thing through indent.
6
* Josh Buhl <jbuhl@users.sourceforge.net>
12
#include "CalcEphem.h"
16
static gdouble kepler(gdouble M, gdouble e)
19
gdouble E, Eold, eps = 1.0e-8;
24
E = Eold + (M - Eold + e * sin(Eold))
25
/ (1.0 - e * cos(Eold));
27
} while ((fabs(E - Eold) > eps) && (n < 100));
31
static gint DayofYear(gint year, gint month, gint day)
34
return ((gint) (jd(year, month, day, 0.0) - jd(year, 1, 0, 0.0)));
38
static gint DayofWeek(gint year, gint month, gint day, gchar dowstr[])
40
gdouble JD, A, Afrac, jd();
43
JD = jd(year, month, day, 0.0);
46
Afrac = A - (gdouble) iA;
47
n = (gint) (Afrac * 7.0 + 0.5);
50
strcpy(dowstr, "Sunday");
53
strcpy(dowstr, "Monday");
56
strcpy(dowstr, "Tuesday");
59
strcpy(dowstr, "Wednesday");
62
strcpy(dowstr, "Thursday");
65
strcpy(dowstr, "Friday");
68
strcpy(dowstr, "Saturday");
75
* Compute the Julian Day number for the given date.
76
* Julian Date is the number of days since noon of Jan 1 4713 B.C.
78
gdouble jd(gint ny, gint nm, gint nd, gdouble UT)
80
gdouble A, B, C, D, JD, day;
85
if ((nm == 1) || (nm == 2)) {
90
if (((gdouble) ny + nm / 12.0 + day / 365.25) >=
91
(1582.0 + 10.0 / 12.0 + 15.0 / 365.25)) {
92
A = ((gint) (ny / 100.0));
93
B = 2.0 - A + (gint) (A / 4.0);
99
C = (gint) ((365.25 * (gdouble) ny) - 0.75);
101
C = (gint) (365.25 * (gdouble) ny);
104
D = (gint) (30.6001 * (gdouble) (nm + 1));
107
JD = B + C + D + day + 1720994.5;
111
gdouble hour24(gdouble hour)
116
n = (gint) (hour / 24.0) - 1;
117
return (hour - n * 24.0);
118
} else if (hour > 24.0) {
119
n = (gint) (hour / 24.0);
120
return (hour - n * 24.0);
126
gdouble angle2pi(gdouble angle)
133
n = (gint) (angle / a) - 1;
134
return (angle - n * a);
135
} else if (angle > a) {
136
n = (gint) (angle / a);
137
return (angle - n * a);
143
static gdouble angle360(gdouble angle)
148
n = (gint) (angle / 360.0) - 1;
149
return (angle - n * 360.0);
150
} else if (angle > 360.0) {
151
n = (gint) (angle / 360.0);
152
return (angle - n * 360.0);
159
static void Radec_to_Cart(gdouble ra, gdouble dec, Vector * r)
163
* Convert ra/dec from degrees to radians
170
* Compute cartesian coordinates (in GEI)
172
r->x = cos(dec) * cos(ra);
173
r->y = cos(dec) * sin(ra);
181
static gint LeapYear(gint year)
183
if ((year % 100 == 0) && (year % 400 != 0))
185
else if (year % 4 == 0)
192
void CalcEphem(glong date, gdouble UT, CTrans * c)
194
gint year, month, day;
195
gdouble TU, TU2, TU3, T0, gmst;
196
gdouble varep, varpi;
197
gdouble eccen, epsilon;
198
gdouble days, M, E, nu, lambnew;
199
gdouble r0, earth_sun_distance;
200
gdouble RA, DEC, RA_Moon, DEC_Moon;
203
gdouble LambdaMoon, BetaMoon, R;
204
gdouble Ta, Tb, Tc, frac();
205
gdouble SinGlat, CosGlat, SinGlon, CosGlon, Tau, lmst, x, y, z;
206
gdouble SinTau, CosTau, SinDec, CosDec;
210
year = (gint) (date / 10000);
211
month = (gint) ((date - year * 10000) / 100);
212
day = (gint) (date - year * 10000 - month * 100);
217
c->doy = DayofYear(year, month, day);
218
c->dow = DayofWeek(year, month, day, c->dowstr);
222
* Compute Greenwich Mean Sidereal Time (gmst)
223
* The TU here is number of Julian centuries
224
* since 2000 January 1.5
225
* From the 1996 astronomical almanac
227
TU = (jd(year, month, day, 0.0) - 2451545.0) / 36525.0;
231
(6.0 + 41.0 / 60.0 + 50.54841 / 3600.0) +
232
8640184.812866 / 3600.0 * TU + 0.093104 / 3600.0 * TU2 -
233
6.2e-6 / 3600.0 * TU3;
236
c->gmst = hour24(T0 + UT * 1.002737909);
238
/* convert to radians for ease later on */
239
gmst = c->gmst * 15.0 * M_PI / 180.0;
241
lmst = 24.0 * frac((c->gmst - c->Glon / 15.0) / 24.0);
245
* Construct Transformation Matrix from GEI to GSE systems
249
* mean ecliptic longitude of sun at epoch TU (varep)
250
* elciptic longitude of perigee at epoch TU (varpi)
251
* eccentricity of orbit at epoch TU (eccen)
253
* The TU here is the number of Julian centuries since
254
* 1900 January 0.0 (= 2415020.0)
256
TDT = UT + 59.0 / 3600.0;
257
TU = (jd(year, month, day, TDT) - 2415020.0) / 36525.0;
259
(279.6966778 + 36000.76892 * TU +
260
0.0003025 * TU * TU) * RadPerDeg;
262
(281.2208444 + 1.719175 * TU +
263
0.000452778 * TU * TU) * RadPerDeg;
264
eccen = 0.01675104 - 0.0000418 * TU - 0.000000126 * TU * TU;
265
c->eccentricity = eccen;
268
* Compute the Obliquity of the Ecliptic at epoch TU
269
* The TU in this formula is the number of Julian
270
* centuries since epoch 2000 January 1.5
272
TU = (jd(year, month, day, TDT) - jd(2000, 1, 1, 12.0)) / 36525.0;
273
epsilon = (23.43929167 - 0.013004166 * TU - 1.6666667e-7 * TU * TU
274
- 5.0277777778e-7 * TU * TU * TU) * RadPerDeg;
275
c->epsilon = epsilon;
279
* Number of Days since epoch 1990.0 (days)
280
* The Mean Anomaly (M)
281
* The True Anomaly (nu)
282
* The Eccentric Anomaly via Keplers equation (E)
286
days = jd(year, month, day, TDT) - jd(year, month, day, TDT);
287
M = angle2pi(2.0 * M_PI / 365.242191 * days + varep - varpi);
288
E = kepler(M, eccen);
290
2.0 * atan(sqrt((1.0 + eccen) / (1.0 - eccen)) * tan(E / 2.0));
291
lambnew = angle2pi(nu + varpi);
292
c->lambda_sun = lambnew;
295
* Compute distance from earth to the sun
297
r0 = 1.495985e8; /* in km */
299
r0 * (1 - eccen * eccen) / (1.0 + eccen * cos(nu)) / 6371.2;
300
c->earth_sun_dist = earth_sun_distance;
303
* Compute Right Ascension and Declination of the Sun
306
angle360(atan2(sin(lambnew) * cos(epsilon), cos(lambnew)) *
308
DEC = asin(sin(epsilon) * sin(lambnew)) * 180.0 / M_PI;
313
* Compute Moon Phase and AGE Stuff. The AGE that comes out of Moon()
314
* is actually the Phase converted to days. Since AGE is actually defined
315
* to be time since last NewMoon, we need to figure out what the JD of the
316
* last new moon was. Thats done below....
318
TU = (jd(year, month, day, TDT) - 2451545.0) / 36525.0;
319
c->MoonPhase = Moon(TU, &LambdaMoon, &BetaMoon, &R, &AGE);
320
LambdaMoon *= RadPerDeg;
321
BetaMoon *= RadPerDeg;
326
(sin(LambdaMoon) * cos(epsilon) -
327
tan(BetaMoon) * sin(epsilon),
328
cos(LambdaMoon)) * DegPerRad);
330
asin(sin(BetaMoon) * cos(epsilon) +
331
cos(BetaMoon) * sin(epsilon) * sin(LambdaMoon)) *
333
c->RA_moon = RA_Moon;
334
c->DEC_moon = DEC_Moon;
337
* Compute Alt/Az coords
339
Tau = (15.0 * lmst - RA_Moon) * RadPerDeg;
340
CosGlat = cos(c->Glat * RadPerDeg);
341
SinGlat = sin(c->Glat * RadPerDeg);
342
CosGlon = cos(c->Glon * RadPerDeg);
343
SinGlon = sin(c->Glon * RadPerDeg);
346
SinDec = sin(DEC_Moon * RadPerDeg);
347
CosDec = cos(DEC_Moon * RadPerDeg);
348
x = CosDec * CosTau * SinGlat - SinDec * CosGlat;
350
z = CosDec * CosTau * CosGlat + SinDec * SinGlat;
351
c->A_moon = DegPerRad * atan2(y, x) + 180.0;
352
c->h_moon = DegPerRad * asin(z);
353
c->Visible = (c->h_moon < 0.0) ? 0 : 1;
356
* Compute accurate AGE of the Moon
358
Tb = TU - AGE / 36525.0; /* should be very close to minimum */
359
Ta = Tb - 0.4 / 36525.0;
360
Tc = Tb + 0.4 / 36525.0;
361
c->MoonAge = (TU - NewMoon(Ta, Tb, Tc)) * 36525.0;
364
* Set Earth-Moon distance (calc above w/ func Moon)
366
c->EarthMoonDistance = R;
369
c->SinGlat = SinGlat;
370
c->CosGlat = CosGlat;