home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / EFFO / pd8.lzh / SRC / watch.c < prev   
Text File  |  1990-04-13  |  10KB  |  369 lines

  1. /* these functions allow you to watch the sky or the solar system via a
  2.  * simple character-graphics representation on the screen. 
  3.  * the interaction starts by using the current time. then control with
  4.  *    END returns to table form; or
  5.  *    RETURN advances time by one StpSz; or
  6.  *    h advances once by 1 hour; or
  7.  *    d advances once by 24 hours (1 day); or
  8.  *    w advances once by 7 days (1 week); or
  9.  *    any other key free runs by StpSz until any key is hit.
  10.  */
  11.  
  12. #include <stdio.h>
  13. #include <math.h>
  14. #include "astro.h"
  15. #include "circum.h"
  16. #include "screen.h"
  17.  
  18. #define    TROW    (R_PROMPT+1)    /* time/date row */
  19. #define    TCOL    C_PROMPT    /*    "      col */
  20. #define    SSZCOL    1        /* column to show solar system z coords */
  21.  
  22. #define    SKYACC    3600.    /* desired sky plot accuracy, in arc seconds */
  23. #define    SSACC    3600.    /* desired solar system plot accuracy, in arc secs */
  24.  
  25. /* macros to convert row(col) in range 1..NR(1..NC) to fraction in range 0..1 */
  26. #define    r2fr(r)        (((r)-1)/(NR-1))
  27. #define    c2fc(c)        (((c)-1)/(NC-1))
  28. #define    fr2r(fr)    ((fr)*(NR-1)+1)
  29. #define    fc2c(fc)    ((fc)*(NC-1)+1)
  30.  
  31. /* single-character tag for each body.
  32.  * order must match the #defines in astro.h and screen.h additions.
  33.  */
  34. static char body_tags[] = "evmjsunpSMx";
  35.  
  36. /* multiple and single loop prompts */
  37. static char frprompt[] = "Running... press any key to stop.";
  38. static char qprompt[]  =
  39. "q to quit, RETURN/h/d/w to step by StpSz/hr/day/wk, or any other to freerun";
  40.  
  41. /* used to locate, record and then erase last plotted chars */
  42. typedef struct {
  43.     double l_fr, l_fc;    /* 2d coords as 0..1 */
  44.     int     l_r, l_c;    /* screen 2d coords */
  45.     char l_tag;        /* char to use to print on screen */
  46. } LastDraw;
  47.  
  48. static int trails;    /* !0 if want to leave trails */
  49.  
  50. watch (np, tminc, wbodies)
  51. Now *np;    /* time now and on each step */
  52. double tminc;    /* hrs to increment time by each step */
  53. int wbodies;    /* each bit is !=0 if want that body */
  54. {
  55.     static char *flds[3] = {
  56.         "Sky", "Solar system"
  57.     };
  58.     int fn = 0;
  59.  
  60.     ask:
  61.     flds[2] = trails ? "Leave trails" : "No trails";
  62.     switch (popup (flds, fn, 3)) {
  63.     case 0: watch_sky (np, tminc, wbodies); break;
  64.     case 1: watch_solarsystem (np, tminc, wbodies); break;
  65.     case 2: trails ^= 1; fn = 2; goto ask;    /* toggle trails and repeat */
  66.     default: break;
  67.     }
  68. }
  69.  
  70. /* full night sky view.
  71.  * north is at left and right of screen south at center.
  72.  * 0 elevation is at bottom of screen, zenith at the top.
  73.  * redraw screen when done.
  74.  */
  75. static
  76. watch_sky (np, tminc, wbodies)
  77. Now *np;    /* time now and on each step */
  78. double tminc;    /* hrs to increment time by each step */
  79. int wbodies;    /* each bit is !=0 if want */
  80. {
  81.     static char title[] = "Sky at";
  82.     int tcol = sizeof(title)+1;
  83.     double tminc0 = tminc;    /* remember the original */
  84.     /* two draw buffers so we can leave old up while calc new then
  85.      * erase and draw in one quick operation. always calc new in newp
  86.      * buffer and erase previous from lastp. buffers alternate roles.
  87.      */
  88.     LastDraw ld0[NOBJ], ld1[NOBJ], *lp, *lastp = ld0, *newp = ld1;
  89.     int nlast = 0, nnew;
  90.     int once = 1;
  91.     double lmjd, tmp;
  92.     Sky s;
  93.     int p;
  94.  
  95.     c_erase();
  96.     f_string (TROW, TCOL, title);
  97.  
  98.     while (1) {
  99.         if (once)
  100.         print_updating();
  101.  
  102.         /* calculate desired stuff into newp[] */
  103.         nnew = 0;
  104.         for (p = nxtbody(-1); p != -1; p = nxtbody(p))
  105.         if (wbodies & (1<<p)) {
  106.             (void) body_cir (p, SKYACC, np, &s);
  107.             if (s.s_alt >= 0) {
  108.             LastDraw *lnp = newp + nnew;
  109.             lnp->l_fr = 1.0 - s.s_alt/(PI/2);
  110.             lnp->l_fc = s.s_az/(2*PI);
  111.             lnp->l_tag = body_tags[p];
  112.             nnew++;
  113.             }
  114.         }
  115.         set_screencoords (newp, nnew);
  116.  
  117.         /* unless we want trails,
  118.          * erase any previous tags (in same order as written) from lastp[].
  119.          */
  120.         if (!trails)
  121.         for (lp = lastp; --nlast >= 0; lp++)
  122.             f_char (lp->l_r, lp->l_c, ' ');
  123.  
  124.         /* print LOCAL time and date we will be using */
  125.         lmjd = mjd - tz/24.0;
  126.         f_time (TROW, tcol, mjd_hr(lmjd));
  127.         f_date (TROW, tcol+9, mjd_day(lmjd));
  128.         now_lst (np, &tmp);
  129.         f_time (TROW, tcol+20, tmp);
  130.         printf ("LST");
  131.  
  132.         /* now draw new stuff from newp[] */
  133.         for (lp = newp; lp < newp + nnew; lp++)
  134.         f_char (lp->l_r, lp->l_c, lp->l_tag);
  135.  
  136.         /* swap new and last roles and save new count */
  137.         if (newp == ld0)
  138.         newp = ld1, lastp = ld0;
  139.         else
  140.         newp = ld0, lastp = ld1;
  141.         nlast = nnew;
  142. #ifdef OSK
  143.         fflush(stdout);
  144. #endif
  145.  
  146.         if (once || (chk_char()==0 && read_char()!=0)) {
  147.         if (readwcmd (tminc0, &tminc, &once) < 0)
  148.             break;
  149.         }
  150.  
  151.         /* advance time */
  152.         inc_mjd (np, tminc);
  153.     }
  154.  
  155.     redraw_screen(2);
  156. }
  157.  
  158. /* solar system view, "down from the top", first point of aries to the right.
  159.  * always include earth.
  160.  * redraw screen when done.
  161.  */
  162. static
  163. watch_solarsystem (np, tminc, wbodies)
  164. Now *np;    /* time now and on each step */
  165. double tminc;    /* hrs to increment time by each step */
  166. int wbodies;
  167. {
  168.     /* max au of each planet from sun; in astro.h #defines order */
  169.     static double auscale[] = {.38, .75, 1.7, 5.2, 11., 20., 31., 39.};
  170.     static char title[] = "Solar System at";
  171.     int tcol = sizeof(title)+1;
  172.     double tminc0 = tminc;    /* remember the original */
  173.     /* two draw buffers so we can leave old up while calc new then
  174.      * erase and draw in one quick operation. always calc new in newp
  175.      * buffer and erase previous from lastp. buffers alternate roles.
  176.      */
  177.     LastDraw ld0[2*NOBJ], ld1[2*NOBJ], *lp, *lastp = ld0, *newp = ld1;
  178.     int nlast = 0, nnew;
  179.     int once = 1;
  180.     double lmjd;
  181.     double scale;
  182.     Sky s;
  183.     int p;
  184.  
  185.     /* set screen scale: largest au we will have to plot.
  186.      * never make it less than 1 au since we always show earth.
  187.      */
  188.     scale = 1.0;
  189.     for (p = MARS; p <= PLUTO; p++)
  190.         if ((wbodies & (1<<p)) && auscale[p] > scale)
  191.         scale = auscale[p];
  192.  
  193.     c_erase();
  194.     f_string (TROW, TCOL, title);
  195.  
  196.     while (1) {
  197.         if (once)
  198.         print_updating();
  199.  
  200.         /* calculate desired stuff into newp[].
  201.          * fake a sun at center and add earth first.
  202.          * (we get earth's loc when ask for sun)
  203.          */
  204.         nnew = 0;
  205.         set_ss (newp+nnew, 0.0, 0.0, 0.0, 'S');
  206.         nnew += 2;
  207.         (void) body_cir (SUN, SSACC, np, &s);
  208.         set_ss (newp+nnew, s.s_edist/scale, s.s_hlong, 0.0, 'E');
  209.         nnew += 2;
  210.         for (p = MERCURY; p <= PLUTO; p++)
  211.         if (wbodies & (1<<p)) {
  212.             (void) body_cir (p, SSACC, np, &s);
  213.             set_ss (newp+nnew, s.s_sdist/scale, s.s_hlong, s.s_hlat,
  214.                                 body_tags[p]);
  215.             nnew += 2;
  216.         }
  217.         for (p = OBJX; p != -1; p = (p == OBJX) ? OBJY : -1)
  218.         if (wbodies & (1<<p)) {
  219.             (void) body_cir (p, SSACC, np, &s);
  220.             if (s.s_hlong != NOHELIO && s.s_sdist <= scale) {
  221.             set_ss (newp+nnew, s.s_sdist/scale, s.s_hlong, s.s_hlat,
  222.                                 body_tags[p]);
  223.             nnew += 2;
  224.             }
  225.         }
  226.  
  227.         set_screencoords (newp, nnew);
  228.  
  229.         /* unless we want trails,
  230.          * erase any previous tags (in same order as written) from lastp[].
  231.          */
  232.         if (!trails)
  233.         for (lp = lastp; --nlast >= 0; lp++)
  234.             f_char (lp->l_r, lp->l_c, ' ');
  235.  
  236.         /* print LOCAL time and date we will be using */
  237.         lmjd = mjd - tz/24.0;
  238.         f_time (TROW, tcol, mjd_hr(lmjd));
  239.         f_date (TROW, tcol+9, mjd_day(lmjd));
  240.  
  241.         /* now draw new stuff from newp[] */
  242.         for (lp = newp; lp < newp + nnew; lp++)
  243.         f_char (lp->l_r, lp->l_c, lp->l_tag);
  244.  
  245.         /* swap new and last roles and save new count */
  246.         if (newp == ld0)
  247.         newp = ld1, lastp = ld0;
  248.         else
  249.         newp = ld0, lastp = ld1;
  250.         nlast = nnew;
  251. #ifdef OSK
  252.         fflush(stdout);
  253. #endif
  254.  
  255.         if (once || (chk_char()==0 && read_char()!=0)) {
  256.         if (readwcmd (tminc0, &tminc, &once) < 0)
  257.             break;
  258.         }
  259.  
  260.         /* advance time */
  261.         inc_mjd (np, tminc);
  262.     }
  263.  
  264.     redraw_screen(2);
  265. }
  266.  
  267. /* fill in two LastDraw solar system entries,
  268.  * one for the x/y display, one for the z.
  269.  */
  270. static
  271. set_ss (lp, dist, lg, lt, tag)
  272. LastDraw *lp;
  273. double dist, lg, lt;    /* scaled heliocentric distance, longitude and lat */
  274. char tag;
  275. {
  276.     lp->l_fr = 0.5 - dist*sin(lg)*0.5;
  277.     lp->l_fc = 0.5 + dist*cos(lg)*0.5/ASPECT;
  278.     lp->l_tag = tag;
  279.     lp++;
  280.     /* row is to show course helio altitude but since we resolve collisions
  281.      * by adjusting columns we can get more detail by smaller variations
  282.      * within one column.
  283.      */
  284.     lp->l_fr = 0.5 - dist*sin(lt)*0.5;
  285.     lp->l_fc = c2fc(SSZCOL) + (1 - lp->l_fr)/NC;
  286.     lp->l_tag = tag;
  287. }
  288.  
  289. /* given a list of LastDraw structs with their l_{fr,fc} filled in,
  290.  * fill in their l_{r,c}.
  291.  * TODO: better collision avoidance.
  292.  */
  293. static
  294. set_screencoords (lp, np)
  295. LastDraw lp[];
  296. int np;
  297. {
  298.     LastDraw *lpi;    /* the current basis for comparison */
  299.     LastDraw *lpj;    /* the sweep over other existing cells */
  300.     int i;        /* index of the current basis cell, lpi */
  301.     int j;        /* index of sweep cell, lpj */
  302.     int n;        /* total cells placed so far (ie, # to check) */
  303.  
  304.     /* idea is to place each new item onto the screen.
  305.      * after each placement, look for collisions.
  306.      * if find a colliding pair, move the one with the great l_fc to
  307.      * the right one cell, then rescan for more collisions.
  308.      * this will yield a result that is sorted by columns by l_fc.
  309.      * TODO: don't just move to the right, try up too for true 2d adjusts.
  310.      */
  311.     for (n = 0; n < np; n++) {
  312.         lpi = lp + n;
  313.         i = n;
  314.         lpi->l_r = fr2r(lpi->l_fr);
  315.         lpi->l_c = fc2c(lpi->l_fc);
  316.       chk:
  317.         for (j = 0; j < n; j++) {
  318.         lpj = lp + j;
  319.         if (i!=j && lpi->l_r == lpj->l_r && lpi->l_c == lpj->l_c) {
  320.             if (lpj->l_fc > lpi->l_fc) {
  321.             /* move lpj and use it as basis for checks now */
  322.             lpi = lpj;
  323.             i = j;
  324.             }
  325.             if (++lpi->l_c > NC)
  326.             lpi->l_c = 1;
  327.             goto chk;
  328.         }
  329.         }
  330.     }
  331. }
  332.  
  333. /* see what the op wants to do now and update prompt/times accordingly.
  334.  * return -1 if we are finished, else 0.
  335.  */
  336. static int
  337. readwcmd (tminc0, tminc, once)
  338. double tminc0;
  339. double *tminc;
  340. int *once;
  341. {
  342.     f_prompt (qprompt);
  343.  
  344.     switch (read_char()) {
  345.     case END:     /* back to table */
  346.         return (-1);
  347.     case '\r':    /* one StpSz step */
  348.         *tminc = tminc0;
  349.         *once = 1;
  350.         break;
  351.     case 'h':    /* one 1-hour step */
  352.         *tminc = 1.0;
  353.         *once = 1;
  354.         break;
  355.     case 'd':    /* one 24-hr step */
  356.         *tminc = 24.0;
  357.         *once = 1;
  358.         break;
  359.     case 'w':    /* 7 day step */
  360.         *tminc = 7*24.0;
  361.         *once = 1;
  362.         break;
  363.     default:        /* free-run */
  364.         *once = 0;
  365.         f_prompt (frprompt);
  366.     }
  367.     return (0);
  368. }
  369.