home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / Apps / Astro / ephem / Source / altmenus.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-12  |  11.1 KB  |  411 lines

  1. /* routines for managing the alternative bottom half menus.
  2.  * planet-specific menus are in their own files.
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <math.h>
  7. #include "astro.h"
  8. #include "circum.h"
  9. #include "screen.h"
  10.  
  11. static int altmenu = F_MNU1;    /* which alternate menu is up; one of F_MNUi */
  12. static int alt2_stdhzn;    /* whether to use STDHZN (aot ADPHZN) horizon algthm  */
  13. static int alt3_geoc;    /* whether to use geocentric (aot topocentric) vantage*/
  14.  
  15. /* table of screen rows given a body #define from astro/h or screen.h */
  16. static short bodyrow[NOBJ] = {
  17.     R_MERCURY, R_VENUS, R_MARS, R_JUPITER, R_SATURN,
  18.     R_URANUS, R_NEPTUNE, R_PLUTO, R_SUN, R_MOON, R_OBJX, R_OBJY
  19. };
  20. /* table of screen cols for third menu format, given body #define ... */
  21. static short bodycol[NOBJ] = {
  22.     C_MERCURY, C_VENUS, C_MARS, C_JUPITER, C_SATURN,
  23.     C_URANUS, C_NEPTUNE, C_PLUTO, C_SUN, C_MOON, C_OBJX, C_OBJY
  24. };
  25.  
  26. /* initialize altmenu; used by main from cracking the ephem startup file.
  27.  */
  28. altmenu_init (n)
  29. int n;
  30. {
  31.     altmenu = n;
  32. }
  33.  
  34. /* let op decide which alternate menu should be up,
  35.  * including any menu-specific setup they might require.
  36.  * return 0 if things changed to require updating the alt menu; else -1.
  37.  */
  38. altmenu_setup()
  39. {
  40.     static char *flds[5] = {
  41.         "Data", "(Rise/Set", "", "(Separations"
  42.     };
  43.     int newmenu = altmenu, newhzn = alt2_stdhzn, newgeoc = alt3_geoc;
  44.     int new;
  45.     int fn = altmenu == F_MNU3 ? 3 : altmenu == F_MNU2 ? 1 : 0;
  46.  
  47.     ask:
  48.     flds[2]= newhzn ? "Standard hzn)" : "Adaptive hzn)";
  49.     flds[4]= newgeoc? "Geocentric)" : "Topocentric)";
  50.  
  51.     switch (popup (flds, fn, 5)) {
  52.     case 0: newmenu = F_MNU1; break;
  53.     case 1: newmenu = F_MNU2; break;
  54.     case 2: newhzn ^= 1; fn = 2; goto ask;
  55.     case 3: newmenu = F_MNU3; break;
  56.     case 4: newgeoc ^= 1; fn = 4; goto ask;
  57.     default: return (-1);
  58.     }
  59.  
  60.     new = 0;
  61.     if (newmenu != altmenu) {
  62.         altmenu = newmenu;
  63.         new++;
  64.     }
  65.     if (newhzn != alt2_stdhzn) {
  66.         alt2_stdhzn = newhzn;
  67.         if (newmenu == F_MNU2)
  68.         new++;
  69.     }
  70.     if (newgeoc != alt3_geoc) {
  71.         alt3_geoc = newgeoc;
  72.         if (newmenu == F_MNU3)
  73.         new++;
  74.     }
  75.     return (new ? 0 : -1);
  76. }
  77.  
  78. /* erase the info for the given planet */
  79. alt_nobody (p)
  80. int p;
  81. {
  82.     f_eol (bodyrow[p], C_RA);
  83. }
  84.  
  85. alt_body (b, force, np)
  86. int b;        /* which body, ala astro.h and screen.h defines */
  87. int force;    /* if !0 then draw for sure, else just if changed since last */
  88. Now *np;
  89. {
  90.     switch (altmenu) {
  91.     case F_MNU1: alt1_body (b, force, np); break;
  92.     case F_MNU2: alt2_body (b, force, np); break;
  93.     case F_MNU3: alt3_body (b, force, np); break;
  94.     }
  95. }
  96.  
  97. /* draw the labels for the current alternate menu format */
  98. alt_labels ()
  99. {
  100.     switch (altmenu) {
  101.     case F_MNU1: alt1_labels (); break;
  102.     case F_MNU2: alt2_labels (); break;
  103.     case F_MNU3: alt3_labels (); break;
  104.     case F_MNUJ: altj_labels (); break;
  105.     }
  106. }
  107.  
  108. alt_erase ()
  109. {
  110.     int i;
  111.  
  112.     for (i = R_PLANTAB; i <= NR; i++)
  113.         f_eol (i, 1);
  114.     f_string (R_ALTM, C_ALTMV, "             ");
  115. }
  116.  
  117. alt_menumask()
  118. {
  119.     return (altmenu);
  120. }
  121.  
  122. /* handy function to return the next planet in the order in which they are
  123.  * displayed in the lower half of the screen.
  124.  * input is a given planet, return is the next planet.
  125.  * if input is not legal, then first planet is returned; when input is the
  126.  * last planet, then -1 is returned.
  127.  * typical usage is something like:
  128.  *   for (p = nxtbody(-1); p != -1; p = nxtbody(p))
  129.  */
  130. nxtbody(p)
  131. int p;
  132. {
  133.     static short nxtpl[NOBJ] = {
  134.         VENUS, MARS, JUPITER, SATURN, URANUS,
  135.         NEPTUNE, PLUTO, OBJX, MOON, MERCURY, OBJY, -1
  136.     };
  137.  
  138.     if (p < MERCURY || p >= NOBJ)
  139.         return (SUN);
  140.     else
  141.         return (nxtpl[p]);
  142. }
  143.  
  144. alt_plnames()
  145. {
  146.     f_string (R_PLANTAB,    C_OBJ,    "OCX");
  147.     f_string (R_SUN,    C_OBJ,    "Su");
  148.     f_string (R_MOON,    C_OBJ,    "Mo");
  149.     f_string (R_MERCURY,    C_OBJ,    "Me");
  150.     f_string (R_VENUS,    C_OBJ,    "Ve");
  151.     f_string (R_MARS,    C_OBJ,    "Ma");
  152.     f_string (R_JUPITER,    C_OBJ,    "Ju");
  153.     f_string (R_SATURN,    C_OBJ,    "Sa");
  154.     f_string (R_URANUS,    C_OBJ,    "Ur");
  155.     f_string (R_NEPTUNE,    C_OBJ,    "Ne");
  156.     f_string (R_PLUTO,    C_OBJ,    "Pl");
  157.     f_string (R_OBJX,    C_OBJ,    "X");
  158.     f_string (R_OBJY,    C_OBJ,    "Y");
  159. }
  160.  
  161. static
  162. alt1_labels()
  163. {
  164.     f_string (R_ALTM, C_ALTMV, "  Planet Data");
  165.  
  166.     alt_plnames();
  167.     f_string (R_PLANTAB,    C_RA+2,    "R.A.");
  168.     f_string (R_PLANTAB,    C_DEC+2,"Dec");
  169.     f_string (R_PLANTAB,    C_AZ+2,    "Az");
  170.     f_string (R_PLANTAB,    C_ALT+2,"Alt");
  171.     f_string (R_PLANTAB,    C_HLONG,"H Long");
  172.     f_string (R_PLANTAB,    C_HLAT,    "H Lat");
  173.     f_string (R_PLANTAB,    C_EDIST,"Ea Dst");
  174.     f_string (R_PLANTAB,    C_SDIST,"Sn Dst");
  175.     f_string (R_PLANTAB,    C_ELONG,"Elong");
  176.     f_string (R_PLANTAB,    C_SIZE,    "Size");
  177.     f_string (R_PLANTAB,    C_MAG,    "VMag");
  178.     f_string (R_PLANTAB,    C_PHASE,"Phs");
  179. }
  180.  
  181. static
  182. alt2_labels()
  183. {
  184.     f_string (R_ALTM, C_ALTMV, "Rise/Set Info");
  185.  
  186.     alt_plnames();
  187.     f_string (R_PLANTAB,    C_RISETM-2,    "Rise Time");
  188.     f_string (R_PLANTAB,    C_RISEAZ,    "Rise Az");
  189.     f_string (R_PLANTAB,    C_TRANSTM-2,    "Trans Time");
  190.     f_string (R_PLANTAB,    C_TRANSALT-1,    "Trans Alt");
  191.     f_string (R_PLANTAB,    C_SETTM-1,    "Set Time");
  192.     f_string (R_PLANTAB,    C_SETAZ,    "Set Az");
  193.     f_string (R_PLANTAB,    C_TUP-1,    "Hours Up");
  194. }
  195.  
  196. static
  197. alt3_labels()
  198. {
  199.     f_string (R_ALTM, C_ALTMV, "  Separations");
  200.  
  201.     alt_plnames();
  202.     f_string (R_PLANTAB,    C_SUN,        " Sun");
  203.     f_string (R_PLANTAB,    C_MOON,        "Moon");
  204.     f_string (R_PLANTAB,    C_MERCURY,    "Merc");
  205.     f_string (R_PLANTAB,    C_VENUS,    "Venus");
  206.     f_string (R_PLANTAB,    C_MARS,        "Mars");
  207.     f_string (R_PLANTAB,    C_JUPITER,    " Jup");
  208.     f_string (R_PLANTAB,    C_SATURN,    " Sat");
  209.     f_string (R_PLANTAB,    C_URANUS,    "Uranus");
  210.     f_string (R_PLANTAB,    C_NEPTUNE,    " Nep");
  211.     f_string (R_PLANTAB,    C_PLUTO,    "Pluto");
  212.     f_string (R_PLANTAB,    C_OBJX,        "  X");
  213.     f_string (R_PLANTAB,    C_OBJY,        "  Y");
  214. }
  215.  
  216. /* print body info in first menu format */
  217. static
  218. alt1_body (p, force, np)
  219. int p;        /* which body, as in astro.h/screen.h defines */
  220. int force;    /* whether to print for sure or only if things have changed */
  221. Now *np;
  222. {
  223.     Sky sky;
  224.     double as = plot_ison() || srch_ison() ? 0.0 : 60.0;
  225.     int row = bodyrow[p];
  226.  
  227.     if (body_cir (p, as, np, &sky) || force) {
  228.         f_ra (row, C_RA, sky.s_ra);
  229.         f_angle (row, C_DEC, sky.s_dec);
  230.         if (sky.s_hlong != NOHELIO) {
  231.         f_angle (row, C_HLONG, sky.s_hlong);
  232.         if (p != SUN)
  233.             f_angle (row, C_HLAT, sky.s_hlat);
  234.         }
  235.  
  236.         if (p == MOON) {
  237.         /* distance is on km, show in miles */
  238.         f_double (R_MOON, C_EDIST, "%6.0f", sky.s_edist/1.609344);
  239.         } else if (sky.s_edist > 0.0) {
  240.         /* show distance in au */
  241.         f_double (row, C_EDIST,(sky.s_edist>=10.0)?"%6.3f":"%6.4f",
  242.                                 sky.s_edist);
  243.         }
  244.         if (sky.s_sdist > 0.0)
  245.         f_double (row, C_SDIST, (sky.s_sdist>=9.99995)?"%6.3f":"%6.4f",
  246.                                 sky.s_sdist);
  247.         if (p != SUN)
  248.         f_double (row, C_ELONG, "%6.1f", sky.s_elong);
  249.         f_double (row, C_SIZE, sky.s_size >= 99.95 ?"%4.0f":"%4.1f",
  250.                                 sky.s_size);
  251.         f_double (row, C_MAG, sky.s_mag <= -9.95 ? "%4.0f" : "%4.1f",
  252.                                 sky.s_mag);
  253.         if (sky.s_sdist > 0.0) {
  254.         /* some terminals scroll when write a char in low-right corner.
  255.          * TODO: is there a nicer way to handle this maybe?
  256.          */
  257.         int col = row == NR ? C_PHASE - 1 : C_PHASE;
  258.         /* would just do this if Turbo-C 2.0 "%?.0f" worked:
  259.          * f_double (row, col, "%3.0f", sky.s_phase);
  260.          */
  261.         f_int (row, col, "%3d", sky.s_phase);
  262.         }
  263.     }
  264.  
  265.     f_angle (row, C_AZ, sky.s_az);
  266.     f_angle (row, C_ALT, sky.s_alt);
  267. }
  268.  
  269. /* print body info in the second menu format */
  270. static
  271. alt2_body (p, force, np)
  272. int p;        /* which body, as in astro.h/screen.h defines */
  273. int force;    /* whether to print for sure or only if things have changed */
  274. Now *np;
  275. {
  276.     double ltr, lts, ltt, azr, azs, altt;
  277.     int row = bodyrow[p];
  278.     int status;
  279.     double tmp;
  280.     int today_tup = 0;
  281.  
  282.     /* always recalc OBJX and Y since we don't know it's the same object */
  283.     if (!riset_cir (p, np, p==OBJX || p==OBJY, alt2_stdhzn?STDHZN:ADPHZN,
  284.         <r, <s, <t, &azr, &azs, &altt, &status) && !force)
  285.         return;
  286.  
  287.     alt_nobody (p);
  288.  
  289.     if (status & RS_ERROR) {
  290.         /* can not find where body is! */
  291.         f_string (row, C_RISETM, "?Error?");
  292.         return;
  293.     }
  294.     if (status & RS_CIRCUMPOLAR) {
  295.         /* body is up all day */
  296.         f_string (row, C_RISETM, "Circumpolar");
  297.         if (status & RS_NOTRANS)
  298.         f_string (row, C_TRANSTM, "No transit");
  299.         else {
  300.         f_mtime (row, C_TRANSTM, ltt);
  301.         if (status & RS_2TRANS)
  302.             f_char (row, C_TRANSTM+5, '+');
  303.         f_angle (row, C_TRANSALT, altt);
  304.         }
  305.         f_string (row, C_TUP, "24:00"); /*f_mtime() changes to 0:00 */
  306.         return;
  307.     }
  308.     if (status & RS_NEVERUP) {
  309.         /* body never up at all today */
  310.         f_string (row, C_RISETM, "Never up");
  311.         f_mtime (row, C_TUP, 0.0);
  312.         return;
  313.     }
  314.  
  315.     if (status & RS_NORISE) {
  316.         /* object does not rise as such today */
  317.         f_string (row, C_RISETM, "Never rises");
  318.         ltr = 0.0; /* for TUP */
  319.         today_tup = 1;
  320.     } else {
  321.         f_mtime (row, C_RISETM, ltr);
  322.         if (status & RS_2RISES) {
  323.         /* object rises more than once today */
  324.         f_char (row, C_RISETM+5, '+');
  325.         }
  326.         f_angle (row, C_RISEAZ, azr);
  327.     }
  328.  
  329.     if (status & RS_NOTRANS)
  330.         f_string (row, C_TRANSTM, "No transit");
  331.     else {
  332.         f_mtime (row, C_TRANSTM, ltt);
  333.         if (status & RS_2TRANS)
  334.         f_char (row, C_TRANSTM+5, '+');
  335.         f_angle (row, C_TRANSALT, altt);
  336.     }
  337.  
  338.     if (status & RS_NOSET) {
  339.         /* object does not set as such today */
  340.         f_string (row, C_SETTM, "Never sets");
  341.         lts = 24.0;    /* for TUP */
  342.         today_tup = 1;
  343.     } else {
  344.         f_mtime (row, C_SETTM, lts);
  345.         if (status & RS_2SETS)
  346.         f_char (row, C_SETTM+5, '+');
  347.         f_angle (row, C_SETAZ, azs);
  348.     }
  349.  
  350.     tmp = lts - ltr;
  351.     if (tmp < 0)
  352.         tmp = 24.0 + tmp;
  353.     f_mtime (row, C_TUP, tmp);
  354.     if (today_tup)
  355.         f_char (row, C_TUP+5, '+');
  356. }
  357.  
  358. /* print body info in third menu format. this may be either the geocentric
  359.  *   or topocentric angular separation between object p and each of the others.
  360.  *   the latter, of course, includes effects of refraction and so can change
  361.  *   quite rapidly near the time of each planets rise or set.
  362.  * for now, we don't save old values so we always redo everything and ignore
  363.  *  the "force" argument. this isn't that bad since body_cir() has memory and
  364.  *   will avoid most computations as we hit them again in the lower triangle.
  365.  * we are limited to only 5 columns per object. to make it fit, we display
  366.  *   degrees:minutes if less than 100 degrees, otherwise just whole degrees.
  367.  */
  368. /*ARGSUSED*/
  369. static
  370. alt3_body (p, force, np)
  371. int p;        /* which body, as in astro.h/screen.h defines */
  372. int force;    /* whether to print for sure or only if things have changed */
  373. Now *np;
  374. {
  375.     int row = bodyrow[p];
  376.     Sky skyp, skyq;
  377.     double spy, cpy, px, *qx, *qy;
  378.     int wantx = obj_ison(OBJX);
  379.     int wanty = obj_ison(OBJY);
  380.     double as = plot_ison() || srch_ison() ? 0.0 : 60.0;
  381.     int q;
  382.  
  383.     (void) body_cir (p, as, np, &skyp);
  384.     if (alt3_geoc) {
  385.         /* use ra for "x", dec for "y". */
  386.         spy = sin (skyp.s_dec);
  387.         cpy = cos (skyp.s_dec);
  388.         px = skyp.s_ra;
  389.         qx = &skyq.s_ra;
  390.         qy = &skyq.s_dec;
  391.     } else {
  392.         /* use azimuth for "x", altitude for "y". */
  393.         spy = sin (skyp.s_alt);
  394.         cpy = cos (skyp.s_alt);
  395.         px = skyp.s_az;
  396.         qx = &skyq.s_az;
  397.         qy = &skyq.s_alt;
  398.     }
  399.     for (q = nxtbody(-1); q != -1; q = nxtbody(q))
  400.         if (q != p && (q != OBJX || wantx) && (q != OBJY || wanty)) {
  401.         double sep, dsep;
  402.         (void) body_cir (q, as, np, &skyq);
  403.         sep = acos(spy*sin(*qy) + cpy*cos(*qy)*cos(px-*qx));
  404.         dsep = raddeg(sep);
  405.         if (dsep >= (100.0 - 1.0/60.0/2.0))
  406.             f_int (row, bodycol[q], "%5d:", dsep);
  407.         else
  408.             f_angle (row, bodycol[q], sep);
  409.         }
  410. }
  411.