/* moondata.c * * Copyright (C) 2000-2004 josh buhl * * 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, 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 (see the file COPYING); if not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA * */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include /* need this for CurrentTime */ #include #include #include "MoonRise.h" #include "moondata.h" #include "CalcEphem.h" #define RADIUS_OF_EARTH 6371 /* kilometers */ typedef struct CTrans MoonData; typedef struct _MoonWidgets MoonWidgets; struct _MoonWidgets { GtkWidget *lst; /* local standard time */ GtkWidget *lmt; /* local mean time */ GtkWidget *lat; /* local apparent time */ GtkWidget *lsdt; /* local sidereal time */ GtkWidget *ut; /* greenwich mean time */ GtkWidget *frc; /* fraction of cycle completed */ GtkWidget *flm; /* days to full moon */ GtkWidget *nwm; /* days to new moon */ GtkWidget *vis; /* whether moon is above horizon */ GtkWidget *uys; /* moon-up yesterday */ GtkWidget *utd; /* moon-up today */ GtkWidget *utm; /* moon-up tomorrow */ GtkWidget *dys; /* moon-down yesterday */ GtkWidget *dtd; /* moon-down today */ GtkWidget *dtm; /* moon-down tomorrow */ GtkWidget *ra; /* right ascension of moon */ GtkWidget *dec; /* declination of moon */ GtkWidget *az; /* azimuth of moon */ GtkWidget *alt; /* altitude of moon */ GtkWidget *dist; /* distance from earth */ }; MoonData moondata; MoonWidgets mw; gboolean visible() { return moondata.Visible; } gdouble moonphase() { return moondata.MoonPhase; } static void format_time(gchar * buf, gint size, gdouble time) { gint hour, min, sec; hour = (gint) (time); min = (gint) ((ABS(time - hour)) * 60); sec = (gint) (ABS(ABS((time - hour)*60)-min)*60); g_snprintf(buf, size, "%02d:%02d:%02d", hour, min, sec); return; } static void mod_time(gdouble * time) { g_assert(time); if (*time < 0.0) *time += 24.0; else if (*time > 24.0) *time -= 24.0; return; } static void format_angle_hours(gchar * buf, gint size, gdouble angle) { gint hour, min, sec; hour = (gint) (angle / 15.0); min = (gint) ((ABS(angle - hour * 15.0)) * 4.0); sec = (gint) (ABS(ABS((angle - hour * 15.0)*4.0)-min)*60); g_snprintf(buf, size, "%02d:%02d:%02d", hour, min, sec); return; } static void calc_riseset_time(gchar * buf, gchar * buf2, gint size, CTrans * c) { gdouble rise, set; MoonRise(c, &rise, &set); if (ABS(rise) > 24.0) g_snprintf(buf, size, _("no rise")); else{ /* rise = rise + (moondata.LST-moondata.UT); */ /* mod_time(&rise); */ format_time(buf, size, rise); } if (ABS(set) > 24.0) g_snprintf(buf2, size, _("no set")); else{ /* set = set + (moondata.LST-moondata.UT); */ /* mod_time(&set); */ format_time(buf2, size, set); } } void update_moondata(MoonApplet * moon) { struct tm *time_struc; /* The tm struct is defined in */ gdouble local_std_time, univ_time, eot; glong current_gmt, date; gint day_of_month, month, year; current_gmt = time(CurrentTime);/* CurrentTime defined in */ time_struc = gmtime(¤t_gmt); univ_time = time_struc->tm_hour + time_struc->tm_min / 60.0 + time_struc->tm_sec / 3600.0; /* The date needs to be the date in UTC, i.e. in greenwich, so * be sure not to call the localtime function until after date * has been set (there's only one tm structure). */ year = time_struc->tm_year + 1900; month = time_struc->tm_mon + 1; day_of_month = time_struc->tm_mday; date = year * 10000 + month * 100 + day_of_month; time_struc = localtime(¤t_gmt); local_std_time = time_struc->tm_hour + time_struc->tm_min / 60.0 + time_struc->tm_sec / 3600.0; /* CalcEphem assumes longitude degrees west to be positive * and degrees east negative. I think the opposite convention * is more intuitive, since degrees east means you add * time to gmt, but we'll stick to CalcEphem's convention to * prevent mixups. */ moondata.Glat = moon->is_north ? moon->latitude : -moon->latitude; moondata.Glon = moon->is_east ? -moon->longitude : moon->longitude ; CalcEphem(date, univ_time, &moondata); /* eot is the equation of time. gmst is Greenwich Sidereal * Time. This equation below is correct, but confusing at * first. It's easy to see when you draw the following * picture: A sphere with 0 and 180 degree longitude, North on * top, a meridian for the real sun, a meridian for a fictive * average sun, a meridian denoting the vernal equinox. Note * that universal time is the hour angle between 180 degrees * and the fictive sun's meridian measured clockwise. gmst is * the hour angle between 0 degrees and the meridian of the * vernal equinox measured clockwise. RA_sun/15.0 is the hour * angle of the real sun measured counterclockwise from the * vernal equinox. eot is the difference between the real and * the fictive sun. Looking at the picture, it's easy to see * that 12=RA_sun/15-gmst+eot+utc (12 hours = 180 deg.) */ eot = 12.0 - univ_time + moondata.gmst - moondata.RA_sun / 15.0; mod_time(&eot); moondata.LST = local_std_time; moondata.LMT = univ_time - moondata.Glon / 15.0; mod_time(&moondata.LMT); moondata.LSD = (moondata.gmst - moondata.Glon / 15.0); mod_time(&moondata.LSD); moondata.LAT = moondata.LMT + eot; mod_time(&moondata.LAT); } static gboolean delete_event (GtkWidget *widget, MoonApplet *moon) { gtk_widget_hide (widget); } static gboolean close_data_dialog (GtkWidget *widget, MoonApplet *moon) { gtk_widget_hide (moon->moondata_dialog); } static void handle_data_response (GtkWidget *widget, int id, MoonApplet *moon) { if (id == GTK_RESPONSE_HELP) { show_help (moon, "glunarclock-detailed"); return; } gtk_widget_hide (moon->moondata_dialog); } void update_moondata_dialog(MoonApplet * moon) { const gint size = 64; gchar buf[size]; gchar buf2[size]; format_time(buf, size, moondata.LST); gtk_label_set_text(GTK_LABEL(mw.lst), buf); format_time(buf, size, moondata.LMT); gtk_label_set_text(GTK_LABEL(mw.lmt), buf); format_time(buf, size, moondata.LAT); gtk_label_set_text(GTK_LABEL(mw.lat), buf); format_time(buf, size, moondata.LSD); gtk_label_set_text(GTK_LABEL(mw.lsdt), buf); format_time(buf, size, moondata.UT); gtk_label_set_text(GTK_LABEL(mw.ut), buf); g_snprintf(buf, size, "%4.2f%%", 100.0 * moondata.MoonPhase); gtk_label_set_text(GTK_LABEL(mw.frc), buf); /* g_snprintf(buf, size, _("%4.2f Days"), moondata.MoonAge); */ /* gtk_label_set_text(GTK_LABEL(mw.age), buf); */ /* g_snprintf(buf, size, "%6.4f%%", */ /* 50.0 * (1.0 - cos(moondata.MoonPhase * 6.2831853))); */ /* gtk_label_set_text(GTK_LABEL(mw.ilm), buf); */ /* format_time(buf, size, moondata.NewMoon*24.0); */ g_snprintf(buf, size, _("%2d%"),(gint)moondata.FullMoon); gtk_label_set_text(GTK_LABEL(mw.flm), buf); g_snprintf(buf, size, "%2d%",(gint)(moondata.NewMoon)); gtk_label_set_text(GTK_LABEL(mw.nwm), buf); /* g_snprintf(buf, size, _("%8.4f Hours"), moondata.NewMoon*24.0); */ /* gtk_label_set_text(GTK_LABEL(mw.nwm), buf); */ g_snprintf(buf, size, (moondata.Visible) ? _("Yes") : _("No")); gtk_label_set_text(GTK_LABEL(mw.vis), buf); /* Changing the moon data to get the rise and set times for yesterday and tomorrow is a hack. Besides, it's not exactly correct. I don't really want to create two more MoonData and then CalcEphem them, since that would be a total of three calls to CalcEphem (which is computationally expensive) for every update, i.e. once a second. Suggestions? */ moondata.day -= 1; calc_riseset_time(buf, buf2, size, &moondata); gtk_label_set_text(GTK_LABEL(mw.uys), buf); gtk_label_set_text(GTK_LABEL(mw.dys), buf2); moondata.day += 2; calc_riseset_time(buf, buf2, size, &moondata); gtk_label_set_text(GTK_LABEL(mw.utm), buf); gtk_label_set_text(GTK_LABEL(mw.dtm), buf2); moondata.day -= 1; calc_riseset_time(buf, buf2, size, &moondata); gtk_label_set_text(GTK_LABEL(mw.utd), buf); gtk_label_set_text(GTK_LABEL(mw.dtd), buf2); /* end hack */ format_angle_hours(buf, size, moondata.RA_moon); gtk_label_set_text(GTK_LABEL(mw.ra), buf); format_time(buf, size, moondata.DEC_moon); gtk_label_set_text(GTK_LABEL(mw.dec), buf); format_time(buf, size, moondata.A_moon); gtk_label_set_text(GTK_LABEL(mw.az), buf); format_time(buf, size, moondata.h_moon); gtk_label_set_text(GTK_LABEL(mw.alt), buf); g_snprintf(buf, size, "%6.0f km", (moondata.EarthMoonDistance)*(RADIUS_OF_EARTH)); gtk_label_set_text(GTK_LABEL(mw.dist), buf); } static void set_moonwidgets(GladeXML * xml) { mw.lst = glade_xml_get_widget (xml, "lst"); mw.lmt = glade_xml_get_widget (xml, "lmt"); mw.lat = glade_xml_get_widget (xml, "lat"); mw.lsdt= glade_xml_get_widget (xml, "lsdt"); mw.ut = glade_xml_get_widget (xml, "ut"); /* mw.age = glade_xml_get_widget (xml, "age"); */ mw.frc = glade_xml_get_widget (xml, "frc"); /* mw.ilm = glade_xml_get_widget (xml, "ilm"); */ mw.flm = glade_xml_get_widget (xml, "flm"); mw.nwm = glade_xml_get_widget (xml, "nwm"); mw.vis = glade_xml_get_widget (xml, "vis"); mw.uys = glade_xml_get_widget (xml, "uys"); mw.utd = glade_xml_get_widget (xml, "utd"); mw.utm = glade_xml_get_widget (xml, "utm"); mw.dys = glade_xml_get_widget (xml, "dys"); mw.dtd = glade_xml_get_widget (xml, "dtd"); mw.dtm = glade_xml_get_widget (xml, "dtm"); mw.ra = glade_xml_get_widget (xml, "ra"); mw.dec = glade_xml_get_widget (xml, "dec"); mw.az = glade_xml_get_widget (xml, "az"); mw.alt = glade_xml_get_widget (xml, "alt"); mw.dist= glade_xml_get_widget (xml, "dist"); } void display_moondata_dialog (MoonApplet * moon) { GladeXML *xml; GtkWidget *button; if (moon->moondata_dialog) { gtk_window_set_screen (GTK_WINDOW (moon->moondata_dialog), gtk_widget_get_screen (GTK_WIDGET (moon))); gtk_window_present (GTK_WINDOW (moon->moondata_dialog)); return; } xml = glade_xml_new (MOON_GLADEDIR "/glunarclock.glade", "moon_data_dialog", NULL); moon->moondata_dialog = glade_xml_get_widget (xml, "moon_data_dialog"); set_moonwidgets(xml); /* gtk_window_set_wmclass (GTK_WINDOW (moon->moondata_dialog), "moon", "Moon"); */ gtk_dialog_set_default_response ( GTK_DIALOG (moon->moondata_dialog), GTK_RESPONSE_CLOSE); gnome_window_icon_set_from_file ( GTK_WINDOW (moon->moondata_dialog), GNOME_ICONDIR"/glunarclock-logo.png"); g_signal_connect (moon->moondata_dialog, "delete_event", G_CALLBACK (delete_event), moon); g_signal_connect (moon->moondata_dialog, "response", G_CALLBACK (handle_data_response), moon); button = glade_xml_get_widget (xml, "close_button"); g_signal_connect (button, "clicked", G_CALLBACK (close_data_dialog), moon); update_moondata_dialog (moon); gtk_window_set_screen (GTK_WINDOW (moon->moondata_dialog), gtk_widget_get_screen (GTK_WIDGET (moon))); gtk_window_present (GTK_WINDOW (moon->moondata_dialog)); g_object_unref (xml); }