home *** CD-ROM | disk | FTP | other *** search
- /*-------------------------------------------------------------------------
- SunClock
-
- Amiga version by Mark Waggoner,
- waggoner@ichips.intel.com or wagnell@PDaXcess.techbook.com
- December 1991
-
- Sun.c
- Routines to calculate and set the illumination mask for the sun clock
- -------------------------------------------------------------------------*/
- #include <time.h>
- #include <math.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <functions.h>
- #include <string.h>
- #include <graphics/gfx.h>
- #include "sunmath.h"
-
- extern struct BitMap MapBitMap,IllumBitMap;
- extern UWORD DataWidth,DataHeight;
- extern WORD *Illum;
- extern void (*MapRefresh)(void);
- extern void (*TextRefresh)(void);
- extern char loctimestr[],gmtimestr[];
-
- /*-------------------------------------------------------------------------
- Draw a horizontal line segment into the bitmap data
- x0 must be less than x1 and both must be > 0
- -------------------------------------------------------------------------*/
- Segment(UBYTE *line,int x0,int x1)
- {
- UBYTE *sp,*ep,sm,em;
-
- sp = line + x0/8;
- ep = line + x1/8;
- sm = 0xff>>(x0%8);
- em = 0xff<<(7-x1%8);
-
- if (sp == ep) {
- *sp = (sm & em);
- return;
- }
-
- *sp |= sm;
- while (++sp<ep) *sp = 0xff;
- *ep |= em;
- }
-
- /*-------------------------------------------------------------------------
- Set the illumination mask bitmap.
- y is the row to set,
- noon is the midpoint of the mask
- width is half the width of the mask
- -------------------------------------------------------------------------*/
- void
- SetIllum(int noon,int y,int width)
- {
- UBYTE *line;
- int x0,x1;
-
- if (width == 0) width = 1;
- if (width < 0) return;
-
- if (y >= DataHeight) return;
-
- line = (UBYTE *)IllumBitMap.Planes[0] + (y * ((DataWidth + 15) / 16) * 2);
-
- x0 = noon - width;
- x1 = noon + width;
- if (x0<0) {
- Segment(line,DataWidth+(x0%DataWidth),DataWidth-1);
- x0 = 0;
- }
- if (x1 >= DataWidth) {
- Segment(line,0,x1%DataWidth);
- x1 = DataWidth-1;
- }
-
- Segment(line,x0,x1);
- }
-
- /*-------------------------------------------------------------------------
- Project the suns illumination onto the bitmap mask
- -------------------------------------------------------------------------*/
- #define tableval(i,v) if (i>=0 && i<DataHeight) { Illum[i] = ((v)==0) ? 1 : (v); }
-
- static void
- ProjectIllumination(int noon,double dec)
- {
- int i,j, ftf = 1;
- int ilon, ilat, lilon, lilat, xt;
- double m, x, y, z, th, lon, lat, s, c;
-
- for(i=0;i<DataHeight;i++)
- Illum[i] = -1;
-
- /* Build transformation for declination */
- dec = dtr(dec);
- s = sin(-dec);
- c = cos(-dec);
-
- /* Increment over a semicircle of illumination */
-
- for (th = -(PI / 2); th <= PI / 2 + 0.001; th += PI / TERMINC) {
-
- /* Transform the point through the declination rotation. */
-
- x = -s * sin(th);
- y = cos(th);
- z = c * sin(th);
-
- /* Transform the resulting co-ordinate through the
- map projection to obtain screen co-ordinates. */
-
- lon = (y == 0 && x == 0) ? 0.0 : rtd(atan2(y, x));
- lat = rtd(asin(z));
-
- ilat = DataHeight - (lat + 90) * (DataHeight / 180.0);
- ilon = lon * (DataWidth / 360.0);
-
- if (ftf) { /* First time. Just save start co-ordinate. */
- lilon = ilon;
- lilat = ilat;
- ftf = 0;
- } else {
- if (lilat == ilat) { /* Set width */
- j = (DataHeight - 1) - ilat;
- tableval(j,ilon);
- } else { /* interpolate intermediate points */
- m = ((double) (ilon - lilon)) / (ilat - lilat);
- for (i = lilat; i != ilat; i += sgn(ilat - lilat)) {
- xt = lilon + floor((m * (i - lilat)) + 0.5);
- j = (DataHeight - 1) - i;
- tableval(j,xt);
- }
- }
- lilon = ilon;
- lilat = ilat;
- }
- }
-
- /* Now tweak the widths to generate full illumination for
- the correct pole. */
-
- if (dec < 0.0) {
- ilat = DataHeight - 1;
- lilat = -1;
- } else {
- ilat = 0;
- lilat = 1;
- }
-
- for (i = ilat; i != DataHeight / 2; i += lilat) {
- if (Illum[i] != -1) {
- while (1) {
- tableval(i,DataWidth/2);
- if (i == ilat)
- break;
- i -= lilat;
- }
- break;
- }
- }
-
- for(i=0;i<DataHeight;i++)
- SetIllum(noon,i,Illum[i]);
-
- }
-
- /*-------------------------------------------------------------------------
- Update the illumination if it has been long enough since the
- last update.
- -------------------------------------------------------------------------*/
- void
- UpdateImages(int force)
- {
- time_t timeval;
- static time_t lasttime = 0;
- struct tm lt,*ct;
- double jt,gt;
- double sunra,sundec,sunrv,sunlong;
- double lastdec;
- double a;
- int xl;
- static int lastxl = -1;
- LONG sec0,mic0,sec1,mic1;
- char *tz;
-
- /* Find out what time it is */
- time(&timeval);
- lt = *localtime(&timeval);
- ct = gmtime(&timeval);
- if (!ct) ct = <
- jt = jtime(ct);
-
- if (tz = getenv("TZ")) {
- strncpy(loctimestr,tz,3);
- loctimestr[3] = ':';
- loctimestr[4] = ' ';
- loctimestr[5] = '\0';
- strcat(loctimestr,asctime(<));
- loctimestr[strlen(loctimestr)-1] = '\0';
- }
- else
- strcpy(loctimestr,"TZ Environment variable not set!");
-
- strcpy(gmtimestr,"GMT: ");
- strcat(gmtimestr,asctime(ct));
- gmtimestr[strlen(gmtimestr)-1] = '\0';
-
- TextRefresh();
-
- if ((timeval > lasttime) && ((timeval - lasttime) < 60) && !force) return;
- lasttime = timeval;
-
- sunpos(jt, 0, &sunra, &sundec, &sunrv, &sunlong);
- gt = gmst(jt);
-
- /* printf("RA: %g DEC: %g RV: %g LONG: %g\n",sunra,sundec,sunrv,sunlong); */
-
- a = 180.0 + (sunra - (gt * 15));
- sunlong = fixangle(a);
- xl = sunlong * ((double) DataWidth / 360.0);
-
- /* If the subsolar point has moved at least one pixel, update
- the illuminated area on the screen. */
-
- if ((lastxl != xl) || (fabs(sundec - lastdec) > 5) || force) {
- BltClear((char *)IllumBitMap.Planes[0],
- ((DataWidth+15)/16)*2*DataHeight,1);
- ProjectIllumination(xl,sundec);
-
- BltBitMap(&MapBitMap,0,0,&IllumBitMap,0,0,
- DataWidth,DataHeight,0x60,0x01,0);
-
- (*MapRefresh)();
- lastxl = xl;
- lastdec = sundec;
- }
- }
-