/* moondata.c
*
* Copyright (C) 2000-2004 josh buhl <jbuhl@users.sourceforge.net>
*
* 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 <config.h>
#endif
#include <gnome.h>
#include <time.h>
#include <X11/X.h> /* need this for CurrentTime */
#include <glade/glade-xml.h>
#include <glade/glade.h>
#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 <time.h> */
gdouble local_std_time, univ_time, eot;
glong current_gmt, date;
gint day_of_month, month, year;
current_gmt = time(CurrentTime);/* CurrentTime defined in <X11/X.h> */
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);
}
syntax highlighted by Code2HTML, v. 0.9.1