From c51ef797a707f4e2c6f9688d4378f2b0e9898a66 Mon Sep 17 00:00:00 2001 From: Perberos Date: Thu, 1 Dec 2011 22:56:10 -0300 Subject: moving from https://github.com/perberos/mate-desktop-environment --- applets/clock/clock-sunpos.c | 197 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 applets/clock/clock-sunpos.c (limited to 'applets/clock/clock-sunpos.c') diff --git a/applets/clock/clock-sunpos.c b/applets/clock/clock-sunpos.c new file mode 100644 index 00000000..2103fd90 --- /dev/null +++ b/applets/clock/clock-sunpos.c @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2007 Red Hat, Inc. + * + * 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. + * + * Authors: + * Jonathan Blandford + * Matthias Clasen + */ + +#include +#include +#include +#include "clock-sunpos.h" + +/* Calculated with the methods and figures from "Practical Astronomy With Your + * Calculator, version 3" by Peter Duffet-Smith. + */ +/* Table 6. Details of the Sun's apparent matecorba at epoch 1990.0 */ + +#define EPOCH 2447891.5 /* days */ /* epoch 1990 */ +#define UNIX_EPOCH 2440586.5 /* days */ /* epoch 1970 */ +#define EPSILON_G 279.403303 /* degrees */ /* ecliptic longitude at epoch 1990.0 */ +#define MU_G 282.768422 /* degrees */ /* ecliptic longitude at perigee */ +#define ECCENTRICITY 0.016713 /* eccentricity of matecorba */ +#define R_0 149598500 /* km */ /* semi-major axis */ +#define THETA_0 0.533128 /* degrees */ /* angular diameter at r = r_0 */ +#define MEAN_OBLIQUITY 23.440592 /* degrees */ /* mean obliquity of earth's axis at epoch 1990.0 */ + +#define NORMALIZE(x) \ + while (x>360) x-=360; while (x<0) x+= 360; + +#define DEG_TO_RADS(x) \ + (x * G_PI/180.0) + +#define RADS_TO_DEG(x) \ + (x * 180.0/G_PI) + +/* Calculate number of days since 4713BC. + */ +static gdouble +unix_time_to_julian_date (gint unix_time) +{ + return UNIX_EPOCH + (double) unix_time / (60 * 60 * 24); +} + +/* Finds an iterative solution for [ E - e sin (E) = M ] for values of e less + than 0.1. Page 90 */ + +#define ERROR_ACCURACY 1e-6 /* radians */ + +static gdouble +solve_keplers_equation (gdouble e, + gdouble M) +{ + gdouble d, E; + + /* start with an initial estimate */ + E = M; + + d = E - e * sin (E) - M; + + while (ABS (d) > ERROR_ACCURACY) + { + E = E - (d / (1 - e * cos (E))); + d = E - e * sin (E) - M; + } + + return E; +} + + /* convert the ecliptic longitude to right ascension and declination. Section 27. */ +static void +ecliptic_to_equatorial (gdouble lambda, + gdouble beta, + gdouble *ra, + gdouble *dec) +{ + gdouble cos_mo; + gdouble sin_mo; + + g_assert (ra != NULL); + g_assert (dec != NULL); + + sin_mo = sin (DEG_TO_RADS (MEAN_OBLIQUITY)); + cos_mo = cos (DEG_TO_RADS (MEAN_OBLIQUITY)); + + *ra = atan2 (sin (lambda) * cos_mo - tan (beta) * sin_mo, cos (lambda)); + *dec = asin (sin (beta) * cos_mo + cos (beta) * sin_mo * sin (lambda)); +} + +/* calculate GST. Section 12 */ +static gdouble +greenwich_sidereal_time (gdouble unix_time) +{ + gdouble u, JD, T, T0, UT; + + u = fmod (unix_time, 24 * 60 * 60); + JD = unix_time_to_julian_date (unix_time - u); + T = (JD - 2451545) / 36525; + T0 = 6.697374558 + (2400.051336 * T) + (0.000025862 * T * T); + T0 = fmod (T0, 24); + UT = u / (60 * 60); + T0 = T0 + UT * 1.002737909; + T0 = fmod (T0, 24); + + return T0; +} + +/* Calculate the position of the sun at a given time. pages 89-91 */ +void +sun_position (time_t unix_time, gdouble *lat, gdouble *lon) +{ + gdouble jd, D, N, M, E, x, v, lambda; + gdouble ra, dec; + jd = unix_time_to_julian_date (unix_time); + + /* Calculate number of days since the epoch */ + D = jd - EPOCH; + + N = D*360/365.242191; + + /* normalize to 0 - 360 degrees */ + NORMALIZE (N); + + /* Step 4: */ + M = N + EPSILON_G - MU_G; + NORMALIZE (M); + + /* Step 5: convert to radians */ + M = DEG_TO_RADS (M); + + /* Step 6: */ + E = solve_keplers_equation (ECCENTRICITY, M); + + /* Step 7: */ + x = sqrt ((1 + ECCENTRICITY)/(1 - ECCENTRICITY)) * tan (E/2); + + /* Step 8, 9 */ + v = 2 * RADS_TO_DEG (atan (x)); + NORMALIZE (v); + + /* Step 10 */ + lambda = v + MU_G; + NORMALIZE (lambda); + + /* convert the ecliptic longitude to right ascension and declination */ + ecliptic_to_equatorial (DEG_TO_RADS (lambda), 0.0, &ra, &dec); + + ra = ra - (G_PI/12) * greenwich_sidereal_time (unix_time); + ra = RADS_TO_DEG (ra); + dec = RADS_TO_DEG (dec); + NORMALIZE (ra); + NORMALIZE (dec); + + *lat = dec; + *lon = ra; +} + + +#if 0 +int +main (int argc, char *argv[]) +{ + gint i; + gint now; + GTimeVal timeval; + gdouble lat, lon; + + gtk_init (&argc, &argv); + + g_get_current_time (&timeval); + now = timeval.tv_sec; + + for (i = 0; i < now; i += 15 * 60) + { + sun_position (i, &lat, &lon); + g_print ("%d: %f %f\n", lat, lon); + } + + return 0; +} + +#endif -- cgit v1.2.1