home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / CLIPPER / MISC / XBBS7200.ZIP / XBBS7200.TAR / today / sun.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-10-02  |  10.8 KB  |  551 lines

  1. /***** hpfcla:net.sources / nsc-pdc!rgb / 10:24 am  May 16, 1985
  2. *
  3. * Changed constants to Fort Collins, Colorado.  (ajs, 850520)
  4. * Made other minor output format improvements also.
  5. *        sun <options>
  6. *
  7. *        options:        -t hh:mm:ss    time (default is current system time)
  8. *             -d mm/dd/yy    date (default is current system date)
  9. *                        -a lat        decimal latitude (default = 45.5333)
  10. *                        -o lon        decimal longitude (default = 122.8333) 
  11. *             -z tz        timezone (default = 8, pst)
  12. *             -p        show position of sun (azimuth)
  13. *             -v        turn on debugging
  14. *        
  15. *        All output is to standard io.  
  16. *
  17. *     Compile with cc -O -o sun sun.c -lm
  18. *     Non 4.2 systems may have to change <sys/time.h> to <time.h> below.
  19. *    (yes, done)
  20. *
  21. *     Note that the latitude, longitude, time zone correction and
  22. *     time zone string are all defaulted in the global variable section.
  23. *
  24. *     Most of the code in this program is adapted from algorithms
  25. *     presented in "Practical Astronomy With Your Calculator" by
  26. *     Peter Duffet-Smith.
  27. *
  28. *     The GST and ALT-AZIMUTH algorithms are from Sky and Telescope,
  29. *     June, 1984 by Roger W. Sinnott
  30. *
  31. *     Author Robert Bond - Beaverton Oregon.
  32. *    
  33. */
  34.  
  35. #include <stdio.h>
  36. #include <math.h>
  37. #include <sys/types.h>
  38. #include <time.h>
  39.  
  40. #define PI       3.141592654
  41. #define EPOCH     1980
  42. #define JDE     2444238.5    /* Julian date of EPOCH */
  43.  
  44. static double dtor();
  45. static double adj360();
  46. double adj24();
  47. double julian_date();
  48. double hms_to_dh();
  49. double solar_lon();
  50. double acos_deg();
  51. double asin_deg();
  52. double atan_q_deg();
  53. double atan_deg();
  54. double sin_deg();
  55. double cos_deg();
  56. double tan_deg();
  57. double gmst();
  58.  
  59. long time();
  60. struct tm *localtime();
  61.  
  62. int th;
  63. int tm;
  64. int ts;
  65. int mo;
  66. int day;
  67. int yr;
  68. int tz=8;            /* Default time zone */
  69. char *tzs  = "(PST)";        /* Default time zone string */
  70. char *dtzs = "(PDT)";        /* Default daylight savings time string */
  71. int debug = 0;
  72. int popt = 0;
  73.  
  74. double lat =  35.0000;        /* Default latitude (Fort Collins, Colorado) */
  75. double lon = 118.0000;        /* Default Longitude (Degrees west) */ 
  76.  
  77. sun(sunrh, sunrm, sunsh, sunsm)
  78. int *sunrh, *sunrm, *sunsh, *sunsm;
  79. {
  80.     double ed, jd;
  81.     double alpha1, delta1, alpha2, delta2, st1r, st1s, st2r, st2s;
  82.     double a1r, a1s, a2r, a2s, dt, dh, x, y;
  83.     double trise, tset, ar, as, alpha, delta, tri, da;
  84.     double lambda1, lambda2;
  85.     double alt, az, gst, m1;
  86.     double hsm, ratio;
  87.     time_t sec_1970;
  88.     int h, m;
  89.     struct tm *pt;
  90.  
  91.     time(&sec_1970);
  92.     pt = localtime(&sec_1970);  
  93.  
  94.     th = pt->tm_hour;
  95.     tm = pt->tm_min;
  96.     ts = pt->tm_sec;
  97.     yr = pt->tm_year + 1900;
  98.     mo = pt->tm_mon + 1;
  99.     day = pt->tm_mday;
  100.     if (pt->tm_isdst) {        /* convert tz to daylight savings time */
  101.     tz--;
  102.     tzs = dtzs;    
  103.     }
  104.  
  105.  
  106.     if (debug)
  107.         printf("Date: %d/%d/%d,  Time: %d:%d:%d, Tz: %d, Lat: %lf, Lon: %lf \n",
  108.         mo,day,yr,th,tm,ts,tz,lat,lon);
  109.  
  110.     jd = julian_date(mo,day,yr);
  111.     ed = jd - JDE;
  112.  
  113.     lambda1 = solar_lon(ed);
  114.     lambda2 = solar_lon(ed + 1.0);
  115.  
  116.     lon_to_eq(lambda1, &alpha1, &delta1);
  117.     lon_to_eq(lambda2, &alpha2, &delta2);
  118.  
  119.     rise_set(alpha1, delta1, &st1r, &st1s, &a1r, &a1s);
  120.     rise_set(alpha2, delta2, &st2r, &st2s, &a2r, &a2s);
  121.  
  122.     m1 = adj24(gmst(jd - 0.5, 0.5 + tz / 24.0) - lon / 15); /* lst midnight */
  123.  
  124.     if (debug)
  125.     printf ("local sidereal time of midnight is %lf \n", m1);
  126.  
  127.     hsm = adj24(st1r - m1);
  128.  
  129.     if (debug)
  130.     printf ("about %lf hours from midnight to dawn \n", hsm);
  131.  
  132.     ratio = hsm / 24.07;
  133.  
  134.     if (debug)
  135.     printf("%lf is how far dawn is into the day \n", ratio);
  136.  
  137.     if (fabs(st2r - st1r) > 1.0) {
  138.     st2r += 24.0;
  139.     if (debug)
  140.         printf("st2r corrected from %lf to %lf \n", st2r-24.0, st2r);
  141.     }
  142.  
  143.     trise = adj24((1.0 - ratio) * st1r + ratio * st2r);
  144.  
  145.     hsm = adj24(st1s - m1);
  146.  
  147.     if (debug)
  148.     printf ("about %lf hours from midnight to sunset \n", hsm);
  149.  
  150.     ratio = hsm / 24.07;
  151.  
  152.     if (debug)
  153.     printf("%lf is how far sunset is into the day \n", ratio);
  154.  
  155.     if (fabs(st2s - st1s) > 1.0) {
  156.     st2s += 24.0;
  157.     if (debug)
  158.         printf("st2s corrected from %lf to %lf \n", st2s-24.0, st2s);
  159.     }
  160.  
  161.     tset = adj24((1.0 - ratio) * st1s + ratio * st2s);
  162.  
  163.     if (debug)
  164.     printf("Uncorrected rise = %lf, set = %lf \n", trise, tset);
  165.  
  166.     ar = a1r * 360.0 / (360.0 + a1r - a2r);
  167.     as = a1s * 360.0 / (360.0 + a1s - a2s);
  168.  
  169.     delta = (delta1 + delta2) / 2.0;
  170.     tri = acos_deg(sin_deg(lat)/cos_deg(delta));
  171.  
  172.     x = 0.835608;        /* correction for refraction, parallax, ? */
  173.     y = asin_deg(sin_deg(x)/sin_deg(tri));
  174.     da = asin_deg(tan_deg(x)/tan_deg(tri));
  175.     dt = 240.0 * y / cos_deg(delta) / 3600;
  176.  
  177.     if (debug)
  178.     printf("Corrections: dt = %lf, da = %lf \n", dt, da);
  179.  
  180.     lst_to_hm(trise - dt, jd, &h, &m);
  181.     *sunrh = h;
  182.     *sunrm = m;
  183.  
  184.     if (popt) {
  185.         dh_to_hm(ar - da, &h, &m);
  186.         printf("Azimuth: %3d %02d'\n", h, m);
  187.     }
  188.  
  189.     lst_to_hm(tset + dt, jd, &h, &m);
  190.     *sunsh = h;
  191.     *sunsm = m;
  192.  
  193.     if (popt) {
  194.         dh_to_hm(as + da, &h, &m);
  195.         printf("Azimuth: %3d %02d'\n", h, m);
  196.     } 
  197.      
  198.  
  199.     if (popt) {
  200.  
  201.     if (alpha1 < alpha2)
  202.         alpha = (alpha1 + alpha2) / 2.0;
  203.     else
  204.         alpha = (alpha1 + 24.0 + alpha2) / 2.0;
  205.     
  206.     if (alpha > 24.0)
  207.         alpha -= 24.0;
  208.  
  209.     dh = (hms_to_dh(th, tm, ts) + tz) / 24.0;
  210.     if (dh > 0.5) {
  211.         dh -= 0.5;
  212.         jd += 0.5;
  213.     } else {
  214.         dh += 0.5;
  215.         jd -= 0.5;
  216.     }
  217.  
  218.     gst = gmst(jd, dh);
  219.  
  220.     eq_to_altaz(alpha, delta, gst, &alt, &az);
  221.  
  222.     printf     ("The sun is at:   ");
  223.     dh_to_hm (az, &h, &m);
  224.     printf     ("Azimuth: %3d %02d'  ", h, m);
  225.     dh_to_hm (alt, &h, &m);
  226.     printf     ("Altitude: %3d %02d'\n", h, m);
  227.     }
  228. }
  229.  
  230. static double
  231. dtor(deg)
  232. double deg;
  233. {
  234.     return (deg * PI / 180.0);
  235. }
  236.  
  237. double
  238. rtod(deg)
  239. double deg;
  240. {
  241.     return (deg * 180.0 / PI);
  242. }
  243.  
  244.  
  245. static double 
  246. adj360(deg)
  247. double deg;
  248. {
  249.     while (deg < 0.0) 
  250.     deg += 360.0;
  251.     while (deg > 360.0)
  252.     deg -= 360.0;
  253.     return(deg);
  254. }
  255.  
  256. double 
  257. adj24(hrs)
  258. double hrs;
  259. {
  260.     while (hrs < 0.0) 
  261.     hrs += 24.0;
  262.     while (hrs > 24.0)
  263.     hrs -= 24.0;
  264.     return(hrs);
  265. }
  266.  
  267. double 
  268. julian_date(m, d, y) int m, d, y;
  269. {
  270.     long a, b;
  271.     double jd;
  272.  
  273.     if (m == 1 || m == 2) {
  274.     --y;
  275.     m += 12;
  276.     }
  277.     if (y < 1583) {
  278.     printf("Can't handle dates before 1583\n");
  279.     exit(1);
  280.     }
  281.     a = (long)y/100;
  282.     b = 2 - a + a/4;
  283.     b += (long)((double)y * 365.25);
  284.     b += (long)(30.6001 * ((double)m + 1.0));
  285.     jd = (double)d + (double)b + 1720994.5;
  286.  
  287.     if (debug) 
  288.     printf("Julian date for %d/%d/%d is %lf \n", m, d, y, jd);
  289.  
  290.     return(jd);
  291. }
  292.  
  293. double 
  294. hms_to_dh(h, m, s) int h, m, s;
  295. {
  296.     double rv;
  297.     rv = h + m / 60.0 + s / 3600.0;
  298.  
  299.     if (debug)
  300.     printf("For time %d:%d:%d frac hours are: %lf \n", h, m, s, rv);
  301.  
  302.     return rv;
  303. }
  304.  
  305. double 
  306. solar_lon(ed)
  307. double ed;
  308. {
  309.     double n, m, e, ect, errt, v;
  310.  
  311.     n = 360.0 * ed / 365.2422;
  312.     n = adj360(n);
  313.     m = n + 278.83354 - 282.596403;
  314.     m = adj360(m);
  315.     m = dtor(m);
  316.     e = m; ect = 0.016718;
  317.     while ((errt = e - ect * sin(e) - m) > 0.0000001) 
  318.         e = e - errt / (1 - ect * cos(e));
  319.     v = 2 * atan(1.0168601 * tan(e/2));
  320.     v = adj360(v * 180.0 / PI + 282.596403);
  321.  
  322.     if (debug)
  323.     printf("Solar Longitude for %lf days is %lf \n", ed, v); 
  324.  
  325.     return(v);
  326. }
  327.  
  328. double 
  329. acos_deg(x)
  330. double x;
  331. {
  332.     return rtod(acos(x));
  333. }
  334.  
  335. double 
  336. asin_deg(x)
  337. double x;
  338. {
  339.     return rtod(asin(x));
  340. }
  341.  
  342. double 
  343. atan_q_deg(y,x)
  344. double y,x;
  345. {
  346.     double rv;
  347.  
  348.     if (y == 0)
  349.         rv = 0;
  350.     else if (x == 0)
  351.         rv = y>0 ? 90.0 : -90.0;
  352.     else rv = atan_deg(y/x);
  353.  
  354.     if (x<0) return rv+180.0;
  355.     if (y<0) return rv+360.0;
  356.     return(rv);
  357. }
  358.  
  359. double
  360. atan_deg(x)
  361. double x;
  362. {
  363.     return rtod(atan(x));
  364. }
  365.  
  366. double 
  367. sin_deg(x)
  368. double x;
  369. {
  370.     return sin(dtor(x));
  371. }
  372.  
  373. double 
  374. cos_deg(x)
  375. double x;
  376. {
  377.     return cos(dtor(x));
  378. }
  379.  
  380. double 
  381. tan_deg(x)
  382. double x;
  383. {
  384.     return tan(dtor(x));
  385. }
  386.  
  387. lon_to_eq(lambda, alpha, delta)
  388. double lambda;
  389. double *alpha;
  390. double *delta;
  391. {
  392.     double tlam,epsilon;
  393.  
  394.     tlam = dtor(lambda);
  395.     epsilon = dtor((double)23.441884);
  396.     *alpha = atan_q_deg((sin(tlam))*cos(epsilon),cos(tlam)) / 15.0;
  397.     *delta = asin_deg(sin(epsilon)*sin(tlam));
  398.  
  399.     if (debug)
  400.     printf("Right ascension, declination for lon %lf is %lf, %lf \n",
  401.         lambda, *alpha, *delta);
  402. }
  403.  
  404. rise_set(alpha, delta, lstr, lsts, ar, as)
  405. double alpha, delta, *lstr, *lsts, *ar, *as;
  406. {
  407.     double tar;
  408.     double h;
  409.  
  410.     tar = sin_deg(delta)/cos_deg(lat);
  411.     if (tar < -1.0 || tar > 1.0) {
  412.     printf("The object is circumpolar\n");
  413.     exit (1);
  414.     }
  415.     *ar = acos_deg(tar);
  416.     *as = 360.0 - *ar;
  417.  
  418.     h = acos_deg(-tan_deg(lat) * tan_deg(delta)) / 15.0;
  419.     *lstr = 24.0 + alpha - h;
  420.     if (*lstr > 24.0)
  421.     *lstr -= 24.0;
  422.     *lsts = alpha + h;
  423.     if (*lsts > 24.0)
  424.     *lsts -= 24.0;
  425.  
  426.     if (debug) {
  427.     printf("For ra, decl. of %lf, %lf: \n", alpha, delta);
  428.     printf("lstr = %lf, lsts = %lf, \n", *lstr, *lsts);
  429.     printf("ar =   %lf, as =   %lf \n", *ar, *as);
  430.     }
  431. }
  432.  
  433. lst_to_hm(lst, jd, h, m)
  434. double lst, jd;
  435. int *h, *m;
  436. {
  437.     double ed, gst, jzjd, t, r, b, t0, gmt;
  438.  
  439.     gst = lst + lon / 15.0;
  440.     if (gst > 24.0)
  441.     gst -= 24.0;
  442.     jzjd = julian_date(1,0,yr);
  443.     ed = jd-jzjd;
  444.     t = (jzjd -2415020.0)/36525.0;
  445.     r = 6.6460656+2400.05126*t+2.58E-05*t*t;
  446.     b = 24.0-(r-24.0*(yr-1900));
  447.     t0 = ed * 0.0657098 - b;
  448.     if (t0 < 0.0)
  449.     t0 += 24;
  450.     gmt = gst-t0;
  451.     if (gmt<0) 
  452.     gmt += 24.0;
  453.     gmt = gmt * 0.99727 - tz;;
  454.     if (gmt < 0)
  455.     gmt +=24.0;
  456.     dh_to_hm(gmt, h, m);
  457. }
  458.  
  459. dh_to_hm(dh, h, m)
  460. double dh;
  461. int *h, *m;
  462. {
  463.     double tempsec;
  464.  
  465.     *h = dh;
  466.  /* *m = (dh - *h) * 60; 
  467.     tempsec = (dh - *h) * 60 - *m; */
  468.     *m = fmod(dh, 1.0) * 60.0; 
  469.     tempsec = fmod(dh, 1.0) * 60.0 - *m;
  470.     tempsec = tempsec * 60 + 0.5;
  471.     if (tempsec > 30.0)
  472.     (*m)++;
  473.     if (*m == 60) {
  474.     *m = 0;
  475.     (*h)++;
  476.     }
  477. }
  478.  
  479. eq_to_altaz(r, d, t, alt, az)
  480. double r, d, t;
  481. double *alt, *az;
  482. {
  483.     double p = 3.14159265;
  484.     double r1 = p / 180.0;
  485.     double b = lat * r1;
  486.     double l = (360 - lon) * r1;
  487.     double t5, s1, c1, c2, s2, a, h;
  488.  
  489.     if (debug)
  490.     printf("Given R. A. = %lf, DECL. = %lf, gmt = %lf \n", r, d, t);
  491.  
  492.     r = r * 15.0 * r1;
  493.     d = d * r1;
  494.     t = t * 15.0 * r1;
  495.     t5 = t - r + l;
  496.     s1 = sin(b) * sin(d) + cos(b) * cos(d) * cos(t5);
  497.     c1 = 1 - s1 * s1;
  498.     if (c1 > 0) {
  499.     c1 = sqrt(c1);
  500.     h = atan(s1 / c1);
  501.     } else {
  502.     h = (s1 / fabs(s1)) * (p / 2.0);
  503.     }
  504.     c2 = cos(b) * sin(d) - sin(b) * cos(d) * cos(t5);
  505.     s2 = -cos(d) * sin(t5);
  506.     if (c2 == 0) 
  507.     a = (s2/fabs(s2)) * (p/2);
  508.     else {
  509.     a = atan(s2/c2);
  510.     if (c2 < 0)
  511.         a=a+p;
  512.     }
  513.     if (a<0)
  514.         a=a+2*p;
  515.     *alt = h / r1;
  516.     *az = a / r1;
  517.  
  518.     if (debug)
  519.     printf("alt = %lf, az = %lf \n",*alt,*az);
  520. }
  521.  
  522. double
  523. gmst(j, f)
  524. double j,f;
  525. {
  526.     double d, j0, t, t1, t2, s;
  527.  
  528.     d = j - 2451545.0;
  529.     t = d / 36525.0;
  530.     t1 = floor(t);
  531.     j0 = t1 * 36525.0 + 2451545.0;
  532.     t2 = (j - j0 + 0.5)/36525.0;
  533.     s = 24110.54841 + 184.812866 * t1; 
  534.     s += 8640184.812866 * t2;
  535.     s += 0.093104 * t * t;
  536.     s -= 0.0000062 * t * t * t;
  537.     s /= 86400.0;
  538.     s -= floor(s);
  539.     s = 24 * (s + (f - 0.5) * 1.002737909);
  540.     if (s < 0)
  541.     s += 24.0;
  542.     if (s > 24.0)
  543.     s -= 24.0;
  544.  
  545.     if (debug)
  546.     printf("For jd = %lf, f = %lf, gst = %lf \n", j, f, s);
  547.  
  548.     return(s);
  549. }
  550.