home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-08-08 | 34.5 KB | 1,123 lines |
- /*
- Moon Tool for the Archimedes
- ============================
-
- Sun Workstation version ................ John Walker
- Archimedes Risc OS 3.1 port ............ Edouard Poor
-
- This program is in the public domain:
- "Do what thou wilt shall be the whole of the law".
-
-
- Introduction
- ============
-
- MoonTool is a program designed give you the following infomation:
-
- o Phase of the Moon
-
- o Age of the Moon
-
- o Distance to the moon
-
- o Dates of the Last and Next New moon as well as the First and
- Last Quarters and the Full Moon.
-
- o Angle the Moon subtends
-
- In addition it also gives you information about:
-
- o Time and Date in Julian, Local and Universal (GMT) times.
-
- o Distance to the Sun
-
- o Angle the Sun subtends
-
- An invaluable tool for those of you who don't like going outside to look
- at the moon, all the nethack players among you, astronomers who like
- to know when the moon it new and thus the stars are at their best viewing,
- or indeed anyone who just really needs to exactly how far away the moon
- and sun are...
-
-
- Interface
- =========
-
- The program starts up in it's iconised mode, giving you a simple window
- with a single button displaying a picture of the moon as it appears
- in the sky. You can move the window with its title bar, or click on the
- icon to bring up the full, un-iconised, view.
-
- In un-iconised mode you are presented with all the information about the
- current time, the moons distance and age, the suns distance, and the
- "Moon Phase" icon. Looking to the top right of the window you will see
- that it has a full-size icon; clicking on this will reveal additional
- information about the dates of the phases of the moon (all in UTC, or
- Universal Time).
-
- Clicking again on the "Moon Phase" icon of the moons current appearance
- will put the program back into iconised mode.
-
- Quitting the prgram simply consists of closing the window when it is
- in un-iconised mode.
-
-
- Risc OS 3.1 Notes
- =================
-
- This program needs both Local Time and Greenwich Mean Time set up
- correctly in your machine.
-
- This requires two things-- Firstly setting the configured time in your
- machine to Greenwich Mean Time then getting the time correct for
- where you live by setting the Congfiguration Setting 'TimeZone' (you
- can type "help TimeZone" on the command line). This step will probably
- be unnessesary in the UK where you are on GMT anyway...
- Where I live (in New Zealand) I use "configure TimeZone +12:0"
-
- The second step is to do with daylight savings-- Use !Alarm to toggle
- between daylight savings on and off instead of altering the time or
- the TimeZone offset. (Daylight Savings Time or DST is labeled 'BST'
- in !Alarms 'Set Time' window, which stands for British Summer Time,
- because Acorn is Very Good at Internationalisation...)
-
- If you set and maintain the time in the method outlined above, you
- will always be able to have the correct time, and be able to work
- out the time in GMT or UTC as well, as will any program that needs
- to know the time in both local and universal. C programs that use
- localtime() and gmtime(), for example, need this.
-
-
- Problems
- ========
-
- There are no problems or bugs with this program. It is perfect in every
- way and any difficulties you may experience are one of the three following
- people, or organisation's fault:
-
- o Yourself
-
- o Your Acorn Dealer
-
- o Acorn Computers Limited
-
- For example you might say "When I run !MoonTool on my RO2 machine it
- crashes" - This would be your fault for not purchasing Risc OS 3.1 yet.
-
- You might say "In 256 colour mode the button plinths in, but it also
- inverts as well" - This would be Acorns fault for not having better
- 'Kwality Kontrol' on its operating systems.
-
- Also someone might complain "When the moon behind a cloud I can't see it
- but I can still it on my computer. Could you set it up so that it's
- visiability is always the same as the real moon?" - This would be their
- dealers fault for selling a computer to someone whose IQ was obviously
- in the low 70's...
-
- In short, if you havn't worked it out yet, I take no responibility for
- anything at all to do with this program.
-
-
- To Be Done
- ==========
-
- Well everything is actually about as well done as it's likely to get,
- but if anyone wants to send me any improvments to the address below
- I'd be very grateful, and will release anothr version with your
- modifications and credit.
-
- Also if anyone can design me a better Filer Icon I'd be most happy
- to replace the one I've got at the moment...
-
- If anyone feels like spell checking this !Help file I'm sure hundreds,
- if not thousands, of english speakers around the world would be grateful
- to you :-)
-
-
- Author Info (Archimedes Version)
- ================================
-
- Send all snail mail/money orders/cheques/cash to:
- Edouard Poor
- 15 Stanley Pt Rd
- Devonport
- Auckland
- New Zealand
-
- Email/uu-files may be addressed to:
- epoo1@cs.aukuni.ac.nz (valid until at least March 1994)
- edouard@nacjack.gen.nz (not used very often)
-
- Voice line:
- +64 9 4450330
-
-
- Bibliography
- ============
-
- The algorithms used in this program to calculate the positions Sun and
- Moon as seen from the Earth are given in the book "Practical Astronomy
- With Your Calculator" by Peter Duffett-Smith, Second Edition, Cambridge
- University Press, 1981. Ignore the word "Calculator" in the title; this
- is an essential reference if you're interested in developing software
- which calculates planetary positions, orbits, eclipses, and the like. If
- you're interested in pursuing such programming, you should also obtain:
-
- "Astronomical Formulae for Calculators" by Jean Meeus, Third Edition,
- Willmann-Bell, 1985. A must-have.
-
- "Planetary Programs and Tables from -4000 to +2800" by Pierre Bretagnon
- and Jean-Louis Simon, Willmann-Bell, 1986. If you want the utmost
- (outside of JPL) accuracy for the planets, it's here.
-
- "Celestial BASIC" by Eric Burgess, Revised Edition, Sybex, 1985. Very
- cookbook oriented, and many of the algorithms are hard to dig out of the
- turgid BASIC code, but you'll probably want it anyway.
-
- Many of these references can be obtained from Willmann-Bell, P.O. Box
- 35025, Richmond, VA 23235, USA. Phone: (804) 320-7016. In addition to
- their own publications, they stock most of the standard references for
- mathematical and positional astronomy.
-
-
- Sun Workstation (Original) Author Info
- ======================================
-
- A Moon for the Sun
-
- Release 2.0
-
- Designed and implemented by John Walker in December 1987,
- revised and updated in February of 1988.
-
- This program was written by:
-
- John Walker
- Autodesk, Inc.
- 2320 Marinship Way
- Sausalito, CA 94965
- (415) 332-2344 Ext. 829
-
- Usenet: {sun!well}!acad!kelvin
-
- I'd appreciate receiving any bug fixes and/or enhancements, which I'll
- incorporate in future versions of the program. Please leave the original
- attribution information intact so that credit and blame may be properly
- apportioned.
-
-
- Source Code
- ===========
-
- Well it was originally compiled with my own personal library "QDD_Lib"
- but it uses very few calls, and they are all, unlike Acorns "RISC_OSLib"
- ones, very easy to read. It should be very easy for anyone with a C
- compiler and any set of wimp libraries to convert this program to
- compile under their own set-up.
-
- Enjoy.
-
- *
- *
- *
- * Astronomical constants
- */
- #define epoch 2444238.5 /* 1980 January 0.0 */
-
- /*
- * Constants defining the Sun's apparent orbit
- */
- #define elonge 278.833540 /* Ecliptic longitude of the Sun at epoch 1980.0 */
- #define elongp 282.596403 /* Ecliptic longitude of the Sun at perigee */
- #define eccent 0.016718 /* Eccentricity of Earth's orbit */
- #define sunsmax 1.495985e8 /* Semi-major axis of Earth's orbit, km */
- #define sunangsiz 0.533128 /* Sun's angular size, degs, at semi-major axis distance */
-
- /*
- * Elements of the Moon's orbit, epoch 1980.0
- */
- #define mmlong 64.975464 /* Moon's mean lonigitude at the epoch */
- #define mmlongp 349.383063 /* Mean longitude of the perigee at the epoch */
- #define mlnode 151.950429 /* Mean longitude of the node at the epoch */
- #define minc 5.145396 /* Inclination of the Moon's orbit */
- #define mecc 0.054900 /* Eccentricity of the Moon's orbit */
- #define mangsiz 0.5181 /* Moon's angular size at distance a from Earth */
- #define msmax 384401.0 /* Semi-major axis of Moon's orbit in km */
- #define mparallax 0.9507 /* Parallax at distance a from Earth */
- #define synmonth 29.53058868 /* Synodic month (new Moon to new Moon) */
- #define lunatbase 2423436.0 /* Base date for E. W. Brown's numbered series
- of lunations (1923 January 16) */
- /*
- * Properties of the Earth
- */
- #define earthrad 6378.16 /* Radius of Earth in kilometres */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include <time.h>
- #include <string.h>
- #include <stdarg.h>
-
- /*
- * Handy mathematical functions and constants
- */
- #define EPSILON 1E-6
- #define PI 3.14159265358979323846 /* Assume not near black hole nor in Tennessee */
- #define sgn(x) (((x) < 0) ? -1 : ((x) > 0 ? 1 : 0)) /* Extract sign */
- #define abs(x) ((x) < 0 ? (-(x)) : (x)) /* Absolute val */
- #define fixangle(a) ((a) - 360.0 * (floor((a) / 360.0))) /* Fix angle */
- #define torad(d) ((d) * (PI / 180.0)) /* Deg->Rad */
- #define todeg(d) ((d) * (180.0 / PI)) /* Rad->Deg */
- #define dsin(x) (sin(torad((x)))) /* Sin from deg */
- #define dcos(x) (cos(torad((x)))) /* Cos from deg */
-
- #define FALSE 0
- #define TRUE 1
-
- static int testmode = FALSE; /* Rapid warp through time for debugging */
- static int Iconised = TRUE;
-
- /* Forward functions */
-
- double jtime(struct tm *);
- double phase(double, double *, double *, double *, double *, double *, double *);
- void phasehunt(double, double *);
- void ringgg(void);
- void drawmoon(double);
- void jyear(double, int *, int *, int *);
- void jhms(double, int *, int *, int *);
-
- #define Plural(x) (x) == 1 ? "" : "s"
-
-
- /***********************************************/
-
- #include "Wimp.h"
- #include "GFX.h"
-
- #define Julian_Date 4
- #define Local_Time 7
- #define Local_Date 8
- #define Universal_Time 11
- #define Universal_Date 12
- #define Moon_Subtends 17
- #define MoonDistance_Kilometers 20
- #define MoonDistance_Radii 21
- #define MoonAge_Days 27
- #define MoonAge_Hours 28
- #define MoonAge_Minutes 29
- #define Sun_Subtends 34
- #define SunDistance_Kilometers 37
- #define SunDistance_AU 38
- #define Phases_LastNewMoon 45
- #define Phases_FirstQuarter 48
- #define Phases_FullMoon 51
- #define Phases_LastQuarter 54
- #define Phases_NextNewMoon 57
- #define Phases_CurrentLunation 61
-
- taskhandle OurTaskHandle;
- windowhandle MoonTool;
- windowhandle MoonIcon;
-
- char temp[128]; /* A temporary string buffer */
-
- /*
- * Useful Risc OS functions
- */
- void Icon_SmartPrint(iconhandle i, char *format, ...)
- {
- va_list argp;
- iconstate info;
- char *source;
- char *dest;
- int length;
-
- va_start(argp, format);
- vsprintf(temp, format, argp);
- va_end(argp);
-
- Wimp_GetIconState(MoonTool, i, &info);
-
- if(info.icon.flags.feild.indirected)
- {
- dest = info.icon.data.indirectedtext.buffer;
- length = info.icon.data.indirectedtext.bufflen-1;
- }
- else
- {
- dest = info.icon.data.text;
- length = 11;
- }
- source = temp;
-
- if(strncmp(dest, source, length) != 0)
- {
- strncpy(dest, source, length);
- Wimp_SetIconState(MoonTool, i, 0, 0);
- }
- }
-
-
- void StartWimp(void)
- {
- int i;
- int isize;
- int windowsize;
- BOOL fontspresent;
- window *moontoolwindow;
- window *mooniconwindow;
- window *scratchwindow;
- void *moontoolispace;
- void *mooniconispace;
- windowstate wstate;
- templatefonts fonts;
-
- /*
- ** Initialise my I/O variables ...
- */
- Wimp_Initialise200("Moon Tool", &OurTaskHandle);
-
- Wimp_OpenTemplate("MoonTool:Templates");
-
- Wimp_NamedTemplateSize("MoonTool", &isize, &windowsize, &fontspresent);
- for(i=0; i<256; i++)
- fonts.font[i] = 0;
- scratchwindow = (window *) malloc(windowsize+isize);
- moontoolispace = (void *) malloc(isize);
- Wimp_LoadNamedTemplate(scratchwindow, "MoonTool", moontoolispace, isize, &fonts);
- Wimp_CreateWindow(scratchwindow, &MoonTool);
-
- Wimp_NamedTemplateSize("MoonIcon", &isize, &windowsize, &fontspresent);
- scratchwindow = (window *) realloc(scratchwindow, windowsize+isize);
- mooniconispace = (void *) malloc(isize);
- Wimp_LoadNamedTemplate(scratchwindow, "MoonIcon", mooniconispace, isize, NULL);
- Wimp_CreateWindow(scratchwindow, &MoonIcon);
-
- Wimp_CloseTemplate();
-
- if(Iconised)
- wstate.handle = MoonIcon;
- else
- wstate.handle = MoonTool;
-
- Wimp_GetWindowState(&wstate);
- Wimp_OpenWindow((openwindowinfo *) &wstate);
-
- free(scratchwindow);
- }
-
-
- /*
- * Dispatch Poll
- */
- void DispatchPoll(eventinfo *event)
- {
- switch (event->type)
- {
- case Open_Window_Request :
- Wimp_OpenWindow(&event->data.window);
- break;
-
- case Close_Window_Request :
- Wimp_CloseDown();
- exit(0);
- break;
-
- case Mouse_Button_Change:
- {
- windowstate state;
-
- if(event->data.buttonchange.pointerinfo.buttons.feild.menu)
- /*MakeMenu(event)*/;
- else
- {
- eventinfo dummyevent;
-
- if(event->data.buttonchange.pointerinfo.window == MoonTool &&
- event->data.buttonchange.pointerinfo.icon == 42)
- {
- Wimp_CloseWindow(MoonTool);
-
- Wimp_PollIdleSeconds(&dummyevent, 0, 0);
- DispatchPoll(&dummyevent);
-
- state.handle = MoonIcon;
- Wimp_GetWindowState(&state);
- state.behind = OPEN_ON_TOP;
- Wimp_OpenWindow((openwindowinfo *) &state);
-
- Iconised = TRUE;
- }
- if(event->data.buttonchange.pointerinfo.window == MoonIcon)
- {
- Wimp_CloseWindow(MoonIcon);
-
- Wimp_PollIdleSeconds(&dummyevent, 0, 0);
- DispatchPoll(&dummyevent);
-
- Iconised = FALSE; /* Have to set this before we call ringgg(); */
- ringgg();
-
- state.handle = MoonTool;
- Wimp_GetWindowState(&state);
- state.behind = OPEN_ON_TOP;
- Wimp_OpenWindow((openwindowinfo *) &state);
- }
- }
- }
- break;
-
- case Menu_Select:
- {
- if(event->data.menu[0] == 1) exit(0);
- }
- break;
-
- case Key_Pressed:
- Wimp_ProcessKey(event->data.key.code);
- break;
-
- case Send_Message:
- case Send_Message_Acknowledged:
- switch(event->data.message.header.type)
- {
- case Message_CloseDown:
- Wimp_CloseDown();
- exit(1);
- break;
- }
- break;
- }
- }
-
-
-
- /* Main program */
-
- int main(int argc, char *argv[])
- {
- int i;
- int delay;
- eventmask mask = 0;
- eventinfo event;
-
- for (i = 1; i < argc; i++)
- {
- if (*argv[i] == '-' && argv[i][1] == 't')
- testmode = TRUE;
- }
-
- StartWimp();
- ringgg();
-
- while(TRUE)
- {
- if(Iconised && !testmode)
- delay = 6000;
- else
- delay = 90;
- Wimp_PollIdleSeconds(&event, mask, delay);
-
- if(event.type == Null_Reason_Code)
- ringgg();
- else
- DispatchPoll(&event);
- }
- }
-
-
- /*
- * DRAWMOON -- Construct icon for moon, given phase of moon.
- */
-
- int IconSpanlist[36][2];
- #define Left 0
- #define Right 1
- #define XMid 35
-
- void drawmoon(double ph)
- {
- int i, j, lx, rx;
- double cp, xscale, d;
- BOOL IconChanged = FALSE;
- spritecontext SavedContext;
-
- xscale = cos(2 * PI * ph);
-
- for (i = 0; i < 29; i++)
- {
- d = (i*2.0+1.0) / 29.0;
- if(d <= 1.0)
- d = 1.0 - d;
- else
- d = d - 1.0;
- cp = 31.0 * cos(asin(d));
-
- if (ph < 0.5)
- {
- rx = 1000;
- lx = XMid - xscale * cp;
- }
- else
- {
- lx = 0;
- rx = XMid + xscale * cp;
- }
-
- if((IconSpanlist[i][Left] != lx) || (IconSpanlist[i][Right] != rx))
- {
- IconSpanlist[i][Left] = lx;
- IconSpanlist[i][Right] = rx;
- IconChanged = TRUE;
- }
- }
- /*
- * Only update icon if it changed (this eliminates gratuitous
- * flashing of the icon on-screen).
- */
- if(IconChanged)
- {
- GFX_ChangeContextToSpriteMask(1, "the_moon", &SavedContext);
- GFX_GCOL(15); /* No Mask */
- GFX_Rectangle(0,0,1000,1000); /* Clear whole sprite */
- GFX_GCOL(0); /* Mask */
- for(i=0; i<29; i++)
- {
- GFX_Line(IconSpanlist[i][Left]*2, i*4 + 8, IconSpanlist[i][Right]*2, i*4 + 8);
- }
- GFX_RestoreContext(&SavedContext);
-
- Wimp_SetIconState(MoonTool, 41, 0, 0);
- Wimp_SetIconState(MoonIcon, 0, 0, 0);
- }
- }
-
- /* RINGGG -- Update status on interval timer ticks and redraw
- window if needed. */
-
- void ringgg(void)
- {
- int lunation, wclosed;
- time_t t;
- double jd, p, aom, cphase, cdist, cangdia, csund, csuang, lptime;
- static double phasar[5];
- static double nptime = 0.0; /* Next new moon time */
- static int updyet = 0; /* Update interval when window closed */
- static int firstime = TRUE; /* Calculate text page first time */
- char amsg[12], tbuf[80];
- static double faketime = 0.0;
- static short moonilast[64][4] = {0};
- int yy, mm, dd, hh, mmm, ss;
- struct tm *gm;
- static char *moname[] = {"January", "February", "March", "April",
- "May", "June", "July", "August", "September",
- "October", "November", "December"};
-
- (void) time(&t);
- jd = jtime((gm = gmtime(&t)));
-
- if(testmode)
- {
- if (faketime == 0.0)
- faketime = jd + 1;
- else
- faketime += 1.0 / 24;
- jd = faketime;
- }
-
- p = phase(jd, &cphase, &aom, &cdist, &cangdia, &csund, &csuang);
- /*
- * Calculate times of phases of this lunation.
- * This is sufficiently time-consuming that
- * we only do it once a month.
- */
- if(jd > nptime)
- {
- phasehunt(jd, phasar); /* X-pensive call */
- }
-
- drawmoon(p);
-
- /* If we're iconic, there's nothing more to do. */
-
- if (Iconised && !firstime)
- return;
-
- /*
- * Update textual information for open window
- */
- firstime = FALSE;
-
- Icon_SmartPrint(Julian_Date, "%.5f", jd + 0.5);
-
- if(testmode)
- {
- jyear(jd, &yy, &mm, &dd);
- jhms(jd, &hh, &mmm, &ss);
- Icon_SmartPrint(Universal_Time, "%02d:%02d:%02d", hh, mmm, ss);
- Icon_SmartPrint(Universal_Date, "%d %s %d", dd, moname[mm-1], yy);
- }
- else
- {
- Icon_SmartPrint(Universal_Time, "%02d:%02d:%02d", gm->tm_hour, gm->tm_min, gm->tm_sec);
- Icon_SmartPrint(Universal_Date, "%d %s %d", gm->tm_mday, moname[gm->tm_mon], gm->tm_year + 1900);
- }
-
- gm = localtime(&t);
- if(testmode)
- {
- Icon_SmartPrint(Local_Time, "--:--:--");
- Icon_SmartPrint(Local_Date, "(Test Mode)");
- }
- else
- {
- Icon_SmartPrint(Local_Time, "%02d:%02d:%02d", gm->tm_hour, gm->tm_min, gm->tm_sec);
- Icon_SmartPrint(Local_Date, "%d %s %d", gm->tm_mday, moname[gm->tm_mon], gm->tm_year + 1900);
- }
-
- /*
- * sprintf(tbuf, "Moon phase: %d%% 0%% = New, 100%% = Full ",
- * (int) (cphase * 100));
- * prt(5);
- */
-
- /*
- * Information about the Moon
- */
- Icon_SmartPrint(Moon_Subtends, "%.4f°", cangdia);
-
- Icon_SmartPrint(MoonDistance_Kilometers, "%ld kilometres", (long) cdist);
- Icon_SmartPrint(MoonDistance_Radii, "%.1f Earth radii", cdist / earthrad);
-
- aom = jd - phasar[0]; /* Cos it was wrong -- Edouard Poor */
-
- Icon_SmartPrint(MoonAge_Days, "%d", (int) aom);
- Icon_SmartPrint(MoonAge_Hours, "%d", ((int) (24 * (aom - floor(aom)))));
- Icon_SmartPrint(MoonAge_Minutes, "%d", ((int) (1440 * (aom - floor(aom)))) % 60);
-
- /*
- * Edit information about the Sun
- */
- Icon_SmartPrint(Sun_Subtends, "%.4f°", csuang);
-
- Icon_SmartPrint(SunDistance_Kilometers, "%.0f kilometres", csund);
- Icon_SmartPrint(SunDistance_AU, "%.3f A.U.", csund / sunsmax);
-
- /*
- * Calculate times of phases of this lunation.
- * This is sufficiently time-consuming that
- * we only do it once a month.
- */
- if(jd > nptime)
- {
- lptime = phasar[0];
- jyear(lptime, &yy, &mm, &dd);
- jhms(lptime, &hh, &mmm, &ss);
- Icon_SmartPrint(Phases_LastNewMoon, "%02d:%02d %d %s %d", hh, mmm, dd, moname[mm - 1], yy);
-
- lptime = phasar[1];
- jyear(lptime, &yy, &mm, &dd);
- jhms(lptime, &hh, &mmm, &ss);
- Icon_SmartPrint(Phases_FirstQuarter, "%02d:%02d %d %s %d", hh, mmm, dd, moname[mm - 1], yy);
-
- lptime = phasar[2];
- jyear(lptime, &yy, &mm, &dd);
- jhms(lptime, &hh, &mmm, &ss);
- Icon_SmartPrint(Phases_FullMoon, "%02d:%02d %d %s %d", hh, mmm, dd, moname[mm - 1], yy);
-
- lptime = phasar[3];
- jyear(lptime, &yy, &mm, &dd);
- jhms(lptime, &hh, &mmm, &ss);
- Icon_SmartPrint(Phases_LastQuarter, "%02d:%02d %d %s %d", hh, mmm, dd, moname[mm - 1], yy);
-
- nptime = phasar[4];
- jyear(nptime, &yy, &mm, &dd);
- jhms(nptime, &hh, &mmm, &ss);
- Icon_SmartPrint(Phases_NextNewMoon, "%02d:%02d %d %s %d", hh, mmm, dd, moname[mm - 1], yy);
-
- lunation = floor(((lptime + 7) - lunatbase) / synmonth) + 1;
- Icon_SmartPrint(Phases_CurrentLunation, "%d", lunation);
- }
- }
-
- /* JDATE -- Convert internal GMT date and time to Julian day
- and fraction. */
-
- long jdate(struct tm *t)
- {
- long c, m, y;
-
- y = t->tm_year + 1900;
- m = t->tm_mon + 1;
- if (m > 2)
- m = m - 3;
- else
- {
- m = m + 9;
- y = y - 1;
- }
- c = y / 100L; /* Compute century */
- y -= 100L * c;
- return t->tm_mday + (c * 146097L) / 4 + (y * 1461L) / 4 +
- (m * 153L + 2) / 5 + 1721119L;
- }
-
- /* JTIME -- Convert internal GMT date and time to astronomical Julian
- time (i.e. Julian date plus day fraction, expressed as
- a double). */
-
- double jtime(struct tm *t)
- {
- return (jdate(t) - 0.5) +
- (t->tm_sec + 60 * (t->tm_min + 60 * t->tm_hour)) / 86400.0;
- }
-
- /* JYEAR -- Convert Julian date to year, month, day, which are
- returned via integer pointers to integers. */
-
- void jyear(double td, int *yy, int *mm, int *dd)
- {
- double j, d, y, m;
-
- td += 0.5; /* Astronomical to civil */
- j = floor(td);
- j = j - 1721119.0;
- y = floor(((4 * j) - 1) / 146097.0);
- j = (j * 4.0) - (1.0 + (146097.0 * y));
- d = floor(j / 4.0);
- j = floor(((4.0 * d) + 3.0) / 1461.0);
- d = ((4.0 * d) + 3.0) - (1461.0 * j);
- d = floor((d + 4.0) / 4.0);
- m = floor(((5.0 * d) - 3) / 153.0);
- d = (5.0 * d) - (3.0 + (153.0 * m));
- d = floor((d + 5.0) / 5.0);
- y = (100.0 * y) + j;
- if (m < 10.0)
- m = m + 3;
- else
- {
- m = m - 9;
- y = y + 1;
- }
- *yy = y;
- *mm = m;
- *dd = d;
- }
-
- /* JHMS -- Convert Julian time to hour, minutes, and seconds. */
-
- void jhms(double j, int *h, int *m, int *s)
- {
- long ij;
-
- j += 0.5; /* Astronomical to civil */
- ij = (j - floor(j)) * 86400.0;
- *h = ij / 3600L;
- *m = (ij / 60L) % 60L;
- *s = ij % 60L;
- }
-
- /* MEANPHASE -- Calculates mean phase of the Moon for a given
- base date and desired phase:
- 0.0 New Moon
- 0.25 First quarter
- 0.5 Full moon
- 0.75 Last quarter
- Beware!!! This routine returns meaningless
- results for any other phase arguments. Don't
- attempt to generalise it without understanding
- that the motion of the moon is far more complicated
- that this calculation reveals. */
-
- double meanphase(double sdate, double phase, double *usek)
- {
- int yy, mm, dd;
- double k, t, t2, t3, nt1;
-
- jyear(sdate, &yy, &mm, &dd);
-
- k = (yy + ((mm - 1) * (1.0 / 12.0)) - 1900) * 12.3685;
-
- /* Time in Julian centuries from 1900 January 0.5 */
- t = (sdate - 2415020.0) / 36525;
- t2 = t * t; /* Square for frequent use */
- t3 = t2 * t; /* Cube for frequent use */
-
- *usek = k = floor(k) + phase;
- nt1 = 2415020.75933 + synmonth * k
- + 0.0001178 * t2
- - 0.000000155 * t3
- + 0.00033 * dsin(166.56 + 132.87 * t - 0.009173 * t2);
-
- return nt1;
- }
-
- /* TRUEPHASE -- Given a K value used to determine the
- mean phase of the new moon, and a phase
- selector (0.0, 0.25, 0.5, 0.75), obtain
- the true, corrected phase time. */
-
- double truephase(double k, double phase)
- {
- double t, t2, t3, pt, m, mprime, f;
- int apcor = FALSE;
-
- k += phase; /* Add phase to new moon time */
- t = k / 1236.85; /* Time in Julian centuries from
- 1900 January 0.5 */
- t2 = t * t; /* Square for frequent use */
- t3 = t2 * t; /* Cube for frequent use */
- pt = 2415020.75933 /* Mean time of phase */
- + synmonth * k
- + 0.0001178 * t2
- - 0.000000155 * t3
- + 0.00033 * dsin(166.56 + 132.87 * t - 0.009173 * t2);
-
- m = 359.2242 /* Sun's mean anomaly */
- + 29.10535608 * k
- - 0.0000333 * t2
- - 0.00000347 * t3;
- mprime = 306.0253 /* Moon's mean anomaly */
- + 385.81691806 * k
- + 0.0107306 * t2
- + 0.00001236 * t3;
- f = 21.2964 /* Moon's argument of latitude */
- + 390.67050646 * k
- - 0.0016528 * t2
- - 0.00000239 * t3;
- if ((phase < 0.01) || (abs(phase - 0.5) < 0.01))
- {
- /* Corrections for New and Full Moon */
-
- pt += (0.1734 - 0.000393 * t) * dsin(m)
- + 0.0021 * dsin(2 * m)
- - 0.4068 * dsin(mprime)
- + 0.0161 * dsin(2 * mprime)
- - 0.0004 * dsin(3 * mprime)
- + 0.0104 * dsin(2 * f)
- - 0.0051 * dsin(m + mprime)
- - 0.0074 * dsin(m - mprime)
- + 0.0004 * dsin(2 * f + m)
- - 0.0004 * dsin(2 * f - m)
- - 0.0006 * dsin(2 * f + mprime)
- + 0.0010 * dsin(2 * f - mprime)
- + 0.0005 * dsin(m + 2 * mprime);
- apcor = TRUE;
- }
- else if ((abs(phase - 0.25) < 0.01 || (abs(phase - 0.75) < 0.01)))
- {
- pt += (0.1721 - 0.0004 * t) * dsin(m)
- + 0.0021 * dsin(2 * m)
- - 0.6280 * dsin(mprime)
- + 0.0089 * dsin(2 * mprime)
- - 0.0004 * dsin(3 * mprime)
- + 0.0079 * dsin(2 * f)
- - 0.0119 * dsin(m + mprime)
- - 0.0047 * dsin(m - mprime)
- + 0.0003 * dsin(2 * f + m)
- - 0.0004 * dsin(2 * f - m)
- - 0.0006 * dsin(2 * f + mprime)
- + 0.0021 * dsin(2 * f - mprime)
- + 0.0003 * dsin(m + 2 * mprime)
- + 0.0004 * dsin(m - 2 * mprime)
- - 0.0003 * dsin(2 * m + mprime);
- if(phase < 0.5)
- /* First quarter correction */
- pt += 0.0028 - 0.0004 * dcos(m) + 0.0003 * dcos(mprime);
- else
- /* Last quarter correction */
- pt += -0.0028 + 0.0004 * dcos(m) - 0.0003 * dcos(mprime);
- apcor = TRUE;
- }
-
- if(!apcor)
- {
- fprintf(stderr, "TRUEPHASE called with invalid phase selector.\n");
- exit(1);
- }
-
- return pt;
- }
-
- /* PHASEHUNT -- Find time of phases of the moon which surround
- the current date. Five phases are found, starting
- and ending with the new moons which bound the
- current lunation. */
-
- void phasehunt(double sdate, double phases[5])
- {
- double adate, k1, k2, nt1, nt2;
-
- adate = sdate - 45;
- nt1 = meanphase(adate, 0.0, &k1);
- while (TRUE)
- {
- adate += synmonth;
- nt2 = meanphase(adate, 0.0, &k2);
- if (nt1 <= sdate && nt2 > sdate)
- break;
- nt1 = nt2;
- k1 = k2;
- }
- phases[0] = truephase(k1, 0.0);
- phases[1] = truephase(k1, 0.25);
- phases[2] = truephase(k1, 0.5);
- phases[3] = truephase(k1, 0.75);
- phases[4] = truephase(k2, 0.0);
- }
-
-
- /* KEPLER -- Solve the equation of Kepler. */
-
- double kepler(double m, double ecc)
- {
- double e, delta;
-
- e = m = torad(m);
- do
- {
- delta = e - ecc * sin(e) - m;
- e -= delta / (1 - ecc * cos(e));
- }
- while (abs(delta) > EPSILON);
-
- return e;
- }
-
-
- /* PHASE -- Calculate phase of moon as a fraction:
-
- The argument is the time for which the phase is requested,
- expressed as a Julian date and fraction. Returns the terminator
- phase angle as a percentage of a full circle (i.e., 0 to 1),
- and stores into pointer arguments the illuminated fraction of
- the Moon's disc, the Moon's age in days and fraction, the
- distance of the Moon from the centre of the Earth, and the
- angular diameter subtended by the Moon as seen by an observer
- at the centre of the Earth.
-
- pphase.............Illuminated fraction
- mage...............Age of moon in days
- dist...............Distance in kilometres
- angdia.............Angular diameter in degrees
- sudist.............Distance to Sun
- suangdia...........Sun's angular diameter
- */
-
- double phase(double pdate, double *pphase, double *mage, double *dist, double *angdia, double *sudist, double *suangdia)
- {
- double Day, N, M, Ec, Lambdasun, ml, MM, MN, Ev, Ae, A3, MmP,
- mEc, A4, lP, V, lPP, NP, y, x, Lambdamoon, BetaM,
- MoonAge, MoonPhase,
- MoonDist, MoonDFrac, MoonAng, MoonPar,
- F, SunDist, SunAng;
-
- /* Calculation of the Sun's position */
-
- Day = pdate - epoch; /* Date within epoch */
- N = fixangle((360 / 365.2422) * Day); /* Mean anomaly of the Sun */
- M = fixangle(N + elonge - elongp); /* Convert from perigee co-ordinates to epoch 1980.0 */
- Ec = kepler(M, eccent); /* Solve equation of Kepler */
- Ec = sqrt((1 + eccent) / (1 - eccent)) * tan(Ec / 2);
- Ec = 2 * todeg(atan(Ec)); /* True anomaly */
- Lambdasun = fixangle(Ec + elongp); /* Sun's geocentric ecliptic longitude */
- F = ((1 + eccent * cos(torad(Ec))) / (1 - eccent * eccent)); /* Orbital distance factor */
- SunDist = sunsmax / F; /* Distance to Sun in km */
- SunAng = F * sunangsiz; /* Sun's angular size in degrees */
-
- /*
- * Calculation of the Moon's position
- */
-
- /* Moon's mean longitude */
- ml = fixangle(13.1763966 * Day + mmlong);
-
- /* Moon's mean anomaly */
- MM = fixangle(ml - 0.1114041 * Day - mmlongp);
-
- /* Moon's ascending node mean longitude */
- MN = fixangle(mlnode - 0.0529539 * Day);
-
- /* Evection */
- Ev = 1.2739 * sin(torad(2 * (ml - Lambdasun) - MM));
-
- /* Annual equation */
- Ae = 0.1858 * sin(torad(M));
-
- /* Correction term */
- A3 = 0.37 * sin(torad(M));
-
- /* Corrected anomaly */
- MmP = MM + Ev - Ae - A3;
-
- /* Correction for the equation of the centre */
- mEc = 6.2886 * sin(torad(MmP));
-
- /* Another correction term */
- A4 = 0.214 * sin(torad(2 * MmP));
-
- /* Corrected longitude */
- lP = ml + Ev + mEc - Ae + A4;
-
- /* Variation */
- V = 0.6583 * sin(torad(2 * (lP - Lambdasun)));
-
- /* True longitude */
- lPP = lP + V;
-
- /* Corrected longitude of the node */
- NP = MN - 0.16 * sin(torad(M));
-
- /* Y inclination coordinate */
- y = sin(torad(lPP - NP)) * cos(torad(minc));
-
- /* X inclination coordinate */
- x = cos(torad(lPP - NP));
-
- /* Ecliptic longitude */
- Lambdamoon = todeg(atan2(y, x));
- Lambdamoon += NP;
-
- /* Ecliptic latitude */
- BetaM = todeg(asin(sin(torad(lPP - NP)) * sin(torad(minc))));
-
- /*
- * Calculation of the phase of the Moon
- */
-
- /* Age of the Moon in degrees */
- MoonAge = lPP - Lambdasun;
-
- /* Phase of the Moon */
- MoonPhase = (1 - cos(torad(MoonAge))) / 2;
-
- /*
- * Calculate distance of moon from the centre of the Earth
- */
-
- MoonDist = (msmax * (1 - mecc * mecc)) / (1 + mecc * cos(torad(MmP + mEc)));
-
- /*
- * Calculate Moon's angular diameter
- */
-
- MoonDFrac = MoonDist / msmax;
- MoonAng = mangsiz / MoonDFrac;
-
- /*
- * Calculate Moon's parallax
- */
-
- MoonPar = mparallax / MoonDFrac;
-
- *pphase = MoonPhase;
- *mage = synmonth * (fixangle(MoonAge) / 360.0); /* ???? This can't be right ???? */
- *dist = MoonDist;
- *angdia = MoonAng;
- *sudist = SunDist;
- *suangdia = SunAng;
- return fixangle(MoonAge) / 360.0;
- }
-