Mar 28 2004 phase of moon, C source for windows app
dev
/*
Gizmo for making an Ambient(TM) Orb track the phase of the moon. Written by Armin Haken (colon @ sonic.net).

I learned how to post URLs from within Visual C from looking at sample code by Pandyalakal harvested from www.codeproject.com.

I also used snippets gathered from the internet relating to the ctime() function, the length of the lunar cycle and the lunar calendar, as well as info on how to submit a color change request (see www.myambient.com).

March 20, 2004, 23:26

Improved March 27 using the much more exact calculations by John Walker. Now the times of full and new moons are accurate to within seconds.

*/

code
#include <stdio.h>
#include <windows.h>
#include <wininet.h>
#include <time.h>
#include <math.h>
#include <assert.h>

/*********************************************copied code*********************************/

/* This stuff is copied from the javascript source of
http://www.fourmilab.ch/earthview/pacalc.html
and all I did was to declare types as "double" and convert the names of the math functions
to turn it into C. */

/* quote from the source I copied:
by John Walker
May 5, 1997
This document is in the public domain.
*/

/* degrees to radians */
double dtr(double x)
{
double pi = acos(-1);
return x*pi/180.0;
}

double dsin(double x)
{
return sin(dtr(x));
}

double dcos(double x)
{
return cos(dtr(x));
}

/* 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,
SynMonth = 29.53058868; /* Synodic month (mean time from new to next new Moon) */

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) || (fabs(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);
}
else if ((fabs(phase - 0.25) < 0.01 || (fabs(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);
}
return pt;
}


/***************************************end of copied code*********************************/


/* turn Julian date into time_t */
time_t deJulianize(double j)
{
/* Julian for beginning of 1970 is 2440587.5 */
if (j < 2440587.5)
return 0;
return (time_t)((j - 2440587.5)*60*60*24);
}


/* turn a time into a per-1000 fraction of the lunar cycle from new moon to new moon */
/* note 1: apparently the mysterious k is the number of lunar cycles since 1900 */
/* note 2: 12.3685 lunar cycles per year */
int time2MoonMill(time_t t)
{
/* lower bound on the cycle number we need */
double k2 = floor((t/(60*60*24*365)+70)*12.3685) - 2;
/* find times of full and new moon just before and just after t */
time_t prevNew, prevFull, nextNew, nextFull;
prevFull = nextFull = deJulianize(truephase(k2, 0.5));
while (nextFull < t)
{
k2++;
prevFull = nextFull;
nextFull = deJulianize(truephase(k2, 0.5));
}
assert(prevFull < nextFull);
k2--;
prevNew = nextNew = deJulianize(truephase(k2, 0));
while (nextNew < t)
{
k2++;
prevNew = nextNew;
nextNew = deJulianize(truephase(k2, 0));
}
assert(prevNew < nextNew);

if (prevNew > prevFull) /* first half of cycle */
return (t - prevNew)*500/(nextFull - prevNew);

return (t - prevFull)*500/(nextNew - prevFull) + 500;
}

/* global color, initialize out of range */
int prevColor = 37;

/* Turn the per-thousandth progress of the moon in its cycle into a color. */
/* 36 colors plus white .. 24 is blue, 6 is yellow, 15 is green and 33 is red .. */
/* Yellow is so anemic that it inserts a double dose of white at the full moon, */
/* right into the middle of the yellow phase. */
int moonMill2Color(int mill)
{
int nColor = (mill*76 + 1111)/1000;
if (nColor < 37) /* green side */
nColor = (60 - (nColor/2)) % 36;
else if (nColor > 40) /* red side */
nColor = (60 - ((nColor-4)/2)) % 36;
else
nColor = 36; /* white */

return nColor;
}


int main()
{
char devID[20];
char comment[100];
char URL[1001];
char response[1001];
unsigned long responseLen;
time_t timeNow;
int perMill;

/* microseconds to sleep */
unsigned int msHour = 1000*60*60;
unsigned int msMinute = 1000*60;

printf("Make your orb track the phase of the moon!nn");
printf("The orb must be set to the "Developer Channel" (visit www.myambient.com).n");
printf("White and yellow indicate a full moon and blue indicates the new moon.n");
printf("As the moon waxes the colors go to yellow via the green spectrum andn");
printf("as it wanes the colors go back from yellow to blue through the red spectrum.nn");
printf("This application will keep checking once an hour and if your orb color needsn");
printf("to be updated it will inform Ambient via the Internet.nn");
printf("Type your orb ID -> (with dashes, as in CDN-M6G-3P5) ");
gets(devID);

while (true)
{
int chosenColor;

time(&timeNow);

printf("nthe time is %s", ctime(&timeNow));

/* add 30 minutes to the time because the app only wakes up once an hour, so on
average it is 30 minutes late */
timeNow += 1800;

perMill = time2MoonMill(timeNow);
chosenColor = moonMill2Color(perMill);

printf ("the lunar cycle is at %d.%d%%, the color should be %dn",
perMill/10, perMill%10, chosenColor);

if (chosenColor != prevColor)
{
HINTERNET session = 0;
HINTERNET request = 0;

if (perMill < 500)
sprintf(comment, "the+moon+is+%d%%%0X+full%%%0X+waxing", (perMill+2)/5, '%', ',');
else
sprintf(comment, "the+moon+is+%d%%%0X+full%%%0X+waning", (1002-perMill)/5, '%', ',');

/* request is sent to the Ambient server for processing */
sprintf(URL, "http://myambient.com:8080/java/my_devices/submitdata.jsp?devID=%s&color=%d&anim=0&comment=%s",
devID, chosenColor, comment);

printf("nsending request: %sn", URL);

session = InternetOpen("lunatic", PRE_CONFIG_INTERNET_ACCESS, NULL,
INTERNET_INVALID_PORT_NUMBER, 0);
if(!session)
{
printf("error - check your internet connection (retry in 1 minute)n");
Sleep(msMinute);
continue;
}

request = InternetOpenUrl(session, URL, NULL, 0, INTERNET_FLAG_RELOAD, 0);
if(!request)
{
printf("internet connection error - could not submit URL (retry in 1 minute)n");
if (session != NULL) InternetCloseHandle(session);
Sleep(msMinute);
continue;
}

/* response from Ambient */
if(InternetReadFile(request, response, 1000, &responseLen))
{
response[responseLen] = 0;
printf("response: %s", response);
if (strcmpi("inserted OK", response) != 0)
prevColor = chosenColor;
}
else
printf("no response from servern");

if (session != NULL) InternetCloseHandle(session);
if (request != NULL) InternetCloseHandle(request);
}

Sleep(msHour);
}
return 0;
}
comments
Is there a C++ version of the moon phase program?
mar 29, 1:35pm | permalink

Some of the punctuation characters in the file got mangled in the display above.
There is a zipped up version of the source file together with the command-line
windows app at:

link
mar 30, 3:13pm | permalink

register / login
you must be a member to reply or post. signup or login