home *** CD-ROM | disk | FTP | other *** search
- /*
- * (c) Copyright 1993, Silicon Graphics, Inc.
- * ALL RIGHTS RESERVED
- *
- * Permission to use, copy, modify, and distribute this software for
- * any purpose and without fee is hereby granted, provided that the above
- * copyright notice appear in all copies and that both the copyright notice
- * and this permission notice appear in supporting documentation, and that
- * the name of Silicon Graphics, Inc. not be used in advertising
- * or publicity pertaining to distribution of the software without specific,
- * written prior permission.
- *
- * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
- * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
- * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
- * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
- * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
- * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
- * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
- * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN
- * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
- * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND
- * Use, duplication, or disclosure by the Government is subject to
- * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
- * (c)(1)(ii) of the Rights in Technical Data and Computer Software
- * clause at DFARS 252.227-7013 and/or in similar or successor
- * clauses in the FAR or the DOD or NASA FAR Supplement.
- * Unpublished-- rights reserved under the copyright laws of the
- * United States. Contractor/manufacturer is Silicon Graphics,
- * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311.
- *
- * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
- */
- #include <GL/glu.h>
- #include <GL/glx.h>
-
- #include "TimeDate.h"
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/time.h>
-
- inline float sign(float a) {return a > 0.0 ? 1. : (a < 0.0 ? -1. : 0.);}
-
- inline float degrees(float a) {return a * 180.0 / M_PI;}
- inline float radians(float a) {return a * M_PI / 180.0;}
-
- inline float arcsin(float a) {return atan2(a, sqrt(1.-a*a));}
-
- /* Thirty days hath September... */
- const int mday[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
- TimeDate::TimeDate(int hour, int minute, int second, long usecond)
- {
- read_time();
- t.tm_hour = hour;
- t.tm_min = minute;
- t.tm_sec = second;
- usec = usecond;
- }
-
- TimeDate TimeDate::operator=(TimeDate a)
- {
- usec = a.usec;
- t = a.t;
- return *this;
- }
-
- TimeDate TimeDate::operator+(TimeDate a)
- {
- TimeDate td;
- td = *this + a.t;
- td.usec = usec + a.usec;
- return td;
- }
-
- TimeDate TimeDate::operator+(struct tm t2)
- {
- TimeDate td;
- td.usec = 0;
- td.t.tm_sec = t.tm_sec + t2.tm_sec;
- td.t.tm_min = t.tm_min + t2.tm_min;
- td.t.tm_hour = t.tm_hour + t2.tm_hour;
- td.t.tm_mday = t.tm_mday + t2.tm_mday;
- td.t.tm_mon = t.tm_mon + t2.tm_mon;
- td.t.tm_year = t.tm_year + t2.tm_year;
- td.t.tm_wday = t.tm_wday + t2.tm_wday;
- td.t.tm_yday = t.tm_yday + t2.tm_yday;
- return td;
- }
-
- TimeDate TimeDate::operator+=(TimeDate a)
- {
- /* This is slower than it needs to be */
- *this = *this + a.t;
- return *this;
- }
-
- TimeDate TimeDate::operator-(TimeDate a)
- {
- TimeDate td;
- td.usec = usec - a.usec;
- td.t.tm_sec = t.tm_sec - a.t.tm_sec;
- td.t.tm_min = t.tm_min - a.t.tm_min;
- td.t.tm_hour = t.tm_hour - a.t.tm_hour;
- td.t.tm_mday = t.tm_mday - a.t.tm_mday;
- td.t.tm_mon = t.tm_mon - a.t.tm_mon;
- td.t.tm_year = t.tm_year - a.t.tm_year;
- td.t.tm_wday = t.tm_wday - a.t.tm_wday;
- td.t.tm_yday = t.tm_yday - a.t.tm_yday;
- return td;
- }
-
- TimeDate TimeDate::operator*(float f)
- {
- TimeDate td;
- td.usec = (long)((float)usec * f);
- td.t.tm_sec = (int)((float)t.tm_sec * f);
- td.t.tm_min = (int)((float)t.tm_min * f);
- td.t.tm_hour = (int)((float)t.tm_hour * f);
- td.t.tm_mday = (int)((float)t.tm_mday * f);
- td.t.tm_mon = (int)((float)t.tm_mon * f);
- td.t.tm_year = (int)((float)t.tm_year * f);
- td.t.tm_wday = (int)((float)t.tm_wday * f);
- td.t.tm_yday = (int)((float)t.tm_yday * f);
- return td;
- }
-
- TimeDate TimeDate::read_time()
- {
- struct timeval tv;
- time_t cal_time;
- struct tm *tmp;
-
- cal_time = time(NULL);
- gettimeofday(&tv);
- tmp = localtime(&cal_time);
-
- usec = tv.tv_usec;
- t = *tmp;
-
- return *this;
- }
-
- void TimeDate::print()
- {
- puts(asctime(&t));
- }
-
-
- /* The sun_direction routine comes from an awk program by Stuart Levy
- * (slevy@geom.umn.edu) */
-
- /* Day number of March 21st, roughly the vernal equinox */
- const float equinox = mday[0] + mday[1] + 21;
-
- /*
- * Date E.T. [degrees]
- * Jan 1 0.82
- * Jan 31 3.35
- * Mar 1 3.08
- * Mar 31 1.02
- * Apr 30 -0.71
- * May 30 -0.62
- * Jun 29 0.87
- * Jul 29 1.60
- * Aug 28 0.28
- * Sep 27 -2.28
- * Oct 27 -4.03
- * Nov 26 -3.15
- * Dec 26 0.19
- */
- const float et[] = {
- .82, 3.35, 3.08, 1.02, -.71, -.62, .87,
- 1.60, .28, -2.28, -4.03, -3.15, .19, 2.02};
-
- const float DEG = 180. / M_PI;
-
- Point TimeDate::sun_direction(float lon, float lat)
- {
- float yearday, eti, etoffset, ET, HA, LON, decl, altitude, azimuth;
- int etindex;
- Point dir;
- long tmp_usec;
- int m;
-
- tmp_usec = usec;
- usec = 0;
- *this = correct_smaller();
-
- /*
- * hour angle of the sun (time since local noon):
- * HA = (time - noon) * 15 degrees/hour
- * + (observer''s east longitude - long. of time zone''s
- * central meridian
- * POSITIVE east, NEGATIVE west)
- * - (15 degrees if time above was daylight savings time, else 0)
- * - "equation of time" (depends on date, correcting the
- * hour angle for
- * the earth''s elliptical orbit and the slope of the ecliptic)
- */
- yearday = (float)t.tm_mday +
- ((float)t.tm_hour + (float)t.tm_min / 60.0) / 24.0;
- for (m = 0; m < t.tm_mon; m++) yearday += mday[m];
-
- /*
- * Index into equation-of-time table, tabulated at 30-day intervals
- * We''ve added an extra entry at the end of the et table, corresponding
- * to January 25th of the following year, to make interpolation work
- * throughout the year.
- * Use simple linear interpolation.
- */
- eti = (yearday - 1.) / 30.;
- etoffset = eti - trunc(eti);
- etindex = (int)trunc(eti) + 1;
- ET = et[etindex - 1] + etoffset*(et[etindex+1 - 1] - et[etindex - 1]);
- /* The 90. puts us in the Central time zone */
- HA = ((float)t.tm_hour + (float)t.tm_min/60. - 12.)*15. +
- lon + 90. - ET;
-
- /*
- * Sun''s declination:
- * sun''s longitude = (date - March 21) * 360 degrees / 365.25 days
- * [This ignores the earth''s elliptical orbit...]
- */
- LON = (yearday - equinox) * 360. / 365.25;
- decl = DEG * arcsin( sin(LON/DEG) * sin(23.4/DEG) );
-
- /*
- * Then a spherical triangle calculation to convert the Sun''s
- * hour angle and declination, and the observer''s latitude,
- * to give the Sun''s altitude and azimuth (angle east from north).
- */
- altitude = DEG * arcsin( sin(decl/DEG)*sin(lat/DEG)
- + cos(decl/DEG)*cos(lat/DEG)*cos(HA/DEG) );
- azimuth = DEG * atan2( -cos(decl/DEG)*sin(HA/DEG),
- sin(decl/DEG)*cos(lat/DEG)
- - cos(decl/DEG)*cos(HA/DEG)*sin(lat/DEG) );
-
- /*
- printf("On %d/%d at %d:%02d, lat %g, lon %g\n",
- t.tm_mon + 1, t.tm_mday + 1, t.tm_hour, t.tm_min, lat, lon);
- printf("HA %.1f ET %.1f Sun lon %.1f decl %.1f alt %.1f az %.1f\n",
- HA,ET,LON,decl,altitude,azimuth);
- */
-
- dir.pt[2] = sin(radians(altitude));
- dir.pt[0] = cos(radians(azimuth));
- dir.pt[1] = sin(radians(azimuth));
- dir.pt[3] = 0;
- dir.unitize();
- // dir.print();
-
- usec = tmp_usec;
-
- return dir;
- }
-
- TimeDate TimeDate::correct_bigger()
- {
- TimeDate td;
- int days;
-
- td.t = t;
- td.usec = usec;
-
- td.t.tm_sec += (int)(td.usec / 1000000);
- td.usec %= 1000000;
- td.t.tm_min += td.t.tm_sec / 60;
- td.t.tm_sec %= 60;
- td.t.tm_hour += td.t.tm_min / 60;
- td.t.tm_min %= 60;
-
- if (td.t.tm_hour > 23) {
- days = td.t.tm_hour / 24;
- td.t.tm_hour %= 24;
- td.t.tm_mday += days;
- td.t.tm_wday = (td.t.tm_wday + days) % 7;
- td.t.tm_yday = (td.t.tm_yday + days) % 365;
- while (td.t.tm_mday > mday[td.t.tm_mon]) {
- td.t.tm_mday -= mday[td.t.tm_mon++];
- if (td.t.tm_mon >= 12) {
- td.t.tm_year += td.t.tm_mon / 12;
- td.t.tm_mon %= 12;
- }
- }
- }
- return td;
- }
-
- TimeDate TimeDate::correct_smaller()
- {
- TimeDate td;
-
- td.t = t;
- td.usec = usec;
-
- while (td.usec < 0) {
- td.t.tm_sec--;
- td.usec += 1000000;
- }
- while (td.t.tm_sec < 0) {
- td.t.tm_min--;
- td.t.tm_sec += 60;
- }
- while (td.t.tm_min < 0) {
- td.t.tm_hour--;
- td.t.tm_min += 60;
- }
- while (td.t.tm_hour < 0) {
- td.t.tm_mday--;
- if (td.t.tm_wday) td.t.tm_wday--;
- else td.t.tm_wday = 6;
- td.t.tm_yday--;
- td.t.tm_hour += 24;
- }
- if (td.t.tm_mon < 0 || td.t.tm_year < 0 || td.t.tm_yday < 0) {
- fprintf(stderr, "Warning: day < 0 in TimeDate.c++.\n");
- td.t.tm_mon = td.t.tm_year = td.t.tm_yday = 0;
- }
- return td.correct_bigger();
- }
-