-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathastronomy.c
195 lines (167 loc) · 5.42 KB
/
astronomy.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/* $Id: astronomy.c,v 1.2 2003/03/19 23:39:21 d3august Exp $ */
/* xtraceroute - graphically show traceroute information.
* Copyright (C) 1996-2003 Björn Augustsson
* Copyright (C) 2002 Hari Nair <hari@alumni.caltech.edu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <time.h>
#include <math.h>
#include "xt.h"
/* Most of this code was cheerfully stolen from the excellent xplanet
* by Hari Nair <hari@alumni.caltech.edu>
* see http://xplanet.sourceforge.net/
*
* Some of this code is (to me anyway) pretty scary. There are _a_lot_
* of magic numbers in here, and I don't understand all of it. So don't
* expect me to explain this stuff to you... :)
*
* /August.
*/
static double
julian(int year, int month, int day, int hour, int min, int sec)
{
if(month < 3)
{
year -= 1;
month += 12;
}
// assume it's the Gregorian calendar (after 1582 Oct 15)
{
int a = year/100;
int b = 2 - a + a/4;
int c = (int)(365.25 * year);
int d = (int)(30.6001 * (month + 1));
double e = day + ((sec/60. + min) / 60. + hour) / 24.;
double jd = b + c + d + e + 1720994.5;
return(jd);
}
}
static double
julianCentury(const time_t tv_sec)
{
double jd = julian(gmtime(&tv_sec)->tm_year + 1900,
gmtime(&tv_sec)->tm_mon + 1,
gmtime(&tv_sec)->tm_mday,
gmtime(&tv_sec)->tm_hour,
gmtime(&tv_sec)->tm_min,
gmtime(&tv_sec)->tm_sec);
return((jd - 2415020)/36525);
}
/* Really scary function. */
static double
poly(const double a1, const double a2, const double a3, const double a4,
const double t)
{
return(a1 + t*(a2 + t*(a3 + t*a4)));
}
/* Solve kepler's equation. */
static double
kepler(const double e, const double M)
{
double E = M;
double delta = 1.0;
while (fabs(delta) > 1E-10)
{
delta = (M + e * sin(E) - E)/(1.0 - e * cos(E));
E += delta;
}
return(E);
}
static double
gmst(const double T, const time_t tv_sec)
{
// Sidereal time at Greenwich at 0 UT
double g = poly(6.6460656, 2400.051262, 0.00002581, 0, T);
// Now find current sidereal time at Greenwich
double currgmt = (gmtime(&tv_sec)->tm_hour
+ gmtime(&tv_sec)->tm_min/60.
+ gmtime(&tv_sec)->tm_sec/3600.);
currgmt *= 1.002737908;
g += currgmt;
g = fmod(g, 24.0);
if (g < 0) g += 24;
return(g);
}
/* Return the current sun position, in eclipitic coodinates. */
/* Based on Chapter 18 of Astronomical Formulae for Calculators by Meeus */
static void
sunpos(const double T, double* sunlat, double* sunlon)
{
double L = (poly(2.7969668E2, 3.600076892E4, 3.025E-4, 0, T)
* torad);
double M = (poly(3.5847583E2, 3.599904975E4, -1.5E-4, -3.3E-6, T)
* torad);
/* Eccentricity of the Earth's orbit. */
double ecc = poly(1.675104E-2, -4.18E-5, -1.26E-7, 0, T);
/* Eccentric anomaly. */
double eccanom = kepler(ecc, M);
double nu = 2.0 * atan(sqrt((1.0+ecc) / (1.0-ecc)) * tan(eccanom / 2.0));
double theta = L + nu - M;
*sunlon = theta;
*sunlat = 0.0;
// sundist = 1.0000002 * (1 - ecc * cos(eccanom));
}
/**
* This converts a position (lat, lon) in the ecliptic plane (the sun's
* plane) to a "normal" position, ie the position on earth where the
* sun is in zenith.
*
* NOTE: All lat, lon values are in radians!
*
* I could optimize this a bit. Since I'm always interested in the suns's
* position, the ec_lat value is always zero. Doesn't matter though.
*/
static void
eclipticToEquatorial(const double ec_lon, const double ec_lat,
const double eps,
double *eq_lon, double *eq_lat)
{
*eq_lat = asin(sin(eps)*sin(ec_lon)*cos(ec_lat) + sin(ec_lat)*cos(eps));
*eq_lon = atan2(cos(eps)*sin(ec_lon) - tan(ec_lat)*sin(eps), cos(ec_lon));
}
/* I have no idea what this does... */
/* 23.452294 might be angle (in degrees) between the earths' and the
suns' orbital planes. Or something. */
static double
calcObliquity(const double T)
{
return (poly(23.452294, -1.30125E-2, -1.64E-6, 5.03E-7, T)
* torad);
}
/**
* Figure out where the sun is, from current time
*
* NOTE: The lat, lon values "returned" are in radians!
*/
void
get_sun_position(double* lat, double* lon)
{
const time_t t = time(NULL);
// gmtime here?
const double jt = julianCentury(t);
const double eps = calcObliquity(jt);
double ec_lat, ec_lon;
double mylat, mylon;
double gst = 2.0*M_PI * gmst(jt, t) / 24;
sunpos(jt, &ec_lat, &ec_lon);
/* Ah, but these are eclipitic coodinates! Better convert them. */
eclipticToEquatorial(ec_lon, ec_lat, eps, &mylon, &mylat);
mylon -= gst;
/* These (lat, lon) values are in radians. */
*lat = mylat;
*lon = mylon;
}