ecd@cs.umn.edu@ncs-med.UUCP (Elwood C. Downey) (03/11/90)
Posting-number: Volume 11, Issue 5 Submitted-by: ecd@cs.umn.edu@ncs-med.UUCP (Elwood C. Downey) Archive-name: ephem4.12/part04 # This is the first line of a "shell archive" file. # This means it contains several files that can be extracted into # the current directory when run with the sh shell, as follows: # sh < this_file_name # This is file 4. echo x plot.c sed -e 's/^X//' << 'EOFxEOF' > plot.c X/* code to support the plotting capabilities. X * idea is to let the operator name a plot file and mark some fields for X * logging. then after each screen update, the logged fields are written to X * the plot file. later, the file may be plotted (very simplistically by X * ephem, for now anyway, or by some other program entirely.). X * X * format of the plot file is one line per coordinate: label,x,y X * if z was specified, it is a fourth field. X * x,y,z are plotted using %g format. X */ X X#include <stdio.h> X#include <math.h> X#include "screen.h" X Xextern char *strcpy(); Xextern errno; Xextern char *sys_errlist[]; X#define errsys (sys_errlist[errno]) X X#define TRACE(x) {FILE *fp = fopen("trace","a"); fprintf x; fclose(fp);} X X#define MAXPLTLINES 10 /* max number of labeled lines we can track. X * note we can't store more than NFLOGS fields X * anyway (see flog.c). X */ X#define FNLEN (14+1) /* longest filename; plus 1 for \0 */ X Xstatic char plt_filename[FNLEN] = "ephem.plt"; /* default plot file name */ Xstatic FILE *plt_fp; /* the plot file; == 0 means don't plot */ X X/* store the label and rcfpack()s for each line to track. */ Xtypedef struct { X char pl_label; X int pl_rcpx, pl_rcpy, pl_rcpz; X} PltLine; Xstatic PltLine pltlines[MAXPLTLINES]; Xstatic int npltlines; /* number of pltlines[] in actual use */ X Xstatic int plt_in_polar; /*if true plot in polar coords, else cartesian*/ Xstatic int pltsrchfld; /* set when the Search field is to be plotted */ X X/* picked the Plot label: X * if on, just turn it off. X * if off, turn on, define fields or select name of file to plot and do it. X * TODO: more flexibility, more relevance. X */ Xplot_setup() X{ X if (plt_fp) X plt_turn_off(); X else { X static char *chcs[4] = { X "Select fields", "Display a plot file", (char *)0, X "Begin plotting" X }; X int ff = 0; X ask: X chcs[2] = plt_in_polar ? "Polar coords" : "Cartesian coords"; X switch (popup(chcs, ff, npltlines > 0 ? 4 : 3)) { X case 0: plt_select_fields(); break; X case 1: plt_file(); break; X case 2: plt_in_polar ^= 1; ff = 2; goto ask; X case 3: plt_turn_on(); break; X } X } X} X X/* write the active plotfields to the current plot file, if one is open. */ Xplot() X{ X if (plt_fp) { X PltLine *plp; X double x, y, z; X if (!srch_ison() && pltsrchfld) { X /* if searching is not on but we are plotting the search X * funtion we must evaluate and log it ourselves here and now. X * plt_turn_on() insured there is a good function to eval. X * N.B. if searching IS on, we rely on main() having called X * srch_eval() BEFORE plot() so it is already evaluated. X */ X double e; X char errmsg[128]; X if (execute_expr (&e, errmsg) < 0) { X f_msg (errmsg); X plt_turn_off(); X return; X } else X flog_log (R_SRCH, C_SRCH, e); X } X /* plot in order of original selection */ X for (plp = pltlines; plp < &pltlines[npltlines]; plp++) { X if (flog_get (plp->pl_rcpx, &x) == 0 X && flog_get (plp->pl_rcpy, &y) == 0) { X fprintf (plt_fp, "%c,%.12g,%.12g", plp->pl_label, x, y); X if (flog_get (plp->pl_rcpz, &z) == 0) X fprintf (plt_fp, ",%.12g", z); X fprintf (plt_fp, "\n"); X } X } X } X} X Xplot_prstate (force) Xint force; X{ X static last; X int this = plt_fp != 0; X X if (force || this != last) { X f_string (R_PLOT, C_PLOTV, this ? " on" : "off"); X last = this; X } X} X Xplot_ison() X{ X return (plt_fp != 0); X} X Xstatic Xplt_reset() X{ X PltLine *plp; X X for (plp = &pltlines[npltlines]; --plp >= pltlines; ) { X (void) flog_delete (plp->pl_rcpx); X (void) flog_delete (plp->pl_rcpy); X (void) flog_delete (plp->pl_rcpz); X plp->pl_rcpx = plp->pl_rcpy = plp->pl_rcpz = 0; X } X npltlines = 0; X pltsrchfld = 0; X} X X/* let operator select the fields he wants to plot. X * register them with flog and keep rcfpack() in pltlines[] array. X * as a special case, set pltsrchfld if Search field is selected. X */ Xstatic Xplt_select_fields() X{ X static char hlp[] = "move and RETURN to select a field, or q to quit"; X static char sry[] = "Sorry; can not log any more fields."; X int r = R_UT, c = C_UTV; /* TODO: start where main was? */ X int sf = rcfpack (R_SRCH, C_SRCH, 0); X char buf[64]; X int rcp; X int i; X X plt_reset(); X for (i = 0; i < MAXPLTLINES; i++) { X sprintf (buf, "select x field for line %d", i+1); X rcp = sel_fld (r, c, alt_menumask()|F_PLT, buf, hlp); X if (!rcp) X break; X if (flog_add (rcp) < 0) { X f_msg (sry); X break; X } X pltlines[i].pl_rcpx = rcp; X if (rcp == sf) X pltsrchfld = 1; X X sprintf (buf, "select y field for line %d", i+1); X r = unpackr (rcp); c = unpackc (rcp); X rcp = sel_fld (r, c, alt_menumask()|F_PLT, buf, hlp); X if (!rcp) { X (void) flog_delete (pltlines[i].pl_rcpx); X break; X } X if (flog_add (rcp) < 0) { X (void) flog_delete (pltlines[i].pl_rcpx); X f_msg (sry); X break; X } X pltlines[i].pl_rcpy = rcp; X if (rcp == sf) X pltsrchfld = 1; X X sprintf (buf, "select z field for line %d", i+1); X r = unpackr (rcp); c = unpackc (rcp); X rcp = sel_fld (r, c, alt_menumask()|F_PLT, buf, hlp); X if (rcp) { X if (flog_add (rcp) < 0) { X (void) flog_delete (pltlines[i].pl_rcpx); X (void) flog_delete (pltlines[i].pl_rcpy); X f_msg (sry); X break; X } X pltlines[i].pl_rcpz = rcp; X if (rcp == sf) X pltsrchfld = 1; X r = unpackr (rcp); c = unpackc (rcp); X } X X do { X sprintf (buf, "enter a one-character label for line %d: ", i+1); X f_prompt (buf); X } while (read_line (buf, 1) != 1); X pltlines[i].pl_label = *buf; X } X npltlines = i; X} X Xstatic Xplt_turn_off () X{ X fclose (plt_fp); X plt_fp = 0; X plot_prstate(0); X} X X/* turn on plotting. X * establish a file to use (and thereby set plt_fp, the plotting_is_on flag). X * also check that there is a srch function if it is being plotted. X */ Xstatic Xplt_turn_on () X{ X int sf = rcfpack(R_SRCH, C_SRCH, 0); X char fn[FNLEN], fnq[64]; X char *optype; X int n; X PltLine *plp; X X /* insure there is a valid srch function if we are to plot it */ X for (plp = &pltlines[npltlines]; --plp >= pltlines; ) X if ((plp->pl_rcpx == sf || plp->pl_rcpy == sf || plp->pl_rcpz == sf) X && !prog_isgood()) { X f_msg ("Plotting search function but it is not defined."); X return; X } X X /* prompt for file name, giving current as default */ X sprintf (fnq, "file to write <%s>: ", plt_filename); X f_prompt (fnq); X n = read_line (fn, sizeof(fn)-1); X X /* leave plotting off if type END. X * reuse same fn if just type \n X */ X if (n < 0) X return; X if (n > 0) X strcpy (plt_filename, fn); X X /* give option to append if file already exists */ X optype = "w"; X if (access (plt_filename, 2) == 0) { X while (1) { X f_prompt ("files exists; append or overwrite (a/o)?: "); X n = read_char(); X if (n == 'a') { X optype = "a"; X break; X } X if (n == 'o') X break; X } X } X X /* plotting is on if file opens ok */ X plt_fp = fopen (plt_filename, optype); X if (!plt_fp) { X char buf[NC]; X sprintf (buf, "can not open %s: %s", plt_filename, errsys); X f_prompt (buf); X (void)read_char(); X } X plot_prstate (0); X} X X/* ask operator for a file to plot. if it's ok, do it. X */ Xstatic Xplt_file () X{ X char fn[FNLEN], fnq[64]; X FILE *pfp; X int n; X X /* prompt for file name, giving current as default */ X sprintf (fnq, "file to read <%s>: ", plt_filename); X f_prompt (fnq); X n = read_line (fn, sizeof(fn)-1); X X /* forget it if type END. X * reuse same fn if just type \n X */ X if (n < 0) X return; X if (n > 0) X strcpy (plt_filename, fn); X X /* do the plot if file opens ok */ X pfp = fopen (plt_filename, "r"); X if (pfp) { X if (plt_in_polar) X plot_polar (pfp); X else X plot_cartesian (pfp); X fclose (pfp); X } else { X char buf[NC]; X sprintf (buf, "can not open %s: %s", plt_filename, errsys); X f_prompt (buf); X (void)read_char(); X } X} X X/* plot the given file on the screen in cartesian coords. X * TODO: add z tags somehow X * N.B. do whatever you like but redraw the screen when done. X */ Xstatic Xplot_cartesian (pfp) XFILE *pfp; X{ X static char fmt[] = "%c,%lf,%lf"; X double x, y; /* N.B. be sure these match what scanf's %lf wants*/ X double minx, maxx, miny, maxy; X char buf[128]; X int npts = 0; X char c; X X /* find ranges and number of points */ X while (fgets (buf, sizeof(buf), pfp)) { X sscanf (buf, fmt, &c, &x, &y); X if (npts++ == 0) { X maxx = minx = x; X maxy = miny = y; X } else { X if (x > maxx) maxx = x; X else if (x < minx) minx = x; X if (y > maxy) maxy = y; X else if (y < miny) miny = y; X } X } X X#define SMALL (1e-10) X if (npts < 2 || fabs(minx-maxx) < SMALL || fabs(miny-maxy) < SMALL) X f_prompt ("At least two different points required to plot."); X else { X /* read file again, this time plotting */ X rewind (pfp); X c_erase(); X while (fgets (buf, sizeof(buf), pfp)) { X int row, col; X sscanf (buf, fmt, &c, &x, &y); X row = NR-(int)((NR-1)*(y-miny)/(maxy-miny)+0.5); X col = 1+(int)((NC-1)*(x-minx)/(maxx-minx)+0.5); X if (row == NR && col == NC) X col--; /* avoid lower right scrolling corner */ X f_char (row, col, c); X } X X /* label axes */ X f_double (1, 1, "%.2g", maxy); X f_double (NR-1, 1, "%.2g", miny); X f_double (NR, 1, "%.2g", minx); X f_double (NR, NC-10, "%.2g", maxx); X } X X /* hit any key to resume... */ X (void) read_char(); X redraw_screen (2); /* full redraw */ X} X X/* plot the given file on the screen in polar coords. X * first numberic field in plot file is r, second is theta in degrees. X * TODO: add z tags somehow X * N.B. do whatever you like but redraw the screen when done. X */ Xstatic Xplot_polar (pfp) XFILE *pfp; X{ X static char fmt[] = "%c,%lf,%lf"; X double r, th; /* N.B. be sure these match what scanf's %lf wants*/ X double maxr; X char buf[128]; X int npts = 0; X char c; X X /* find ranges and number of points */ X while (fgets (buf, sizeof(buf), pfp)) { X sscanf (buf, fmt, &c, &r, &th); X if (npts++ == 0) X maxr = r; X else X if (r > maxr) X maxr = r; X } X X if (npts < 2) X f_prompt ("At least two points required to plot."); X else { X /* read file again, this time plotting */ X rewind (pfp); X c_erase(); X while (fgets (buf, sizeof(buf), pfp)) { X int row, col; X double x, y; X sscanf (buf, fmt, &c, &r, &th); X x = r * cos(th/57.2958); /* degs to rads */ X y = r * sin(th/57.2958); X row = NR-(int)((NR-1)*(y+maxr)/(2.0*maxr)+0.5); X col = 1+(int)((NC-1)*(x+maxr)/(2.0*maxr)/ASPECT+0.5); X if (row == NR && col == NC) X col--; /* avoid lower right scrolling corner */ X f_char (row, col, c); X } X X /* label radius */ X f_double (NR/2, NC-10, "%.4g", maxr); X } X X /* hit any key to resume... */ X (void) read_char(); X redraw_screen (2); /* full redraw */ X} EOFxEOF len=`wc -c < plot.c` if expr $len != 10712 > /dev/null then echo Length of plot.c is $len but it should be 10712. fi echo x popup.c sed -e 's/^X//' << 'EOFxEOF' > popup.c X/* put up a one-line menu consisting of the given fields and let op move X * between them with the same methods as sel_fld(). X * return index of which he picked, or -1 if hit END. X */ X X#include <stdio.h> X#include "screen.h" X X#define FLDGAP 2 /* inter-field gap */ X#define MAXFLDS 32 /* max number of fields we can handle */ X Xstatic char pup[] = "Select: "; X X/* put up an array of strings on prompt line and let op pick one. X * start with field fn. X * N.B. we do not do much error/bounds checking. X */ Xpopup (fields, fn, nfields) Xchar *fields[]; Xint fn; Xint nfields; X{ X int fcols[MAXFLDS]; /* column to use for each field */ X int i; X X if (nfields > MAXFLDS) X return (-1); X X again: X /* erase the prompt line; we are going to take it over */ X c_pos (R_PROMPT, C_PROMPT); X c_eol(); X X /* compute starting column for each field */ X fcols[0] = sizeof(pup); X for (i = 1; i < nfields; i++) X fcols[i] = fcols[i-1] + strlen (fields[i-1]) + FLDGAP; X X /* draw each field, with comma after all but last */ X c_pos (R_PROMPT, 1); X fputs (pup, stdout); X for (i = 0; i < nfields; i++) { X c_pos (R_PROMPT, fcols[i]); X printf (i < nfields-1 ? "%s," : "%s", fields[i]); X } X X /* let op choose one now; begin at fn. X */ X i = fn; X while (1) { X c_pos (R_PROMPT, fcols[i]); X switch (read_char()) { X case END: return (-1); X case REDRAW: redraw_screen(2); goto again; X case VERSION: version(); goto again; X case '\r': return (i); X case 'h': X if (--i < 0) X i = nfields - 1; X break; X case 'l': X if (++i >= nfields) X i = 0; X break; X } X } X} EOFxEOF len=`wc -c < popup.c` if expr $len != 1578 > /dev/null then echo Length of popup.c is $len but it should be 1578. fi echo x precess.c sed -e 's/^X//' << 'EOFxEOF' > precess.c X#include <stdio.h> X#include <math.h> X#include "astro.h" X X/* corrects ra and dec, both in radians, for precession from epoch 1 to epoch 2. X * the epochs are given by their modified JDs, mjd1 and mjd2, respectively. X * N.B. ra and dec are modifed IN PLACE. X */ Xprecess (mjd1, mjd2, ra, dec) Xdouble mjd1, mjd2; /* initial and final epoch modified JDs */ Xdouble *ra, *dec; /* ra/dec for mjd1 in, for mjd2 out */ X{ X static double lastmjd1, lastmjd2; X static double m, n, nyrs; X double dra, ddec; /* ra and dec corrections */ X X if (mjd1 != lastmjd1 || mjd2 != lastmjd2) { X double t1, t2; /* Julian centuries of 36525 days since Jan .5 1900*/ X double m1, n1; /* "constants" for t1 */ X double m2, n2; /* "constants" for t2 */ X t1 = mjd1/36525.; X t2 = mjd2/36525.; X m1 = 3.07234+(1.86e-3*t1); X n1 = 20.0468-(8.5e-3*t1); X m2 = 3.07234+(1.86e-3*t2); X n2 = 20.0468-(8.5e-3*t2); X m = (m1+m2)/2; /* average m for the two epochs */ X n = (n1+n2)/2; /* average n for the two epochs */ X nyrs = (mjd2-mjd1)/365.2425; X lastmjd1 = mjd1; X lastmjd2 = mjd2; X } X X dra = (m+(n*sin(*ra)*tan(*dec)/15))*7.272205e-5*nyrs; X ddec = n*cos(*ra)*4.848137e-6*nyrs; X *ra += dra; X *dec += ddec; X /* added by ECD */ X if (*dec > PI/2) { X *dec = PI - *dec; X *ra += PI; X } else if (*dec < -PI/2) { X *dec = -PI - *dec; X *ra += PI; X } X range (ra, 2*PI); X} EOFxEOF len=`wc -c < precess.c` if expr $len != 1385 > /dev/null then echo Length of precess.c is $len but it should be 1385. fi echo x reduce.c sed -e 's/^X//' << 'EOFxEOF' > reduce.c X#include <math.h> X#include "astro.h" X X/* convert those orbital elements that change from epoch mjd0 to epoch mjd. X */ Xreduce_elements (mjd0, mjd, inc0, ap0, om0, inc, ap, om) Xdouble mjd0; /* initial epoch */ Xdouble mjd; /* desired epoch */ Xdouble inc0; /* initial inclination, rads */ Xdouble ap0; /* initial argument of perihelion, as an mjd */ Xdouble om0; /* initial , rads */ Xdouble *inc; /* desired inclination, rads */ Xdouble *ap; /* desired epoch of perihelion, as an mjd */ Xdouble *om; /* desired , rads */ X{ X double t0, t1; X double tt, tt2, t02, tt3; X double eta, th, th0; X double a, b; X double dap; X double cinc, sinc; X double ot, sot, cot, ot1; X double seta, ceta; X X t0 = mjd0/365250.0; X t1 = mjd/365250.0; X X tt = t1-t0; X tt2 = tt*tt; X t02 = t0*t0; X tt3 = tt*tt2; X eta = (471.07-6.75*t0+.57*t02)*tt+(.57*t0-3.37)*tt2+.05*tt3; X th0 = 32869.0*t0+56*t02-(8694+55*t0)*tt+3*tt2; X eta = degrad(eta/3600.0); X th0 = degrad((th0/3600.0)+173.950833); X th = (50256.41+222.29*t0+.26*t02)*tt+(111.15+.26*t0)*tt2+.1*tt3; X th = th0+degrad(th/3600.0); X cinc = cos(inc0); X sinc = sin(inc0); X ot = om0-th0; X sot = sin(ot); X cot = cos(ot); X seta = sin(eta); X ceta = cos(eta); X a = sinc*sot; X b = ceta*sinc*cot-seta*cinc; X ot1 = atan(a/b); X if (b<0) ot1 += PI; X b = sinc*ceta-cinc*seta*cot; X a = -1*seta*sot; X dap = atan(a/b); X if (b<0) dap += PI; X X *ap = ap0+dap; X range (ap, 2*PI); X *om = ot1+th; X range (om, 2*PI); X X if (inc0<.175) X *inc = asin(a/sin(dap)); X else X *inc = 1.570796327-asin((cinc*ceta)+(sinc*seta*cot)); X} EOFxEOF len=`wc -c < reduce.c` if expr $len != 1647 > /dev/null then echo Length of reduce.c is $len but it should be 1647. fi echo x refract.c sed -e 's/^X//' << 'EOFxEOF' > refract.c X#include <stdio.h> X#include <math.h> X#include "astro.h" X X/* correct the true altitude, ta, for refraction to the apparent altitude, aa, X * each in radians, given the local atmospheric pressure, pr, in mbars, and X * the temperature, tr, in degrees C. X */ Xrefract (pr, tr, ta, aa) Xdouble pr, tr; Xdouble ta; Xdouble *aa; X{ X double r; /* refraction correction*/ X X if (ta >= degrad(15.)) { X /* model for altitudes at least 15 degrees above horizon */ X r = 7.888888e-5*pr/((273+tr)*tan(ta)); X } else if (ta > degrad(-5.)) { X /* hairier model for altitudes at least -5 and below 15 degrees */ X double a, b, tadeg = raddeg(ta); X a = ((2e-5*tadeg+1.96e-2)*tadeg+1.594e-1)*pr; X b = (273+tr)*((8.45e-2*tadeg+5.05e-1)*tadeg+1); X r = degrad(a/b); X } else { X /* do nothing if more than 5 degrees below horizon. X */ X r = 0; X } X X *aa = ta + r; X} X X/* correct the apparent altitude, aa, for refraction to the true altitude, ta, X * each in radians, given the local atmospheric pressure, pr, in mbars, and X * the temperature, tr, in degrees C. X */ Xunrefract (pr, tr, aa, ta) Xdouble pr, tr; Xdouble aa; Xdouble *ta; X{ X double err; X double appar; X double true; X X /* iterative solution: search for the true that refracts to the X * given apparent. X * since refract() is discontinuous at -5 degrees, there is a range X * of apparent altitudes between about -4.5 and -5 degrees that are X * not invertable (the graph of ap vs. true has a vertical step at X * true = -5). thus, the iteration just oscillates if it gets into X * this region. if this happens the iteration is forced to abort. X * of course, this makes unrefract() discontinuous too. X */ X true = aa; X do { X refract (pr, tr, true, &appar); X err = appar - aa; X true -= err; X } while (fabs(err) >= 1e-6 && true > degrad(-5)); X X *ta = true; X} EOFxEOF len=`wc -c < refract.c` if expr $len != 1857 > /dev/null then echo Length of refract.c is $len but it should be 1857. fi echo x riset.c sed -e 's/^X//' << 'EOFxEOF' > riset.c X#include <stdio.h> X#include <math.h> X#include "astro.h" X X/* given the true geocentric ra and dec of an object, in radians, the observer's X * latitude in radians, and a horizon displacement correction, dis, in radians X * find the local sidereal times and azimuths of rising and setting, lstr/s X * and azr/s, in radians, respectively. X * dis is the vertical displacement from the true position of the horizon. it X * is positive if the apparent position is higher than the true position. X * said another way, it is positive if the shift causes the object to spend X * longer above the horizon. for example, atmospheric refraction is typically X * assumed to produce a vertical shift of 34 arc minutes at the horizon; dis X * would then take on the value +9.89e-3 (radians). On the other hand, if X * your horizon has hills such that your apparent horizon is, say, 1 degree X * above sea level, you would allow for this by setting dis to -1.75e-2 X * (radians). X * status: 0: normal; 1: never rises; -1: circumpolar; 2: trouble. X */ Xriset (ra, dec, lat, dis, lstr, lsts, azr, azs, status) Xdouble ra, dec; Xdouble lat, dis; Xdouble *lstr, *lsts; Xdouble *azr, *azs; Xint *status; X{ X static double lastlat = 0, slat = 0, clat = 1.0; X double dec1, sdec, cdec, tdec; X double psi, spsi, cpsi; X double h, dh, ch; /* hr angle, delta and cos */ X X /* avoid needless sin/cos since latitude doesn't change often */ X if (lat != lastlat) { X clat = cos(lat); X slat = sin(lat); X lastlat = lat; X } X X /* can't cope with objects very near the celestial pole nor if we X * are located very near the earth's poles. X */ X cdec = cos(dec); X if (fabs(cdec*clat) < 1e-10) { X /* trouble */ X *status = 2; X return; X } X X cpsi = slat/cdec; X if (cpsi>1.0) cpsi = 1.0; X else if (cpsi<-1.0) cpsi = -1.0; X psi = acos(cpsi); X spsi = sin(psi); X X dh = dis*spsi; X dec1 = dec + (dis*cpsi); X sdec = sin(dec1); X tdec = tan(dec1); X X ch = (-1*slat*tdec)/clat; X X if (ch < -1) { X /* circumpolar */ X *status = -1; X return; X } X if (ch > 1) { X /* never rises */ X *status = 1; X return; X } X X *status = 0; X h = acos(ch)+dh; X X *lstr = 24+radhr(ra-h); X *lsts = radhr(ra+h); X range (lstr, 24.0); X range (lsts, 24.0); X X *azr = acos(sdec/clat); X range (azr, 2*PI); X *azs = 2*PI - *azr; X} EOFxEOF len=`wc -c < riset.c` if expr $len != 2388 > /dev/null then echo Length of riset.c is $len but it should be 2388. fi echo x riset_c.c sed -e 's/^X//' << 'EOFxEOF' > riset_c.c X/* find rise and set circumstances, ie, riset_cir() and related functions. */ X X#include <stdio.h> X#include <math.h> X#include "astro.h" X#include "circum.h" X#include "screen.h" /* just for SUN and MOON */ X X#define TRACE(x) {FILE *fp = fopen("trace","a"); fprintf x; fclose(fp);} X X#define STDREF degrad(34./60.) /* nominal horizon refraction amount */ X#define TWIREF degrad(18.) /* twilight horizon displacement */ X X/* find where and when a body, p, will rise and set and X * its transit circumstances. all times are local, angles rads e of n. X * return 0 if just returned same stuff as previous call, else 1 if new. X * status is set from the RS_* #defines in circum.h. X * also used to find astro twilight by calling with dis of 18 degrees. X */ Xriset_cir (p, np, hzn, ltr, lts, ltt, azr, azs, altt, status) Xint p; /* one of the body defines in astro.h or screen.h */ XNow *np; Xint hzn; /* STDHZN or ADPHZN or TWILIGHT */ Xdouble *ltr, *lts; /* local rise and set times */ Xdouble *ltt; /* local transit time */ Xdouble *azr, *azs; /* local rise and set azimuths, rads e of n */ Xdouble *altt; /* local altitude at transit */ Xint *status; /* one or more of the RS_* defines */ X{ X typedef struct { X Now l_now; X double l_ltr, l_lts, l_ltt, l_azr, l_azs, l_altt; X int l_hzn; X int l_status; X } Last; X /* must be in same order as the astro.h/screen.h #define's */ X static Last last[NOBJ]; X Last *lp; X int new; X X lp = last + p; X if (same_cir (np, &lp->l_now) && same_lday (np, &lp->l_now) X && lp->l_hzn == hzn) { X *ltr = lp->l_ltr; X *lts = lp->l_lts; X *ltt = lp->l_ltt; X *azr = lp->l_azr; X *azs = lp->l_azs; X *altt = lp->l_altt; X *status = lp->l_status; X new = 0; X } else { X *status = 0; X iterative_riset (p, np, hzn, ltr, lts, ltt, azr, azs, altt, status); X lp->l_ltr = *ltr; X lp->l_lts = *lts; X lp->l_ltt = *ltt; X lp->l_azr = *azr; X lp->l_azs = *azs; X lp->l_altt = *altt; X lp->l_status = *status; X lp->l_hzn = hzn; X lp->l_now = *np; X new = 1; X } X return (new); X} X Xstatic Xiterative_riset (p, np, hzn, ltr, lts, ltt, azr, azs, altt, status) Xint p; XNow *np; Xint hzn; Xdouble *ltr, *lts, *ltt; /* local times of rise, set and transit */ Xdouble *azr, *azs, *altt;/* local azimuths of rise, set and transit altitude */ Xint *status; X{ X#define MAXPASSES 6 X double lstr, lsts, lstt; /* local sidereal times of rising/setting */ X double mjd0; /* mjd estimates of rise/set event */ X double lnoon; /* mjd of local noon */ X double x; /* discarded tmp value */ X Now n; /* just used to call now_lst() */ X double lst; /* lst at local noon */ X double diff, lastdiff; /* iterative improvement to mjd0 */ X int pass; X int rss; X X /* first approximation is to find rise/set times of a fixed object X * in its position at local noon. X */ X lnoon = mjd_day(mjd - tz/24.0) + (12.0 + tz)/24.0; /*mjd of local noon*/ X n.n_mjd = lnoon; X n.n_lng = lng; X now_lst (&n, &lst); /* lst at local noon */ X mjd0 = lnoon; X stationary_riset (p,mjd0,np,hzn,&lstr,&lsts,&lstt,&x,&x,&x,&rss); X chkrss: X switch (rss) { X case 0: break; X case 1: *status = RS_NEVERUP; return; X case -1: *status = RS_CIRCUMPOLAR; goto transit; X default: *status = RS_ERROR; return; X } X X /* find a better approximation to the rising circumstances based on X * more passes, each using a "fixed" object at the location at X * previous approximation of the rise time. X */ X lastdiff = 1000.0; X for (pass = 1; pass < MAXPASSES; pass++) { X diff = (lstr - lst)*SIDRATE; /* next guess at rise time wrt noon */ X if (diff > 12.0) X diff -= 24.0*SIDRATE; /* not tomorrow, today */ X else if (diff < -12.0) X diff += 24.0*SIDRATE; /* not yesterday, today */ X mjd0 = lnoon + diff/24.0; /* next guess at mjd of rise */ X stationary_riset (p,mjd0,np,hzn,&lstr,&x,&x,azr,&x,&x,&rss); X if (rss != 0) goto chkrss; X if (fabs (diff - lastdiff) < 0.25/60.0) X break; /* converged to better than 15 secs */ X lastdiff = diff; X } X if (pass == MAXPASSES) X *status |= RS_NORISE; /* didn't converge - no rise today */ X else { X *ltr = 12.0 + diff; X if (p != MOON && X (*ltr <= 24.0*(1.0-SIDRATE) || *ltr >= 24.0*SIDRATE)) X *status |= RS_2RISES; X } X X /* find a better approximation to the setting circumstances based on X * more passes, each using a "fixed" object at the location at X * previous approximation of the set time. X */ X lastdiff = 1000.0; X for (pass = 1; pass < MAXPASSES; pass++) { X diff = (lsts - lst)*SIDRATE; /* next guess at set time wrt noon */ X if (diff > 12.0) X diff -= 24.0*SIDRATE; /* not tomorrow, today */ X else if (diff < -12.0) X diff += 24.0*SIDRATE; /* not yesterday, today */ X mjd0 = lnoon + diff/24.0; /* next guess at mjd of set */ X stationary_riset (p,mjd0,np,hzn,&x,&lsts,&x,&x,azs,&x,&rss); X if (rss != 0) goto chkrss; X if (fabs (diff - lastdiff) < 0.25/60.0) X break; /* converged to better than 15 secs */ X lastdiff = diff; X } X if (pass == MAXPASSES) X *status |= RS_NOSET; /* didn't converge - no set today */ X else { X *lts = 12.0 + diff; X if (p != MOON && X (*lts <= 24.0*(1.0-SIDRATE) || *lts >= 24.0*SIDRATE)) X *status |= RS_2SETS; X } X X transit: X /* find a better approximation to the transit circumstances based on X * more passes, each using a "fixed" object at the location at X * previous approximation of the transit time. X */ X lastdiff = 1000.0; X for (pass = 1; pass < MAXPASSES; pass++) { X diff = (lstt - lst)*SIDRATE; /*next guess at transit time wrt noon*/ X if (diff > 12.0) X diff -= 24.0*SIDRATE; /* not tomorrow, today */ X else if (diff < -12.0) X diff += 24.0*SIDRATE; /* not yesterday, today */ X mjd0 = lnoon + diff/24.0; /* next guess at mjd of set */ X stationary_riset (p,mjd0,np,hzn,&x,&x,&lstt,&x,&x,altt,&rss); X if (fabs (diff - lastdiff) < 0.25/60.0) X break; /* converged to better than 15 secs */ X lastdiff = diff; X } X if (pass == MAXPASSES) X *status |= RS_NOTRANS; /* didn't converge - no transit today */ X else { X *ltt = 12.0 + diff; X if (p != MOON && X (*ltt <= 24.0*(1.0-SIDRATE) || *ltt >= 24.0*SIDRATE)) X *status |= RS_2TRANS; X } X} X Xstatic Xstationary_riset (p, mjd0, np, hzn, lstr, lsts, lstt, azr, azs, altt, status) Xint p; Xdouble mjd0; XNow *np; Xint hzn; Xdouble *lstr, *lsts, *lstt; Xdouble *azr, *azs, *altt; Xint *status; X{ X extern void bye(); X double dis; X Now n; X Sky s; X X switch (hzn) { X case STDHZN: X /* nominal atmospheric refraction. X * then add nominal moon or sun semi-diameter, as appropriate. X */ X dis = STDREF; X break; X case TWILIGHT: X if (p != SUN) { X f_msg ("Non-sun twilight bug!"); X bye(); X } X dis = TWIREF; X break; X default: X /* horizon displacement is refraction plus object's semi-diameter */ X unrefract (pressure, temp, 0.0, &dis); X dis = -dis; X n = *np; X n.n_mjd = mjd0; X (void) body_cir (p, 0.0, &n, &s); X dis += degrad(s.s_size/3600./2.0); X } X X switch (p) { X case SUN: X if (hzn == STDHZN) X dis += degrad (32./60./2.); X fixedsunriset (mjd0,np,dis,lstr,lsts,lstt,azr,azs,altt,status); X break; X case MOON: X if (hzn == STDHZN) X dis += degrad (32./60./2.); X fixedmoonriset (mjd0,np,dis,lstr,lsts,lstt,azr,azs,altt,status); X break; X default: X if (hzn == STDHZN) { X /* assume planets have negligible diameters. X * also, need to set s if hzn was STDHZN. X */ X n = *np; X n.n_mjd = mjd0; X (void) body_cir (p, 0.0, &n, &s); X } X riset (s.s_ra, s.s_dec, lat, dis, lstr, lsts, azr, azs, status); X transit (s.s_ra, s.s_dec, np, lstt, altt); X } X} X X/* find the local rise/set sidereal times and azimuths of an object fixed X * at the ra/dec of the sun on the given mjd time as seen from lat. X * times are for the upper limb. dis should account for refraction and X * sun's semi-diameter; we add corrections for nutation and aberration. X */ Xstatic Xfixedsunriset (mjd0, np, dis, lstr, lsts, lstt, azr, azs, altt, status) Xdouble mjd0; XNow *np; Xdouble dis; Xdouble *lstr, *lsts, *lstt; Xdouble *azr, *azs, *altt; Xint *status; X{ X double lsn, rsn; X double deps, dpsi; X double r, d; X X /* find ecliptic position of sun at mjd */ X sunpos (mjd0, &lsn, &rsn); X X /* allow for nutation and 20.4" light travel time */ X nutation (mjd0, &deps, &dpsi); X lsn += dpsi; X lsn -= degrad(20.4/3600.0); X X /* convert ecliptic to equatorial coords */ X ecl_eq (mjd0, 0.0, lsn, &r, &d); X X /* find circumstances for given horizon displacement */ X riset (r, d, lat, dis, lstr, lsts, azr, azs, status); X transit (r, d, np, lstt, altt); X} X X/* find the local sidereal rise/set times and azimuths of an object fixed X * at the ra/dec of the moon on the given mjd time as seen from lat. X * times are for the upper limb. dis should account for refraction and moon's X * semi-diameter; we add corrections for parallax, and nutation. X * accuracy is to nearest minute. X */ Xstatic Xfixedmoonriset (mjd0, np, dis, lstr, lsts, lstt, azr, azs, altt, status) Xdouble mjd0; XNow *np; Xdouble dis; Xdouble *lstr, *lsts, *lstt; Xdouble *azr, *azs, *altt; Xint *status; X{ X double lam, bet, hp; X double deps, dpsi; X double r, d; X double ha; X X /* find geocentric ecliptic location and equatorial horizontal parallax X * of moon at mjd. X */ X moon (mjd0, &lam, &bet, &hp); X X /* allow for nutation */ X nutation (mjd0, &deps, &dpsi); X lam += dpsi; X X /* convert ecliptic to equatorial coords */ X ecl_eq (mjd0, bet, lam, &r, &d); X X /* find local sidereal times of rise/set times/azimuths for given X * equatorial coords, allowing for X * .27249*sin(hp) parallax (hp is radius of earth from moon; X * .27249 is radius of moon from earth where X * the ratio is the dia_moon/dia_earth). X * hp nominal angular earth radius. subtract because X * tangential line-of-sight makes moon appear lower X * as move out from center of earth. X */ X dis += .27249*sin(hp) - hp; X riset (r, d, lat, dis, lstr, lsts, azr, azs, status); X X /* account for parallax on the meridian (0 hour-angle). X * TODO: is this really right? other stuff too? better way?? help! X */ X ta_par (0.0, d, lat, height, hp, &ha, &d); X transit (r+ha, d, np, lstt, altt); X} X X/* find when and how hi object at (r,d) is when it transits. */ Xstatic Xtransit (r, d, np, lstt, altt) Xdouble r, d; /* ra and dec, rads */ XNow *np; /* for refraction info */ Xdouble *lstt; /* local sidereal time of transit */ Xdouble *altt; /* local, refracted, altitude at time of transit */ X{ X *lstt = radhr(r); X *altt = PI/2 - lat + d; X if (*altt > PI/2) X *altt = PI - *altt; X refract (pressure, temp, *altt, altt); X} EOFxEOF len=`wc -c < riset_c.c` if expr $len != 10652 > /dev/null then echo Length of riset_c.c is $len but it should be 10652. fi echo x sel_fld.c sed -e 's/^X//' << 'EOFxEOF' > sel_fld.c X#include <stdio.h> X#include "screen.h" X X/* table of the fields, with flags indicating which menu(s) they are on and X * whether pickable for changing or plotting. X * N.B. type must be long enough to hold 16 bits. X */ Xstatic int fields[] = { X rcfpack (R_ALTM, C_ALTM, F_MMNU|F_CHG), X rcfpack (R_DAWN, C_DAWN, F_MMNU|F_CHG), X rcfpack (R_DAWN, C_DAWNV, F_MMNU|F_PLT), X rcfpack (R_DUSK, C_DUSK, F_MMNU|F_CHG), X rcfpack (R_DUSK, C_DUSKV, F_MMNU|F_PLT), X rcfpack (R_EPOCH, C_EPOCHV, F_MMNU|F_CHG), X rcfpack (R_HEIGHT, C_HEIGHTV, F_MMNU|F_CHG|F_PLT), X rcfpack (R_JD, C_JDV, F_MMNU|F_CHG|F_PLT), X rcfpack (R_JUPITER, C_ALT, F_MNU1|F_PLT), X rcfpack (R_JUPITER, C_AZ, F_MNU1|F_PLT), X rcfpack (R_JUPITER, C_DEC, F_MNU1|F_PLT), X rcfpack (R_JUPITER, C_EDIST, F_MNU1|F_PLT), X rcfpack (R_JUPITER, C_ELONG, F_MNU1|F_PLT), X rcfpack (R_JUPITER, C_HLAT, F_MNU1|F_PLT), X rcfpack (R_JUPITER, C_HLONG, F_MNU1|F_PLT), X rcfpack (R_JUPITER, C_MAG, F_MNU1|F_PLT), X rcfpack (R_JUPITER, C_MARS, F_MNU3|F_PLT), X rcfpack (R_JUPITER, C_MERCURY, F_MNU3|F_PLT), X rcfpack (R_JUPITER, C_MOON, F_MNU3|F_PLT), X rcfpack (R_JUPITER, C_NEPTUNE, F_MNU3|F_PLT), X rcfpack (R_JUPITER, C_OBJ, F_MMNU|F_CHG), X rcfpack (R_JUPITER, C_OBJX, F_MNU3|F_PLT), X rcfpack (R_JUPITER, C_PHASE, F_MNU1|F_PLT), X rcfpack (R_JUPITER, C_PLUTO, F_MNU3|F_PLT), X rcfpack (R_JUPITER, C_RA, F_MNU1|F_PLT), X rcfpack (R_JUPITER, C_RISEAZ, F_MNU2|F_PLT), X rcfpack (R_JUPITER, C_RISETM, F_MNU2|F_PLT), X rcfpack (R_JUPITER, C_SATURN, F_MNU3|F_PLT), X rcfpack (R_JUPITER, C_SDIST, F_MNU1|F_PLT), X rcfpack (R_JUPITER, C_SETAZ, F_MNU2|F_PLT), X rcfpack (R_JUPITER, C_SETTM, F_MNU2|F_PLT), X rcfpack (R_JUPITER, C_SIZE, F_MNU1|F_PLT), X rcfpack (R_JUPITER, C_SUN, F_MNU3|F_PLT), X rcfpack (R_JUPITER, C_TRANSALT, F_MNU2|F_PLT), X rcfpack (R_JUPITER, C_TRANSTM, F_MNU2|F_PLT), X rcfpack (R_JUPITER, C_TUP, F_MNU2|F_PLT), X rcfpack (R_JUPITER, C_URANUS, F_MNU3|F_PLT), X rcfpack (R_JUPITER, C_VENUS, F_MNU3|F_PLT), X rcfpack (R_LAT, C_LATV, F_MMNU|F_CHG|F_PLT), X rcfpack (R_LD, C_LD, F_MMNU|F_PLT|F_CHG), X rcfpack (R_LON, C_LON, F_MMNU|F_CHG), X rcfpack (R_LON, C_LONV, F_MMNU|F_PLT), X rcfpack (R_LONG, C_LONGV, F_MMNU|F_CHG|F_PLT), X rcfpack (R_LST, C_LSTV, F_MMNU|F_CHG|F_PLT), X rcfpack (R_LT, C_LT, F_MMNU|F_CHG|F_PLT), X rcfpack (R_MARS, C_ALT, F_MNU1|F_PLT), X rcfpack (R_MARS, C_AZ, F_MNU1|F_PLT), X rcfpack (R_MARS, C_DEC, F_MNU1|F_PLT), X rcfpack (R_MARS, C_EDIST, F_MNU1|F_PLT), X rcfpack (R_MARS, C_ELONG, F_MNU1|F_PLT), X rcfpack (R_MARS, C_HLAT, F_MNU1|F_PLT), X rcfpack (R_MARS, C_HLONG, F_MNU1|F_PLT), X rcfpack (R_MARS, C_JUPITER, F_MNU3|F_PLT), X rcfpack (R_MARS, C_MAG, F_MNU1|F_PLT), X rcfpack (R_MARS, C_MERCURY, F_MNU3|F_PLT), X rcfpack (R_MARS, C_MOON, F_MNU3|F_PLT), X rcfpack (R_MARS, C_NEPTUNE, F_MNU3|F_PLT), X rcfpack (R_MARS, C_OBJ, F_MMNU|F_CHG), X rcfpack (R_MARS, C_OBJX, F_MNU3|F_PLT), X rcfpack (R_MARS, C_PHASE, F_MNU1|F_PLT), X rcfpack (R_MARS, C_PLUTO, F_MNU3|F_PLT), X rcfpack (R_MARS, C_RA, F_MNU1|F_PLT), X rcfpack (R_MARS, C_RISEAZ, F_MNU2|F_PLT), X rcfpack (R_MARS, C_RISETM, F_MNU2|F_PLT), X rcfpack (R_MARS, C_SATURN, F_MNU3|F_PLT), X rcfpack (R_MARS, C_SDIST, F_MNU1|F_PLT), X rcfpack (R_MARS, C_SETAZ, F_MNU2|F_PLT), X rcfpack (R_MARS, C_SETTM, F_MNU2|F_PLT), X rcfpack (R_MARS, C_SIZE, F_MNU1|F_PLT), X rcfpack (R_MARS, C_SUN, F_MNU3|F_PLT), X rcfpack (R_MARS, C_TRANSALT, F_MNU2|F_PLT), X rcfpack (R_MARS, C_TRANSTM, F_MNU2|F_PLT), X rcfpack (R_MARS, C_TUP, F_MNU2|F_PLT), X rcfpack (R_MARS, C_URANUS, F_MNU3|F_PLT), X rcfpack (R_MARS, C_VENUS, F_MNU3|F_PLT), X rcfpack (R_MERCURY, C_ALT, F_MNU1|F_PLT), X rcfpack (R_MERCURY, C_AZ, F_MNU1|F_PLT), X rcfpack (R_MERCURY, C_DEC, F_MNU1|F_PLT), X rcfpack (R_MERCURY, C_EDIST, F_MNU1|F_PLT), X rcfpack (R_MERCURY, C_ELONG, F_MNU1|F_PLT), X rcfpack (R_MERCURY, C_HLAT, F_MNU1|F_PLT), X rcfpack (R_MERCURY, C_HLONG, F_MNU1|F_PLT), X rcfpack (R_MERCURY, C_JUPITER, F_MNU3|F_PLT), X rcfpack (R_MERCURY, C_MAG, F_MNU1|F_PLT), X rcfpack (R_MERCURY, C_MARS, F_MNU3|F_PLT), X rcfpack (R_MERCURY, C_MOON, F_MNU3|F_PLT), X rcfpack (R_MERCURY, C_NEPTUNE, F_MNU3|F_PLT), X rcfpack (R_MERCURY, C_OBJ, F_MMNU|F_CHG), X rcfpack (R_MERCURY, C_OBJX, F_MNU3|F_PLT), X rcfpack (R_MERCURY, C_PHASE, F_MNU1|F_PLT), X rcfpack (R_MERCURY, C_PLUTO, F_MNU3|F_PLT), X rcfpack (R_MERCURY, C_RA, F_MNU1|F_PLT), X rcfpack (R_MERCURY, C_RISEAZ, F_MNU2|F_PLT), X rcfpack (R_MERCURY, C_RISETM, F_MNU2|F_PLT), X rcfpack (R_MERCURY, C_SATURN, F_MNU3|F_PLT), X rcfpack (R_MERCURY, C_SDIST, F_MNU1|F_PLT), X rcfpack (R_MERCURY, C_SETAZ, F_MNU2|F_PLT), X rcfpack (R_MERCURY, C_SETTM, F_MNU2|F_PLT), X rcfpack (R_MERCURY, C_SIZE, F_MNU1|F_PLT), X rcfpack (R_MERCURY, C_SUN, F_MNU3|F_PLT), X rcfpack (R_MERCURY, C_TRANSALT, F_MNU2|F_PLT), X rcfpack (R_MERCURY, C_TRANSTM, F_MNU2|F_PLT), X rcfpack (R_MERCURY, C_TUP, F_MNU2|F_PLT), X rcfpack (R_MERCURY, C_URANUS, F_MNU3|F_PLT), X rcfpack (R_MERCURY, C_VENUS, F_MNU3|F_PLT), X rcfpack (R_MOON, C_ALT, F_MNU1|F_PLT), X rcfpack (R_MOON, C_AZ, F_MNU1|F_PLT), X rcfpack (R_MOON, C_DEC, F_MNU1|F_PLT), X rcfpack (R_MOON, C_EDIST, F_MNU1|F_PLT), X rcfpack (R_MOON, C_ELONG, F_MNU1|F_PLT), X rcfpack (R_MOON, C_JUPITER, F_MNU3|F_PLT), X rcfpack (R_MOON, C_MAG, F_MNU1|F_PLT), X rcfpack (R_MOON, C_MARS, F_MNU3|F_PLT), X rcfpack (R_MOON, C_MERCURY, F_MNU3|F_PLT), X rcfpack (R_MOON, C_NEPTUNE, F_MNU3|F_PLT), X rcfpack (R_MOON, C_OBJ, F_MMNU|F_CHG), X rcfpack (R_MOON, C_OBJX, F_MNU3|F_PLT), X rcfpack (R_MOON, C_PHASE, F_MNU1|F_PLT), X rcfpack (R_MOON, C_PLUTO, F_MNU3|F_PLT), X rcfpack (R_MOON, C_RA, F_MNU1|F_PLT), X rcfpack (R_MOON, C_RISEAZ, F_MNU2|F_PLT), X rcfpack (R_MOON, C_RISETM, F_MNU2|F_PLT), X rcfpack (R_MOON, C_SATURN, F_MNU3|F_PLT), X rcfpack (R_MOON, C_SDIST, F_MNU1|F_PLT), X rcfpack (R_MOON, C_SETAZ, F_MNU2|F_PLT), X rcfpack (R_MOON, C_SETTM, F_MNU2|F_PLT), X rcfpack (R_MOON, C_SIZE, F_MNU1|F_PLT), X rcfpack (R_MOON, C_SUN, F_MNU3|F_PLT), X rcfpack (R_MOON, C_TRANSALT, F_MNU2|F_PLT), X rcfpack (R_MOON, C_TRANSTM, F_MNU2|F_PLT), X rcfpack (R_MOON, C_TUP, F_MNU2|F_PLT), X rcfpack (R_MOON, C_URANUS, F_MNU3|F_PLT), X rcfpack (R_MOON, C_VENUS, F_MNU3|F_PLT), X rcfpack (R_NEPTUNE, C_ALT, F_MNU1|F_PLT), X rcfpack (R_NEPTUNE, C_AZ, F_MNU1|F_PLT), X rcfpack (R_NEPTUNE, C_DEC, F_MNU1|F_PLT), X rcfpack (R_NEPTUNE, C_EDIST, F_MNU1|F_PLT), X rcfpack (R_NEPTUNE, C_ELONG, F_MNU1|F_PLT), X rcfpack (R_NEPTUNE, C_HLAT, F_MNU1|F_PLT), X rcfpack (R_NEPTUNE, C_HLONG, F_MNU1|F_PLT), X rcfpack (R_NEPTUNE, C_JUPITER, F_MNU3|F_PLT), X rcfpack (R_NEPTUNE, C_MAG, F_MNU1|F_PLT), X rcfpack (R_NEPTUNE, C_MARS, F_MNU3|F_PLT), X rcfpack (R_NEPTUNE, C_MERCURY, F_MNU3|F_PLT), X rcfpack (R_NEPTUNE, C_MOON, F_MNU3|F_PLT), X rcfpack (R_NEPTUNE, C_OBJ, F_MMNU|F_CHG), X rcfpack (R_NEPTUNE, C_OBJX, F_MNU3|F_PLT), X rcfpack (R_NEPTUNE, C_PHASE, F_MNU1|F_PLT), X rcfpack (R_NEPTUNE, C_PLUTO, F_MNU3|F_PLT), X rcfpack (R_NEPTUNE, C_RA, F_MNU1|F_PLT), X rcfpack (R_NEPTUNE, C_RISEAZ, F_MNU2|F_PLT), X rcfpack (R_NEPTUNE, C_RISETM, F_MNU2|F_PLT), X rcfpack (R_NEPTUNE, C_SATURN, F_MNU3|F_PLT), X rcfpack (R_NEPTUNE, C_SDIST, F_MNU1|F_PLT), X rcfpack (R_NEPTUNE, C_SETAZ, F_MNU2|F_PLT), X rcfpack (R_NEPTUNE, C_SETTM, F_MNU2|F_PLT), X rcfpack (R_NEPTUNE, C_SIZE, F_MNU1|F_PLT), X rcfpack (R_NEPTUNE, C_SUN, F_MNU3|F_PLT), X rcfpack (R_NEPTUNE, C_TRANSALT, F_MNU2|F_PLT), X rcfpack (R_NEPTUNE, C_TRANSTM, F_MNU2|F_PLT), X rcfpack (R_NEPTUNE, C_TUP, F_MNU2|F_PLT), X rcfpack (R_NEPTUNE, C_URANUS, F_MNU3|F_PLT), X rcfpack (R_NEPTUNE, C_VENUS, F_MNU3|F_PLT), X rcfpack (R_NSTEP, C_NSTEPV, F_MMNU|F_CHG), X rcfpack (R_OBJX, C_ALT, F_MNU1|F_PLT), X rcfpack (R_OBJX, C_AZ, F_MNU1|F_PLT), X rcfpack (R_OBJX, C_DEC, F_MNU1|F_PLT), X rcfpack (R_OBJX, C_EDIST, F_MNU1|F_PLT), X rcfpack (R_OBJX, C_ELONG, F_MNU1|F_PLT), X rcfpack (R_OBJX, C_HLAT, F_MNU1|F_PLT), X rcfpack (R_OBJX, C_HLONG, F_MNU1|F_PLT), X rcfpack (R_OBJX, C_JUPITER, F_MNU3|F_PLT), X rcfpack (R_OBJX, C_MAG, F_MNU1|F_PLT), X rcfpack (R_OBJX, C_MARS, F_MNU3|F_PLT), X rcfpack (R_OBJX, C_MERCURY, F_MNU3|F_PLT), X rcfpack (R_OBJX, C_MOON, F_MNU3|F_PLT), X rcfpack (R_OBJX, C_NEPTUNE, F_MNU3|F_PLT), X rcfpack (R_OBJX, C_OBJ, F_MMNU|F_CHG), X rcfpack (R_OBJX, C_PHASE, F_MNU1|F_PLT), X rcfpack (R_OBJX, C_PLUTO, F_MNU3|F_PLT), X rcfpack (R_OBJX, C_RA, F_MNU1|F_PLT), X rcfpack (R_OBJX, C_RISEAZ, F_MNU2|F_PLT), X rcfpack (R_OBJX, C_RISETM, F_MNU2|F_PLT), X rcfpack (R_OBJX, C_SATURN, F_MNU3|F_PLT), X rcfpack (R_OBJX, C_SDIST, F_MNU1|F_PLT), X rcfpack (R_OBJX, C_SETAZ, F_MNU2|F_PLT), X rcfpack (R_OBJX, C_SETTM, F_MNU2|F_PLT), X rcfpack (R_OBJX, C_SUN, F_MNU3|F_PLT), X rcfpack (R_OBJX, C_TRANSALT, F_MNU2|F_PLT), X rcfpack (R_OBJX, C_TRANSTM, F_MNU2|F_PLT), X rcfpack (R_OBJX, C_TUP, F_MNU2|F_PLT), X rcfpack (R_OBJX, C_URANUS, F_MNU3|F_PLT), X rcfpack (R_OBJX, C_VENUS, F_MNU3|F_PLT), X rcfpack (R_PLOT, C_PLOT, F_MMNU|F_CHG), X rcfpack (R_PLUTO, C_ALT, F_MNU1|F_PLT), X rcfpack (R_PLUTO, C_AZ, F_MNU1|F_PLT), X rcfpack (R_PLUTO, C_DEC, F_MNU1|F_PLT), X rcfpack (R_PLUTO, C_EDIST, F_MNU1|F_PLT), X rcfpack (R_PLUTO, C_ELONG, F_MNU1|F_PLT), X rcfpack (R_PLUTO, C_HLAT, F_MNU1|F_PLT), X rcfpack (R_PLUTO, C_HLONG, F_MNU1|F_PLT), X rcfpack (R_PLUTO, C_JUPITER, F_MNU3|F_PLT), X rcfpack (R_PLUTO, C_MAG, F_MNU1|F_PLT), X rcfpack (R_PLUTO, C_MARS, F_MNU3|F_PLT), X rcfpack (R_PLUTO, C_MERCURY, F_MNU3|F_PLT), X rcfpack (R_PLUTO, C_MOON, F_MNU3|F_PLT), X rcfpack (R_PLUTO, C_NEPTUNE, F_MNU3|F_PLT), X rcfpack (R_PLUTO, C_OBJ, F_MMNU|F_CHG), X rcfpack (R_PLUTO, C_OBJX, F_MNU3|F_PLT), X rcfpack (R_PLUTO, C_PHASE, F_MNU1|F_PLT), X rcfpack (R_PLUTO, C_RA, F_MNU1|F_PLT), X rcfpack (R_PLUTO, C_RISEAZ, F_MNU2|F_PLT), X rcfpack (R_PLUTO, C_RISETM, F_MNU2|F_PLT), X rcfpack (R_PLUTO, C_SATURN, F_MNU3|F_PLT), X rcfpack (R_PLUTO, C_SDIST, F_MNU1|F_PLT), X rcfpack (R_PLUTO, C_SETAZ, F_MNU2|F_PLT), X rcfpack (R_PLUTO, C_SETTM, F_MNU2|F_PLT), X rcfpack (R_PLUTO, C_SIZE, F_MNU1|F_PLT), X rcfpack (R_PLUTO, C_SUN, F_MNU3|F_PLT), X rcfpack (R_PLUTO, C_TRANSALT, F_MNU2|F_PLT), X rcfpack (R_PLUTO, C_TRANSTM, F_MNU2|F_PLT), X rcfpack (R_PLUTO, C_TUP, F_MNU2|F_PLT), X rcfpack (R_PLUTO, C_URANUS, F_MNU3|F_PLT), X rcfpack (R_PLUTO, C_VENUS, F_MNU3|F_PLT), X rcfpack (R_PRES, C_PRESV, F_MMNU|F_CHG|F_PLT), X rcfpack (R_SATURN, C_ALT, F_MNU1|F_PLT), X rcfpack (R_SATURN, C_AZ, F_MNU1|F_PLT), X rcfpack (R_SATURN, C_DEC, F_MNU1|F_PLT), X rcfpack (R_SATURN, C_EDIST, F_MNU1|F_PLT), X rcfpack (R_SATURN, C_ELONG, F_MNU1|F_PLT), X rcfpack (R_SATURN, C_HLAT, F_MNU1|F_PLT), X rcfpack (R_SATURN, C_HLONG, F_MNU1|F_PLT), X rcfpack (R_SATURN, C_JUPITER, F_MNU3|F_PLT), X rcfpack (R_SATURN, C_MAG, F_MNU1|F_PLT), X rcfpack (R_SATURN, C_MARS, F_MNU3|F_PLT), X rcfpack (R_SATURN, C_MERCURY, F_MNU3|F_PLT), X rcfpack (R_SATURN, C_MOON, F_MNU3|F_PLT), X rcfpack (R_SATURN, C_NEPTUNE, F_MNU3|F_PLT), X rcfpack (R_SATURN, C_OBJ, F_MMNU|F_CHG), X rcfpack (R_SATURN, C_OBJX, F_MNU3|F_PLT), X rcfpack (R_SATURN, C_PHASE, F_MNU1|F_PLT), X rcfpack (R_SATURN, C_PLUTO, F_MNU3|F_PLT), X rcfpack (R_SATURN, C_RA, F_MNU1|F_PLT), X rcfpack (R_SATURN, C_RISEAZ, F_MNU2|F_PLT), X rcfpack (R_SATURN, C_RISETM, F_MNU2|F_PLT), X rcfpack (R_SATURN, C_SDIST, F_MNU1|F_PLT), X rcfpack (R_SATURN, C_SETAZ, F_MNU2|F_PLT), X rcfpack (R_SATURN, C_SETTM, F_MNU2|F_PLT), X rcfpack (R_SATURN, C_SIZE, F_MNU1|F_PLT), X rcfpack (R_SATURN, C_SUN, F_MNU3|F_PLT), X rcfpack (R_SATURN, C_TRANSALT, F_MNU2|F_PLT), X rcfpack (R_SATURN, C_TRANSTM, F_MNU2|F_PLT), X rcfpack (R_SATURN, C_TUP, F_MNU2|F_PLT), X rcfpack (R_SATURN, C_URANUS, F_MNU3|F_PLT), X rcfpack (R_SATURN, C_VENUS, F_MNU3|F_PLT), X rcfpack (R_SRCH, C_SRCH, F_MMNU|F_CHG|F_PLT), X rcfpack (R_STPSZ, C_STPSZV, F_MMNU|F_CHG), X rcfpack (R_SUN, C_ALT, F_MNU1|F_PLT), X rcfpack (R_SUN, C_AZ, F_MNU1|F_PLT), X rcfpack (R_SUN, C_DEC, F_MNU1|F_PLT), X rcfpack (R_SUN, C_EDIST, F_MNU1|F_PLT), X rcfpack (R_SUN, C_HLONG, F_MNU1|F_PLT), X rcfpack (R_SUN, C_JUPITER, F_MNU3|F_PLT), X rcfpack (R_SUN, C_MAG, F_MNU1|F_PLT), X rcfpack (R_SUN, C_MARS, F_MNU3|F_PLT), X rcfpack (R_SUN, C_MERCURY, F_MNU3|F_PLT), X rcfpack (R_SUN, C_MOON, F_MNU3|F_PLT), X rcfpack (R_SUN, C_NEPTUNE, F_MNU3|F_PLT), X rcfpack (R_SUN, C_OBJ, F_MMNU|F_CHG), X rcfpack (R_SUN, C_OBJX, F_MNU3|F_PLT), X rcfpack (R_SUN, C_PLUTO, F_MNU3|F_PLT), X rcfpack (R_SUN, C_RA, F_MNU1|F_PLT), X rcfpack (R_SUN, C_RISEAZ, F_MNU2|F_PLT), X rcfpack (R_SUN, C_RISETM, F_MNU2|F_PLT), X rcfpack (R_SUN, C_SATURN, F_MNU3|F_PLT), X rcfpack (R_SUN, C_SETAZ, F_MNU2|F_PLT), X rcfpack (R_SUN, C_SETTM, F_MNU2|F_PLT), X rcfpack (R_SUN, C_SIZE, F_MNU1|F_PLT), X rcfpack (R_SUN, C_TRANSALT, F_MNU2|F_PLT), X rcfpack (R_SUN, C_TRANSTM, F_MNU2|F_PLT), X rcfpack (R_SUN, C_TUP, F_MNU2|F_PLT), X rcfpack (R_SUN, C_URANUS, F_MNU3|F_PLT), X rcfpack (R_SUN, C_VENUS, F_MNU3|F_PLT), X rcfpack (R_TEMP, C_TEMPV, F_MMNU|F_CHG|F_PLT), X rcfpack (R_TZN, C_TZN, F_MMNU|F_CHG), X rcfpack (R_TZONE, C_TZONEV, F_MMNU|F_CHG), X rcfpack (R_UD, C_UD, F_MMNU|F_PLT|F_CHG), X rcfpack (R_URANUS, C_ALT, F_MNU1|F_PLT), X rcfpack (R_URANUS, C_AZ, F_MNU1|F_PLT), X rcfpack (R_URANUS, C_DEC, F_MNU1|F_PLT), X rcfpack (R_URANUS, C_EDIST, F_MNU1|F_PLT), X rcfpack (R_URANUS, C_ELONG, F_MNU1|F_PLT), X rcfpack (R_URANUS, C_HLAT, F_MNU1|F_PLT), X rcfpack (R_URANUS, C_HLONG, F_MNU1|F_PLT), X rcfpack (R_URANUS, C_JUPITER, F_MNU3|F_PLT), X rcfpack (R_URANUS, C_MAG, F_MNU1|F_PLT), X rcfpack (R_URANUS, C_MARS, F_MNU3|F_PLT), X rcfpack (R_URANUS, C_MERCURY, F_MNU3|F_PLT), X rcfpack (R_URANUS, C_MOON, F_MNU3|F_PLT), X rcfpack (R_URANUS, C_NEPTUNE, F_MNU3|F_PLT), X rcfpack (R_URANUS, C_OBJ, F_MMNU|F_CHG), X rcfpack (R_URANUS, C_OBJX, F_MNU3|F_PLT), X rcfpack (R_URANUS, C_PHASE, F_MNU1|F_PLT), X rcfpack (R_URANUS, C_PLUTO, F_MNU3|F_PLT), X rcfpack (R_URANUS, C_RA, F_MNU1|F_PLT), X rcfpack (R_URANUS, C_RISEAZ, F_MNU2|F_PLT), X rcfpack (R_URANUS, C_RISETM, F_MNU2|F_PLT), X rcfpack (R_URANUS, C_SATURN, F_MNU3|F_PLT), X rcfpack (R_URANUS, C_SDIST, F_MNU1|F_PLT), X rcfpack (R_URANUS, C_SETAZ, F_MNU2|F_PLT), X rcfpack (R_URANUS, C_SETTM, F_MNU2|F_PLT), X rcfpack (R_URANUS, C_SIZE, F_MNU1|F_PLT), X rcfpack (R_URANUS, C_SUN, F_MNU3|F_PLT), X rcfpack (R_URANUS, C_TRANSALT, F_MNU2|F_PLT), X rcfpack (R_URANUS, C_TRANSTM, F_MNU2|F_PLT), X rcfpack (R_URANUS, C_TUP, F_MNU2|F_PLT), X rcfpack (R_URANUS, C_VENUS, F_MNU3|F_PLT), X rcfpack (R_UT, C_UTV, F_MMNU|F_PLT|F_CHG), X rcfpack (R_VENUS, C_ALT, F_MNU1|F_PLT), X rcfpack (R_VENUS, C_AZ, F_MNU1|F_PLT), X rcfpack (R_VENUS, C_DEC, F_MNU1|F_PLT), X rcfpack (R_VENUS, C_EDIST, F_MNU1|F_PLT), X rcfpack (R_VENUS, C_ELONG, F_MNU1|F_PLT), X rcfpack (R_VENUS, C_HLAT, F_MNU1|F_PLT), X rcfpack (R_VENUS, C_HLONG, F_MNU1|F_PLT), X rcfpack (R_VENUS, C_JUPITER, F_MNU3|F_PLT), X rcfpack (R_VENUS, C_MAG, F_MNU1|F_PLT), X rcfpack (R_VENUS, C_MARS, F_MNU3|F_PLT), X rcfpack (R_VENUS, C_MERCURY, F_MNU3|F_PLT), X rcfpack (R_VENUS, C_MOON, F_MNU3|F_PLT), X rcfpack (R_VENUS, C_NEPTUNE, F_MNU3|F_PLT), X rcfpack (R_VENUS, C_OBJ, F_MMNU|F_CHG), X rcfpack (R_VENUS, C_OBJX, F_MNU3|F_PLT), X rcfpack (R_VENUS, C_PHASE, F_MNU1|F_PLT), X rcfpack (R_VENUS, C_PLUTO, F_MNU3|F_PLT), X rcfpack (R_VENUS, C_RA, F_MNU1|F_PLT), X rcfpack (R_VENUS, C_RISEAZ, F_MNU2|F_PLT), X rcfpack (R_VENUS, C_RISETM, F_MNU2|F_PLT), X rcfpack (R_VENUS, C_SATURN, F_MNU3|F_PLT), X rcfpack (R_VENUS, C_SDIST, F_MNU1|F_PLT), X rcfpack (R_VENUS, C_SETAZ, F_MNU2|F_PLT), X rcfpack (R_VENUS, C_SETTM, F_MNU2|F_PLT), X rcfpack (R_VENUS, C_SIZE, F_MNU1|F_PLT), X rcfpack (R_VENUS, C_SUN, F_MNU3|F_PLT), X rcfpack (R_VENUS, C_TRANSALT, F_MNU2|F_PLT), X rcfpack (R_VENUS, C_TRANSTM, F_MNU2|F_PLT), X rcfpack (R_VENUS, C_TUP, F_MNU2|F_PLT), X rcfpack (R_VENUS, C_URANUS, F_MNU3|F_PLT), X rcfpack (R_WATCH, C_WATCH, F_MMNU|F_CHG), X}; X#define NFIELDS (sizeof(fields)/sizeof(fields[0])) X X/* let op select a field by moving around and hitting RETURN, or until see END. X * also allow moving directly to a planet row using its name. X * only allow fields with the given flag mask. X * return the rcfpack()'d field, or 0 if typed END. X * N.B. we might also exit() entirely by calling bye() if op types QUIT. X */ Xsel_fld (r, c, flag, prmpt, help) Xint r, c; /* inial row, col */ Xint flag; Xchar *prmpt, *help; X{ X extern void bye(); X char *lastp; X int ch; X X lastp = 0; X while (1) { X if (lastp != prmpt) { X lastp = prmpt; X f_prompt (lastp); X } X c_pos (r, c); X switch (ch = read_char()) { X case REDRAW: X redraw_screen(2); /* redraw all from scratch */ X lastp = 0; X break; X case VERSION: X version(); X lastp = 0; X break; X case HELP: X f_msg (help); X lastp = 0; X break; X case QUIT: X f_prompt ("Exit ephem? (y) "); X if (read_char() == 'y') X bye(); /* never returns */ X lastp = 0; X break; X case END: X return (0); X case '\r': X return (rcfpack (r, c, 0)); X default: X move_cur (ch, flag, &r, &c); X break; X } X } X} X X/* move cursor to next field in given direction: hjkl, or directly to a X * field, and set *rp and *cp. X * limit eligible fields to those with given flag mask. X */ Xstatic Xmove_cur (dirchar, flag, rp, cp) Xchar dirchar; Xint flag; Xint *rp, *cp; X{ X int curr = *rp, curc = *cp; X int f, newf, *fp; X int d, newd; X X wrapped: X newf = 0; X newd = 1000; X X switch (dirchar) { X case 'h': /* left */ X /* go to next field to the left, or wrap. */ X for (fp = fields+NFIELDS; --fp >= fields; ) { X f = *fp; X if (tstpackf(f,flag) && unpackr(f) == curr) { X d = curc - unpackc(f); X if (d > 0 && d < newd) { X newf = f; X newd = d; X } X } X } X if (!newf) { X curc = NC; X goto wrapped; X } X break; X X case 'j': /* down */ X /* go to closest field on next row down with anything on it, X * or wrap. X */ X for (fp = fields+NFIELDS; --fp >= fields; ) { X f = *fp; X if (tstpackf(f,flag)) { X d = unpackr(f) - curr; X if (d > 0 && d < newd) { X newf = f; X newd = d; X } X } X } X if (newf) { X /* now find the field closest to current col on that row */ X newf = nearestfld (unpackr(newf), curc, flag); X } else { X curr = 0; X goto wrapped; X } X break; X X case 'k': /* up */ X /* go to closest field on next row up with anything on it, X * or wrap. X */ X for (fp = fields+NFIELDS; --fp >= fields; ) { X f = *fp; X if (tstpackf(f,flag)) { X d = curr - unpackr(f); X if (d > 0 && d < newd) { X newf = f; X newd = d; X } X } X } X if (newf) { X /* now find the field closest to current col on that row */ X newf = nearestfld (unpackr(newf), curc, flag); X } else { X curr = NR+1; X goto wrapped; X } X break; X X case 'l': /* right */ X /* go to next field to the right, or wrap. */ X for (fp = fields+NFIELDS; --fp >= fields; ) { X f = *fp; X if (tstpackf(f,flag) && unpackr(f) == curr) { X d = unpackc(f) - curc; X if (d > 0 && d < newd) { X newf = f; X newd = d; X } X } X } X if (!newf) { X curc = 0; X goto wrapped; X } X break; X X /* handy shorthands directly to a given spot. X * calling nearestfld() automatically allows for which menu X * is up now and what is pickable. X * N.B. using nearestfld() can be too aggressive. it will try X * other fields entirely if one you intend is not eligible. X */ X case 'S': newf = nearestfld (R_SUN, 1, flag); break; X case 'M': newf = nearestfld (R_MOON, 1, flag); break; X case 'e': newf = nearestfld (R_MERCURY, 1, flag); break; X case 'v': newf = nearestfld (R_VENUS, 1, flag); break; X case 'm': newf = nearestfld (R_MARS, 1, flag); break; X case cntrl('j'): newf = nearestfld (R_JUPITER, 1, flag); break; X case 's': newf = nearestfld (R_SATURN, 1, flag); break; X case 'u': newf = nearestfld (R_URANUS, 1, flag); break; X case 'n': newf = nearestfld (R_NEPTUNE, 1, flag); break; X case 'p': newf = nearestfld (R_PLUTO, 1, flag); break; X case 'x': newf = nearestfld (R_OBJX, 1, flag); break; X case 'd': newf = nearestfld (R_UD, C_UD, flag); break; X case 'o': newf = nearestfld (R_EPOCH, C_EPOCHV, flag); break; X case 'z': newf = nearestfld (R_STPSZ, C_STPSZV, flag); break; X } X X if (newf > 0) { X *rp = unpackr(newf); X *cp = unpackc(newf); X } X} X X/* return the nearest field with given flag mask, either way, on this row, X * else -1 if none. X */ Xstatic int Xnearestfld (r, c, flag) Xint r, c, flag; X{ X int nf, f, *fp; X int d, d0; X X nf = 0; X d0 = 1000; X X for (fp = fields+NFIELDS; --fp >= fields; ) { X f = *fp; X if (tstpackf(f,flag) && unpackr(f) == r) { X d = abs(c - unpackc(f)); X if (d < d0) { X nf = f; X d0 = d; X } X } X } X return (nf ? nf : -1); X} EOFxEOF len=`wc -c < sel_fld.c` if expr $len != 21267 > /dev/null then echo Length of sel_fld.c is $len but it should be 21267. fi echo x sex_dec.c sed -e 's/^X//' << 'EOFxEOF' > sex_dec.c X/* given hours (or degrees), hd, minutes, m, and seconds, s, X * return decimal hours (or degrees), *d. X * in the case of hours (angles) < 0, only the first non-zero element should X * be negative. X */ Xsex_dec (hd, m, s, d) Xint hd, m, s; Xdouble *d; X{ X int sign = 1; X X if (hd < 0) { X sign = -1; X hd = -hd; X } else if (m < 0) { X sign = -1; X m = -m; X } else if (s < 0) { X sign = -1; X s = -s; X } X X *d = (((double)s/60.0 + (double)m)/60.0 + (double)hd) * sign; X} X X/* given decimal hours (or degrees), d. X * return nearest hours (or degrees), *hd, minutes, *m, and seconds, *s, X * each always non-negative; *isneg is set to 1 if d is < 0, else to 0. X */ Xdec_sex (d, hd, m, s, isneg) Xdouble d; Xint *hd, *m, *s, *isneg; X{ X double min; X X if (d < 0) { X *isneg = 1; X d = -d; X } else X *isneg = 0; X X *hd = (int)d; X min = (d - *hd)*60.; X *m = (int)min; X *s = (int)((min - *m)*60. + 0.5); X X if (*s == 60) { X if ((*m += 1) == 60) { X *hd += 1; X *m = 0; X } X *s = 0; X } X /* no negative 0's */ X if (*hd == 0 && *m == 0 && *s == 0) X *isneg = 0; X} X X/* insure 0 <= *v < r. X */ Xrange (v, r) Xdouble *v, r; X{ X while (*v < 0) *v += r; X while (*v >= r) *v -= r; X} EOFxEOF len=`wc -c < sex_dec.c` if expr $len != 1194 > /dev/null then echo Length of sex_dec.c is $len but it should be 1194. fi