home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-03-14 | 53.3 KB | 2,128 lines |
- Newsgroups: comp.sources.misc
- From: e_downey@hwking.cca.cr.rockwell.com (Elwood C. Downey)
- Subject: v28i090: ephem - an interactive astronomical ephemeris, v4.28, Part07/09
- Message-ID: <1992Mar10.215921.16270@sparky.imd.sterling.com>
- X-Md4-Signature: 96e65b62725b81b7c3d9c10d7ddf4c4a
- Date: Tue, 10 Mar 1992 21:59:21 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: e_downey@hwking.cca.cr.rockwell.com (Elwood C. Downey)
- Posting-number: Volume 28, Issue 90
- Archive-name: ephem/part07
- Environment: UNIX, VMS, DOS, MAC
- Supersedes: ephem-4.21: Volume 14, Issue 76-81
-
- #! /bin/sh
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: altmenus.c flog.c formats.c listing.c plot.c srch.c
- # Wrapped by kent@sparky on Tue Mar 10 14:34:08 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 7 (of 9)."'
- if test -f 'altmenus.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'altmenus.c'\"
- else
- echo shar: Extracting \"'altmenus.c'\" \(11329 characters\)
- sed "s/^X//" >'altmenus.c' <<'END_OF_FILE'
- X/* routines for managing the alternative bottom half menus.
- X * planet-specific menus are in their own files.
- X */
- X
- X#include <stdio.h>
- X#include <math.h>
- X#include "astro.h"
- X#include "circum.h"
- X#include "screen.h"
- X
- Xstatic int altmenu = F_MNU1; /* which alternate menu is up; one of F_MNUi */
- Xstatic int alt2_stdhzn; /* whether to use STDHZN (aot ADPHZN) horizon algthm */
- Xstatic int alt3_geoc; /* whether to use geocentric (aot topocentric) vantage*/
- X
- X/* table of screen rows given a body #define from astro/h or screen.h */
- Xstatic short bodyrow[NOBJ] = {
- X R_MERCURY, R_VENUS, R_MARS, R_JUPITER, R_SATURN,
- X R_URANUS, R_NEPTUNE, R_PLUTO, R_SUN, R_MOON, R_OBJX, R_OBJY
- X};
- X/* table of screen cols for third menu format, given body #define ... */
- Xstatic short bodycol[NOBJ] = {
- X C_MERCURY, C_VENUS, C_MARS, C_JUPITER, C_SATURN,
- X C_URANUS, C_NEPTUNE, C_PLUTO, C_SUN, C_MOON, C_OBJX, C_OBJY
- X};
- X
- X/* initialize altmenu; used by main from cracking the ephem startup file.
- X */
- Xaltmenu_init (n)
- Xint n;
- X{
- X altmenu = n;
- X}
- X
- X/* let op decide which alternate menu should be up,
- X * including any menu-specific setup they might require.
- X * return 0 if things changed to require updating the alt menu; else -1.
- X */
- Xaltmenu_setup()
- X{
- X static char *flds[5] = {
- X "Data", "(Rise/Set", "", "(Separations"
- X };
- X int newmenu = altmenu, newhzn = alt2_stdhzn, newgeoc = alt3_geoc;
- X int new;
- X int fn = altmenu == F_MNU3 ? 3 : altmenu == F_MNU2 ? 1 : 0;
- X
- X ask:
- X flds[2]= newhzn ? "Standard hzn)" : "Adaptive hzn)";
- X flds[4]= newgeoc? "Geocentric)" : "Topocentric)";
- X
- X switch (popup (flds, fn, 5)) {
- X case 0: newmenu = F_MNU1; break;
- X case 1: newmenu = F_MNU2; break;
- X case 2: newhzn ^= 1; fn = 2; goto ask;
- X case 3: newmenu = F_MNU3; break;
- X case 4: newgeoc ^= 1; fn = 4; goto ask;
- X default: return (-1);
- X }
- X
- X new = 0;
- X if (newmenu != altmenu) {
- X altmenu = newmenu;
- X new++;
- X }
- X if (newhzn != alt2_stdhzn) {
- X alt2_stdhzn = newhzn;
- X if (newmenu == F_MNU2)
- X new++;
- X }
- X if (newgeoc != alt3_geoc) {
- X alt3_geoc = newgeoc;
- X if (newmenu == F_MNU3)
- X new++;
- X }
- X return (new ? 0 : -1);
- X}
- X
- X/* erase the info for the given planet */
- Xalt_nobody (p)
- Xint p;
- X{
- X f_eol (bodyrow[p], C_RA);
- X}
- X
- Xalt_body (b, force, np)
- Xint b; /* which body, ala astro.h and screen.h defines */
- Xint force; /* if !0 then draw for sure, else just if changed since last */
- XNow *np;
- X{
- X switch (altmenu) {
- X case F_MNU1: alt1_body (b, force, np); break;
- X case F_MNU2: alt2_body (b, force, np); break;
- X case F_MNU3: alt3_body (b, force, np); break;
- X }
- X}
- X
- X/* draw the labels for the current alternate menu format */
- Xalt_labels ()
- X{
- X switch (altmenu) {
- X case F_MNU1: alt1_labels (); break;
- X case F_MNU2: alt2_labels (); break;
- X case F_MNU3: alt3_labels (); break;
- X case F_MNUJ: altj_labels (); break;
- X }
- X}
- X
- Xalt_erase ()
- X{
- X int i;
- X
- X for (i = R_PLANTAB; i <= NR; i++)
- X f_eol (i, 1);
- X f_string (R_ALTM, C_ALTMV, " ");
- X}
- X
- Xalt_menumask()
- X{
- X return (altmenu);
- X}
- X
- X/* handy function to return the next planet in the order in which they are
- X * displayed in the lower half of the screen.
- X * input is a given planet, return is the next planet.
- X * if input is not legal, then first planet is returned; when input is the
- X * last planet, then -1 is returned.
- X * typical usage is something like:
- X * for (p = nxtbody(-1); p != -1; p = nxtbody(p))
- X */
- Xnxtbody(p)
- Xint p;
- X{
- X static short nxtpl[NOBJ] = {
- X VENUS, MARS, JUPITER, SATURN, URANUS,
- X NEPTUNE, PLUTO, OBJX, MOON, MERCURY, OBJY, -1
- X };
- X
- X if (p < MERCURY || p >= NOBJ)
- X return (SUN);
- X else
- X return (nxtpl[p]);
- X}
- X
- Xalt_plnames()
- X{
- X f_string (R_PLANTAB, C_OBJ, "OCX");
- X f_string (R_SUN, C_OBJ, "Su");
- X f_string (R_MOON, C_OBJ, "Mo");
- X f_string (R_MERCURY, C_OBJ, "Me");
- X f_string (R_VENUS, C_OBJ, "Ve");
- X f_string (R_MARS, C_OBJ, "Ma");
- X f_string (R_JUPITER, C_OBJ, "Ju");
- X f_string (R_SATURN, C_OBJ, "Sa");
- X f_string (R_URANUS, C_OBJ, "Ur");
- X f_string (R_NEPTUNE, C_OBJ, "Ne");
- X f_string (R_PLUTO, C_OBJ, "Pl");
- X f_string (R_OBJX, C_OBJ, "X");
- X f_string (R_OBJY, C_OBJ, "Y");
- X}
- X
- Xstatic
- Xalt1_labels()
- X{
- X f_string (R_ALTM, C_ALTMV, " Planet Data");
- X
- X alt_plnames();
- X f_string (R_PLANTAB, C_RA+2, "R.A.");
- X f_string (R_PLANTAB, C_DEC+2,"Dec");
- X f_string (R_PLANTAB, C_AZ+2, "Az");
- X f_string (R_PLANTAB, C_ALT+2,"Alt");
- X f_string (R_PLANTAB, C_HLONG,"H Long");
- X f_string (R_PLANTAB, C_HLAT, "H Lat");
- X f_string (R_PLANTAB, C_EDIST,"Ea Dst");
- X f_string (R_PLANTAB, C_SDIST,"Sn Dst");
- X f_string (R_PLANTAB, C_ELONG,"Elong");
- X f_string (R_PLANTAB, C_SIZE, "Size");
- X f_string (R_PLANTAB, C_MAG, "VMag");
- X f_string (R_PLANTAB, C_PHASE,"Phs");
- X}
- X
- Xstatic
- Xalt2_labels()
- X{
- X f_string (R_ALTM, C_ALTMV, "Rise/Set Info");
- X
- X alt_plnames();
- X f_string (R_PLANTAB, C_RISETM-2, "Rise Time");
- X f_string (R_PLANTAB, C_RISEAZ, "Rise Az");
- X f_string (R_PLANTAB, C_TRANSTM-2, "Trans Time");
- X f_string (R_PLANTAB, C_TRANSALT-1, "Trans Alt");
- X f_string (R_PLANTAB, C_SETTM-1, "Set Time");
- X f_string (R_PLANTAB, C_SETAZ, "Set Az");
- X f_string (R_PLANTAB, C_TUP-1, "Hours Up");
- X}
- X
- Xstatic
- Xalt3_labels()
- X{
- X f_string (R_ALTM, C_ALTMV, " Separations");
- X
- X alt_plnames();
- X f_string (R_PLANTAB, C_SUN, " Sun");
- X f_string (R_PLANTAB, C_MOON, "Moon");
- X f_string (R_PLANTAB, C_MERCURY, "Merc");
- X f_string (R_PLANTAB, C_VENUS, "Venus");
- X f_string (R_PLANTAB, C_MARS, "Mars");
- X f_string (R_PLANTAB, C_JUPITER, " Jup");
- X f_string (R_PLANTAB, C_SATURN, " Sat");
- X f_string (R_PLANTAB, C_URANUS, "Uranus");
- X f_string (R_PLANTAB, C_NEPTUNE, " Nep");
- X f_string (R_PLANTAB, C_PLUTO, "Pluto");
- X f_string (R_PLANTAB, C_OBJX, " X");
- X f_string (R_PLANTAB, C_OBJY, " Y");
- X}
- X
- X/* print body info in first menu format */
- Xstatic
- Xalt1_body (p, force, np)
- Xint p; /* which body, as in astro.h/screen.h defines */
- Xint force; /* whether to print for sure or only if things have changed */
- XNow *np;
- X{
- X Sky sky;
- X double as = plot_ison() || srch_ison() ? 0.0 : 60.0;
- X int row = bodyrow[p];
- X
- X if (body_cir (p, as, np, &sky) || force) {
- X f_ra (row, C_RA, sky.s_ra);
- X f_angle (row, C_DEC, sky.s_dec);
- X if (sky.s_hlong != NOHELIO) {
- X f_angle (row, C_HLONG, sky.s_hlong);
- X if (p != SUN)
- X f_angle (row, C_HLAT, sky.s_hlat);
- X }
- X
- X if (p == MOON) {
- X /* distance is on km, show in miles */
- X f_double (R_MOON, C_EDIST, "%6.0f", sky.s_edist/1.609344);
- X } else if (sky.s_edist > 0.0) {
- X /* show distance in au */
- X f_double (row, C_EDIST,(sky.s_edist>=10.0)?"%6.3f":"%6.4f",
- X sky.s_edist);
- X }
- X if (sky.s_sdist > 0.0)
- X f_double (row, C_SDIST, (sky.s_sdist>=9.99995)?"%6.3f":"%6.4f",
- X sky.s_sdist);
- X if (p != SUN)
- X f_double (row, C_ELONG, "%6.1f", sky.s_elong);
- X f_double (row, C_SIZE, sky.s_size >= 99.95 ?"%4.0f":"%4.1f",
- X sky.s_size);
- X f_double (row, C_MAG, sky.s_mag <= -9.95 ? "%4.0f" : "%4.1f",
- X sky.s_mag);
- X if (sky.s_sdist > 0.0) {
- X /* some terminals scroll when write a char in low-right corner.
- X * TODO: is there a nicer way to handle this maybe?
- X */
- X int col = row == NR ? C_PHASE - 1 : C_PHASE;
- X /* would just do this if Turbo-C 2.0 "%?.0f" worked:
- X * f_double (row, col, "%3.0f", sky.s_phase);
- X */
- X f_int (row, col, "%3d", sky.s_phase);
- X }
- X }
- X
- X f_angle (row, C_AZ, sky.s_az);
- X f_angle (row, C_ALT, sky.s_alt);
- X}
- X
- X/* print body info in the second menu format */
- Xstatic
- Xalt2_body (p, force, np)
- Xint p; /* which body, as in astro.h/screen.h defines */
- Xint force; /* whether to print for sure or only if things have changed */
- XNow *np;
- X{
- X double ltr, lts, ltt, azr, azs, altt;
- X int row = bodyrow[p];
- X int status;
- X double tmp;
- X int today_tup = 0;
- X
- X /* always recalc OBJX and Y since we don't know it's the same object */
- X if (!riset_cir (p, np, p==OBJX || p==OBJY, alt2_stdhzn?STDHZN:ADPHZN,
- X <r, <s, <t, &azr, &azs, &altt, &status) && !force)
- X return;
- X
- X alt_nobody (p);
- X
- X if (status & RS_ERROR) {
- X /* can not find where body is! */
- X f_string (row, C_RISETM, "?Error?");
- X return;
- X }
- X if (status & RS_CIRCUMPOLAR) {
- X /* body is up all day */
- X f_string (row, C_RISETM, "Circumpolar");
- X if (status & RS_NOTRANS)
- X f_string (row, C_TRANSTM, "No transit");
- X else {
- X f_mtime (row, C_TRANSTM, ltt);
- X if (status & RS_2TRANS)
- X f_char (row, C_TRANSTM+5, '+');
- X f_angle (row, C_TRANSALT, altt);
- X }
- X f_string (row, C_TUP, "24:00"); /*f_mtime() changes to 0:00 */
- X return;
- X }
- X if (status & RS_NEVERUP) {
- X /* body never up at all today */
- X f_string (row, C_RISETM, "Never up");
- X f_mtime (row, C_TUP, 0.0);
- X return;
- X }
- X
- X if (status & RS_NORISE) {
- X /* object does not rise as such today */
- X f_string (row, C_RISETM, "Never rises");
- X ltr = 0.0; /* for TUP */
- X today_tup = 1;
- X } else {
- X f_mtime (row, C_RISETM, ltr);
- X if (status & RS_2RISES) {
- X /* object rises more than once today */
- X f_char (row, C_RISETM+5, '+');
- X }
- X f_angle (row, C_RISEAZ, azr);
- X }
- X
- X if (status & RS_NOTRANS)
- X f_string (row, C_TRANSTM, "No transit");
- X else {
- X f_mtime (row, C_TRANSTM, ltt);
- X if (status & RS_2TRANS)
- X f_char (row, C_TRANSTM+5, '+');
- X f_angle (row, C_TRANSALT, altt);
- X }
- X
- X if (status & RS_NOSET) {
- X /* object does not set as such today */
- X f_string (row, C_SETTM, "Never sets");
- X lts = 24.0; /* for TUP */
- X today_tup = 1;
- X } else {
- X f_mtime (row, C_SETTM, lts);
- X if (status & RS_2SETS)
- X f_char (row, C_SETTM+5, '+');
- X f_angle (row, C_SETAZ, azs);
- X }
- X
- X tmp = lts - ltr;
- X if (tmp < 0)
- X tmp = 24.0 + tmp;
- X f_mtime (row, C_TUP, tmp);
- X if (today_tup)
- X f_char (row, C_TUP+5, '+');
- X}
- X
- X/* print body info in third menu format. this may be either the geocentric
- X * or topocentric angular separation between object p and each of the others.
- X * the latter, of course, includes effects of refraction and so can change
- X * quite rapidly near the time of each planets rise or set.
- X * for now, we don't save old values so we always redo everything and ignore
- X * the "force" argument. this isn't that bad since body_cir() has memory and
- X * will avoid most computations as we hit them again in the lower triangle.
- X * we are limited to only 5 columns per object. to make it fit, we display
- X * degrees:minutes if less than 100 degrees, otherwise just whole degrees.
- X */
- X/*ARGSUSED*/
- Xstatic
- Xalt3_body (p, force, np)
- Xint p; /* which body, as in astro.h/screen.h defines */
- Xint force; /* whether to print for sure or only if things have changed */
- XNow *np;
- X{
- X int row = bodyrow[p];
- X Sky skyp, skyq;
- X double spy, cpy, px, *qx, *qy;
- X int wantx = obj_ison(OBJX);
- X int wanty = obj_ison(OBJY);
- X double as = plot_ison() || srch_ison() ? 0.0 : 60.0;
- X int q;
- X
- X (void) body_cir (p, as, np, &skyp);
- X if (alt3_geoc) {
- X /* use ra for "x", dec for "y". */
- X spy = sin (skyp.s_dec);
- X cpy = cos (skyp.s_dec);
- X px = skyp.s_ra;
- X qx = &skyq.s_ra;
- X qy = &skyq.s_dec;
- X } else {
- X /* use azimuth for "x", altitude for "y". */
- X spy = sin (skyp.s_alt);
- X cpy = cos (skyp.s_alt);
- X px = skyp.s_az;
- X qx = &skyq.s_az;
- X qy = &skyq.s_alt;
- X }
- X for (q = nxtbody(-1); q != -1; q = nxtbody(q))
- X if (q != p && (q != OBJX || wantx) && (q != OBJY || wanty)) {
- X double sep, dsep;
- X (void) body_cir (q, as, np, &skyq);
- X sep = acos(spy*sin(*qy) + cpy*cos(*qy)*cos(px-*qx));
- X dsep = raddeg(sep);
- X if (dsep >= (100.0 - 1.0/60.0/2.0))
- X f_int (row, bodycol[q], "%5d:", dsep);
- X else
- X f_angle (row, bodycol[q], sep);
- X }
- X}
- END_OF_FILE
- if test 11329 -ne `wc -c <'altmenus.c'`; then
- echo shar: \"'altmenus.c'\" unpacked with wrong size!
- fi
- # end of 'altmenus.c'
- fi
- if test -f 'flog.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'flog.c'\"
- else
- echo shar: Extracting \"'flog.c'\" \(3241 characters\)
- sed "s/^X//" >'flog.c' <<'END_OF_FILE'
- X/* this is a simple little package to manage the saving and retrieving of
- X * field values, which we call field logging or "flogs". a flog consists of a
- X * field location, ala rcfpack(), its value as a double and its value as
- X * a string (ie, however it was printed). you can reset the list of flogs, add
- X * to and remove from the list of registered fields and log a field if it has
- X * been registered.
- X *
- X * this is used by the plotting and searching facilities of ephem to maintain
- X * the values of the fields that are being plotted or used in search
- X * expressions. it is used by the listing facility to generate listing files.
- X *
- X * a field can be in use for more than one
- X * thing at a time (eg, all the X plot values may the same time field, or
- X * searching and plotting might be on at one time using the same field) so
- X * we consider the field to be in use as long a usage count is > 0.
- X */
- X
- X#include "screen.h"
- X
- Xextern char *strcpy(), *strncpy();
- X
- X#define NFLOGS 32 /* max number of distinct simultaneous logged
- X * fields
- X */
- X
- Xtypedef struct {
- X int fl_usagecnt; /* number of "users" logging to this field */
- X int fl_fld; /* an rcfpack(r,c,0) */
- X double fl_val; /* stored value as a double */
- X char fl_str[16]; /* stored value as a formatted string.
- X * N.B.: never overwrite last char: keep as \0
- X */
- X} FLog;
- X
- Xstatic FLog flog[NFLOGS];
- X
- X/* add fld to the list. if already there, just increment usage count.
- X * return 0 if ok, else -1 if no more room.
- X */
- Xflog_add (fld)
- Xint fld;
- X{
- X FLog *flp, *unusedflp = 0;
- X
- X /* scan for fld already in list, or find an unused one along the way */
- X for (flp = &flog[NFLOGS]; --flp >= flog; ) {
- X if (flp->fl_usagecnt > 0) {
- X if (flp->fl_fld == fld) {
- X flp->fl_usagecnt++;
- X return (0);
- X }
- X } else
- X unusedflp = flp;
- X }
- X if (unusedflp) {
- X unusedflp->fl_fld = fld;
- X unusedflp->fl_usagecnt = 1;
- X return (0);
- X }
- X return (-1);
- X}
- X
- X/* decrement usage count for flog for fld. if goes to 0 take it out of list.
- X * ok if not in list i guess...
- X */
- Xflog_delete (fld)
- Xint fld;
- X{
- X FLog *flp;
- X
- X for (flp = &flog[NFLOGS]; --flp >= flog; )
- X if (flp->fl_fld == fld && flp->fl_usagecnt > 0) {
- X if (--flp->fl_usagecnt <= 0) {
- X flp->fl_usagecnt = 0;
- X }
- X break;
- X }
- X}
- X
- X/* if plotting, listing or searching is active then
- X * if rcfpack(r,c,0) is in the fld list, set its value to val.
- X * return 0 if ok, else -1 if not in list.
- X */
- Xflog_log (r, c, val, str)
- Xint r, c;
- Xdouble val;
- Xchar *str;
- X{
- X if (plot_ison() || listing_ison() || srch_ison()) {
- X FLog *flp;
- X int fld = rcfpack (r, c, 0);
- X for (flp = &flog[NFLOGS]; --flp >= flog; )
- X if (flp->fl_fld == fld && flp->fl_usagecnt > 0) {
- X flp->fl_val = val;
- X (void) strncpy (flp->fl_str, str, sizeof(flp->fl_str)-1);
- X return(0);
- X }
- X return (-1);
- X } else
- X return (0);
- X}
- X
- X/* search for fld in list. if find it, return its value and str, if str.
- X * return 0 if found it, else -1 if not in list.
- X */
- Xflog_get (fld, vp, str)
- Xint fld;
- Xdouble *vp;
- Xchar *str;
- X{
- X FLog *flp;
- X
- X for (flp = &flog[NFLOGS]; --flp >= flog; )
- X if (flp->fl_fld == fld && flp->fl_usagecnt > 0) {
- X *vp = flp->fl_val;
- X if (str)
- X (void) strcpy (str, flp->fl_str);
- X return (0);
- X }
- X return (-1);
- X}
- END_OF_FILE
- if test 3241 -ne `wc -c <'flog.c'`; then
- echo shar: \"'flog.c'\" unpacked with wrong size!
- fi
- # end of 'flog.c'
- fi
- if test -f 'formats.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'formats.c'\"
- else
- echo shar: Extracting \"'formats.c'\" \(7430 characters\)
- sed "s/^X//" >'formats.c' <<'END_OF_FILE'
- X/* basic formating routines.
- X * all the screen oriented printing should go through here.
- X */
- X
- X#include <stdio.h>
- X#include <math.h>
- X#include <ctype.h>
- X#ifdef VMS
- X#include <stdlib.h>
- X#endif
- X#include "astro.h"
- X#include "screen.h"
- X
- Xextern char *strcpy();
- X
- X/* suppress screen io if this is true, but always flog stuff.
- X */
- Xstatic int f_scrnoff;
- Xf_on ()
- X{
- X f_scrnoff = 0;
- X}
- Xf_off ()
- X{
- X f_scrnoff = 1;
- X}
- X
- X/* draw n blanks at the given cursor position. */
- Xf_blanks (r, c, n)
- Xint r, c, n;
- X{
- X if (f_scrnoff)
- X return;
- X c_pos (r, c);
- X while (--n >= 0)
- X putchar (' ');
- X}
- X
- X/* print the given value, v, in "sexadecimal" format at [r,c]
- X * ie, in the form A:m.P, where A is a digits wide, P is p digits.
- X * if p == 0, then no decimal point either.
- X */
- Xf_sexad (r, c, a, p, mod, v)
- Xint r, c;
- Xint a, p; /* left space, min precision */
- Xint mod; /* don't let whole portion get this big */
- Xdouble v;
- X{
- X char astr[32], str[32];
- X long dec;
- X double frac;
- X int visneg;
- X double vsav = v;
- X
- X if (v >= 0.0)
- X visneg = 0;
- X else {
- X if (v <= -0.5/60.0*pow(10.0,-1.0*p)) {
- X v = -v;
- X visneg = 1;
- X } else {
- X /* don't show as negative if less than the precision showing */
- X v = 0.0;
- X visneg = 0;
- X }
- X }
- X
- X dec = v;
- X frac = (v - dec)*60.0;
- X (void) sprintf (str, "59.%.*s5", p, "999999999");
- X if (frac >= atof (str)) {
- X dec += 1;
- X frac = 0.0;
- X }
- X dec %= mod;
- X if (dec == 0 && visneg)
- X (void) strcpy (str, "-0");
- X else
- X (void) sprintf (str, "%ld", visneg ? -dec : dec);
- X
- X /* would just do this if Turbo-C 2.0 %?.0f" worked:
- X * sprintf (astr, "%*s:%0*.*f", a, str, p == 0 ? 2 : p+3, p, frac);
- X */
- X if (p == 0)
- X (void) sprintf (astr, "%*s:%02d", a, str, (int)(frac+0.5));
- X else
- X (void) sprintf (astr, "%*s:%0*.*f", a, str, p+3, p, frac);
- X
- X (void) flog_log (r, c, vsav, astr);
- X
- X f_string (r, c, astr);
- X}
- X
- X/* print the given value, t, in sexagesimal format at [r,c]
- X * ie, in the form T:mm:ss, where T is nd digits wide.
- X * N.B. we assume nd >= 2.
- X */
- Xf_sexag (r, c, nd, t)
- Xint r, c, nd;
- Xdouble t;
- X{
- X char tstr[32];
- X int h, m, s;
- X int tisneg;
- X
- X dec_sex (t, &h, &m, &s, &tisneg);
- X if (h == 0 && tisneg)
- X (void) sprintf (tstr, "%*s-0:%02d:%02d", nd-2, "", m, s);
- X else
- X (void) sprintf (tstr, "%*d:%02d:%02d", nd, tisneg ? -h : h, m, s);
- X
- X (void) flog_log (r, c, t, tstr);
- X f_string (r, c, tstr);
- X}
- X
- X/* print angle ra, in radians, in ra hours as hh:mm.m at [r,c]
- X * N.B. we assume ra is >= 0.
- X */
- Xf_ra (r, c, ra)
- Xint r, c;
- Xdouble ra;
- X{
- X f_sexad (r, c, 2, 1, 24, radhr(ra));
- X}
- X
- X/* print time, t, as hh:mm:ss */
- Xf_time (r, c, t)
- Xint r, c;
- Xdouble t;
- X{
- X f_sexag (r, c, 2, t);
- X}
- X
- X/* print time, t, as +/-hh:mm:ss (don't show leading +) */
- Xf_signtime (r, c, t)
- Xint r, c;
- Xdouble t;
- X{
- X f_sexag (r, c, 3, t);
- X}
- X
- X/* print time, t, as hh:mm */
- Xf_mtime (r, c, t)
- Xint r, c;
- Xdouble t;
- X{
- X f_sexad (r, c, 2, 0, 24, t);
- X}
- X
- X/* print angle, a, in rads, as degress at [r,c] in form ddd:mm */
- Xf_angle(r, c, a)
- Xint r, c;
- Xdouble a;
- X{
- X f_sexad (r, c, 3, 0, 360, raddeg(a));
- X}
- X
- X/* print angle, a, in rads, as degress at [r,c] in form dddd:mm:ss */
- Xf_gangle(r, c, a)
- Xint r, c;
- Xdouble a;
- X{
- X f_sexag (r, c, 4, raddeg(a));
- X}
- X
- X/* print the given modified Julian date, jd, as the starting date at [r,c]
- X * in the form mm/dd/yyyy.
- X */
- Xf_date (r, c, jd)
- Xint r, c;
- Xdouble jd;
- X{
- X char dstr[32];
- X int m, y;
- X double d, tmp;
- X
- X mjd_cal (jd, &m, &d, &y);
- X (void) sprintf (dstr, "%2d/%02d/%-4d", m, (int)(d), y);
- X
- X /* shadow to the plot subsystem as years. */
- X mjd_year (jd, &tmp);
- X (void) flog_log (r, c, tmp, dstr);
- X f_string (r, c, dstr);
- X}
- X
- X/* print the given double as a rounded int, with the given format.
- X * this is used to plot full precision, but display far less.
- X * N.B. caller beware that we really do expect fmt to refer to an int, not
- X * a long for example. also beware of range that implies.
- X */
- Xf_int (row, col, fmt, f)
- Xint row, col;
- Xchar fmt[];
- Xdouble f;
- X{
- X char str[80];
- X int i;
- X
- X i = (f < 0) ? (int)(f-0.5) : (int)(f+0.5);
- X (void) sprintf (str, fmt, i);
- X
- X (void) flog_log (row, col, f, str);
- X f_string (row, col, str);
- X}
- X
- Xf_char (row, col, c)
- Xint row, col;
- Xchar c;
- X{
- X if (f_scrnoff)
- X return;
- X c_pos (row, col);
- X putchar (c);
- X}
- X
- Xf_string (r, c, s)
- Xint r, c;
- Xchar *s;
- X{
- X if (f_scrnoff)
- X return;
- X c_pos (r, c);
- X (void) fputs (s, stdout);
- X}
- X
- Xf_double (r, c, fmt, f)
- Xint r, c;
- Xchar *fmt;
- Xdouble f;
- X{
- X char str[80];
- X (void) sprintf (str, fmt, f);
- X (void) flog_log (r, c, f, str);
- X f_string (r, c, str);
- X}
- X
- X/* print prompt line */
- Xf_prompt (p)
- Xchar *p;
- X{
- X c_pos (R_PROMPT, C_PROMPT);
- X c_eol ();
- X c_pos (R_PROMPT, C_PROMPT);
- X (void) fputs (p, stdout);
- X}
- X
- X/* clear from [r,c] to end of line, if we are drawing now. */
- Xf_eol (r, c)
- Xint r, c;
- X{
- X if (!f_scrnoff) {
- X c_pos (r, c);
- X c_eol();
- X }
- X}
- X
- X/* print a message and wait for op to hit any key */
- Xf_msg (m)
- Xchar *m;
- X{
- X f_prompt (m);
- X (void) read_char();
- X}
- X
- X/* crack a line of the form X?X?X into its components,
- X * where X is an integer and ? can be any character except '0-9' or '-',
- X * such as ':' or '/'.
- X * only change those fields that are specified:
- X * eg: ::10 only changes *s
- X * 10 only changes *d
- X * 10:0 changes *d and *m
- X * if see '-' anywhere, first non-zero component will be made negative.
- X */
- Xf_sscansex (bp, d, m, s)
- Xchar *bp;
- Xint *d, *m, *s;
- X{
- X char c;
- X int *p = d;
- X int *nonzp = 0;
- X int sawneg = 0;
- X int innum = 0;
- X
- X while (c = *bp++)
- X if (isdigit(c)) {
- X if (!innum) {
- X *p = 0;
- X innum = 1;
- X }
- X *p = *p*10 + (c - '0');
- X if (*p && !nonzp)
- X nonzp = p;
- X } else if (c == '-') {
- X sawneg = 1;
- X } else if (c != ' ') {
- X /* advance to next component */
- X p = (p == d) ? m : s;
- X innum = 0;
- X }
- X
- X if (sawneg && nonzp)
- X *nonzp = -*nonzp;
- X}
- X
- X/* crack a floating date string, bp, of the form m/d/y, where d may be a
- X * floating point number, into its components.
- X * leave any component unspecified unchanged.
- X * actually, the slashes may be anything but digits or a decimal point.
- X * this is functionally the same as f_sscansex() exept we allow for
- X * the day portion to be real, and we don't handle negative numbers.
- X * maybe someday we could make a combined one and use it everywhere.
- X */
- Xf_sscandate (bp, m, d, y)
- Xchar *bp;
- Xint *m, *y;
- Xdouble *d;
- X{
- X char *bp0, c;
- X
- X bp0 = bp;
- X while ((c = *bp++) && isdigit(c))
- X continue;
- X if (bp > bp0+1)
- X *m = atoi (bp0);
- X if (c == '\0')
- X return;
- X bp0 = bp;
- X while ((c = *bp++) && (isdigit(c) || c == '.'))
- X continue;
- X if (bp > bp0+1)
- X *d = atof (bp0);
- X if (c == '\0')
- X return;
- X bp0 = bp;
- X while (c = *bp++)
- X continue;
- X if (bp > bp0+1)
- X *y = atoi (bp0);
- X}
- X
- X/* just like dec_sex() but makes the first non-zero element negative if
- X * x is negative (instead of returning a sign flag).
- X */
- Xf_dec_sexsign (x, h, m, s)
- Xdouble x;
- Xint *h, *m, *s;
- X{
- X int n;
- X dec_sex (x, h, m, s, &n);
- X if (n) {
- X if (*h)
- X *h = -*h;
- X else if (*m)
- X *m = -*m;
- X else
- X *s = -*s;
- X }
- X}
- X
- X/* return 1 if bp looks like a decimal year; else 0.
- X * any number greater than 12 or less than 0 is assumed to be a year, or any
- X * string with exactly one decimal point, an optional minus sign, and nothing
- X * else but digits.
- X */
- Xdecimal_year (bp)
- Xchar *bp;
- X{
- X char c;
- X int ndig = 0, ndp = 0, nneg = 0, nchar = 0;
- X double y = atof(bp);
- X
- X while (c = *bp++) {
- X nchar++;
- X if (isdigit(c))
- X ndig++;
- X else if (c == '.')
- X ndp++;
- X else if (c == '-')
- X nneg++;
- X }
- X
- X return (y > 12 || y < 0
- X || (ndp == 1 && nneg <= 1 && nchar == ndig+ndp+nneg));
- X}
- END_OF_FILE
- if test 7430 -ne `wc -c <'formats.c'`; then
- echo shar: \"'formats.c'\" unpacked with wrong size!
- fi
- # end of 'formats.c'
- fi
- if test -f 'listing.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'listing.c'\"
- else
- echo shar: Extracting \"'listing.c'\" \(7576 characters\)
- sed "s/^X//" >'listing.c' <<'END_OF_FILE'
- X/* code to support the listing capabilities.
- X * idea is to let the operator name a listing file and mark some fields for
- X * logging. then after each screen update, the logged fields are written to
- X * the listing file in the same manner as they appeared on the screen.
- X *
- X * format of the listing file is one line per screen update.
- X */
- X
- X#include <stdio.h>
- X#include <math.h>
- X#include "screen.h"
- X
- Xextern char *strcpy();
- X
- X#ifdef VMS
- X#include <perror.h>
- X#include <errno.h>
- X#else
- Xextern char *sys_errlist[];
- Xextern errno;
- X#endif
- X
- X#define errsys (sys_errlist[errno])
- X
- X
- X#define TRACE(x) {FILE *fp = fopen("trace","a"); fprintf x; fclose(fp);}
- X
- X#define MAXLSTFLDS 10 /* max number of fields 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 lst_filename[FNLEN] = "ephem.lst"; /* default plot file name */
- Xstatic FILE *lst_fp; /* the plot file; == 0 means don't plot */
- X
- X/* store rcfpack()s for each field to track, in l-to-r order */
- Xstatic int lstflds[MAXLSTFLDS];
- Xstatic int nlstflds; /* number of lstflds[] in actual use */
- X
- Xstatic int lstsrchfld; /* set when the Search field is to be listed */
- X
- X/* picked the Listing label:
- X * if on, just turn it off.
- X * if off, turn on, define fields or select name of file to list to and do it.
- X * TODO: more flexibility, more relevance.
- X */
- Xlisting_setup()
- X{
- X if (lst_fp)
- X lst_turn_off();
- X else {
- X static char *chcs[] = {
- X "Select fields", "Display a listing file", "Begin listing"
- X };
- X static int fn; /* start with 0, then remember for next time */
- X ask:
- X switch (popup(chcs, fn, nlstflds > 0 ? 3 : 2)) {
- X case 0: fn = 0; lst_select_fields(); goto ask;
- X case 1: fn = 1; lst_file(); goto ask;
- X case 2: fn = 2; lst_turn_on(); break;
- X default: break;
- X }
- X }
- X}
- X
- X/* write the active listing to the current listing file, if one is open. */
- Xlisting()
- X{
- X if (lst_fp) {
- X int n;
- X double flx;
- X char flstr[32];
- X if (!srch_ison() && lstsrchfld) {
- X /* if searching is not on but we are listing the search
- X * funtion we must evaluate and log it ourselves here and now.
- X * lst_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 lst_turn_off();
- X return;
- X } else {
- X (void) sprintf (flstr, "%g", e);
- X (void) flog_log (R_SRCH, C_SRCH, e, flstr);
- X }
- X }
- X
- X /* list in order of original selection */
- X for (n = 0; n < nlstflds; n++)
- X if (flog_get (lstflds[n], &flx, flstr) == 0)
- X (void) fprintf (lst_fp, "%s ", flstr);
- X (void) fprintf (lst_fp, "\n");
- X }
- X}
- X
- Xlisting_prstate (force)
- Xint force;
- X{
- X static last;
- X int this = lst_fp != 0;
- X
- X if (force || this != last) {
- X f_string (R_LISTING, C_LISTINGV, this ? " on" : "off");
- X last = this;
- X }
- X}
- X
- Xlisting_ison()
- X{
- X return (lst_fp != 0);
- X}
- X
- Xstatic
- Xlst_reset()
- X{
- X int *lp;
- X
- X for (lp = lstflds; lp < &lstflds[nlstflds]; lp++) {
- X (void) flog_delete (*lp);
- X *lp = 0;
- X }
- X nlstflds = 0;
- X lstsrchfld = 0;
- X}
- X
- X/* let operator select the fields he wants to have in his listing.
- X * register them with flog and keep rcfpack() in lstflds[] array.
- X * as a special case, set lstsrchfld if Search field is selected.
- X */
- Xstatic
- Xlst_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 list any more fields.";
- X int f = rcfpack(R_UT,C_UTV,0); /* TODO: start where main was? */
- X int sf = rcfpack (R_SRCH,C_SRCH,0);
- X char buf[64];
- X int i;
- X
- X lst_reset();
- X for (i = 0; i < MAXLSTFLDS; i++) {
- X (void) sprintf(buf,"select field for column %d or q to quit", i+1);
- X f = sel_fld (f, alt_menumask()|F_PLT, buf, hlp);
- X if (!f)
- X break;
- X if (flog_add (f) < 0) {
- X f_msg (sry);
- X break;
- X }
- X lstflds[i] = f;
- X if (f == sf)
- X lstsrchfld = 1;
- X }
- X if (i == MAXLSTFLDS)
- X f_msg (sry);
- X nlstflds = i;
- X}
- X
- Xstatic
- Xlst_turn_off ()
- X{
- X (void) fclose (lst_fp);
- X lst_fp = 0;
- X listing_prstate(0);
- X}
- X
- X/* turn on listing facility.
- X * establish a file to use (and thereby set lst_fp, the "listing-is-on" flag).
- X * also check that there is a srch function if it is being used.
- X */
- Xstatic
- Xlst_turn_on ()
- X{
- X int sf = rcfpack(R_SRCH, C_SRCH, 0);
- X char fn[FNLEN], fnq[NC];
- X char *optype;
- X int n;
- X
- X /* insure there is a valid srch function if we are to list it */
- X for (n = 0; n < nlstflds; n++)
- X if (lstflds[n] == sf && !prog_isgood()) {
- X f_msg ("Listing search function but it is not defined.");
- X return;
- X }
- X
- X /* prompt for file name, giving current as default */
- X (void) sprintf (fnq, "file to write <%s>: ", lst_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 (void) strcpy (lst_filename, fn);
- X
- X /* give option to append if file already exists */
- X optype = "w";
- X if (access (lst_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 /* listing is on if file opens ok */
- X lst_fp = fopen (lst_filename, optype);
- X if (!lst_fp) {
- X (void) sprintf (fnq, "can not open %s: %s", lst_filename, errsys);
- X f_msg (fnq);
- X } else {
- X /* add a title if desired */
- X static char tp[] = "Title (q to skip): ";
- X f_prompt (tp);
- X if (read_line (fnq, PW - sizeof(tp)) > 0)
- X (void) fprintf (lst_fp, "%s\n", fnq);
- X }
- X
- X listing_prstate (0);
- X}
- X
- X/* ask operator for a listing file to show. if it's ok, do it.
- X */
- Xstatic
- Xlst_file ()
- X{
- X char fn[FNLEN], fnq[64];
- X FILE *lfp;
- X int n;
- X
- X /* prompt for file name, giving current as default */
- X (void) sprintf (fnq, "file to read <%s>: ", lst_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 (void) strcpy (lst_filename, fn);
- X
- X /* show it if file opens ok */
- X lfp = fopen (lst_filename, "r");
- X if (lfp) {
- X display_listing_file (lfp);
- X (void) fclose (lfp);
- X } else {
- X char buf[NC];
- X (void) sprintf (buf, "can not open %s: %s", lst_filename, errsys);
- X f_prompt (buf);
- X (void)read_char();
- X }
- X}
- X
- X/* display the given listing file on the screen.
- X * allow for files longer than the screen.
- X * N.B. do whatever you like but redraw the screen when done.
- X */
- Xstatic
- Xdisplay_listing_file (lfp)
- XFILE *lfp;
- X{
- X static char eofp[] = "[End-of-file. Hit any key to resume...] ";
- X static char p[] = "[Hit any key to continue or q to quit...] ";
- X char buf[NC+2]; /* screen width plus for '\n' and '\0' */
- X int nc, nl;
- X
- X c_erase();
- X nl = 0;
- X while (1) {
- X (void) fgets (buf, sizeof(buf), lfp);
- X if (feof(lfp)) {
- X printf (eofp);
- X (void) read_char();
- X break;
- X }
- X /* make sure last char is \n, even if it's a long line */
- X nc = strlen (buf);
- X if (nc == NC+1) {
- X (void) ungetc (buf[NC], lfp);
- X buf[NC] = '\n';
- X }
- X printf ("%s\r", buf);
- X if (++nl == NR-1) {
- X /* read-ahead one char to check for eof */
- X int rach = getc (lfp);
- X if (feof(lfp)) {
- X (void) printf (eofp);
- X (void) read_char();
- X break;
- X } else
- X (void) ungetc (rach, lfp);
- X (void) printf (p);
- X if (read_char() == END)
- X break;
- X c_erase();
- X nl = 0;
- X }
- X }
- X
- X redraw_screen (2); /* full redraw */
- X}
- END_OF_FILE
- if test 7576 -ne `wc -c <'listing.c'`; then
- echo shar: \"'listing.c'\" unpacked with wrong size!
- fi
- # end of 'listing.c'
- fi
- if test -f 'plot.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'plot.c'\"
- else
- echo shar: Extracting \"'plot.c'\" \(11208 characters\)
- sed "s/^X//" >'plot.c' <<'END_OF_FILE'
- 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();
- X
- X#ifdef VMS
- X#include <perror.h>
- X#include <errno.h>
- X#else
- Xextern char *sys_errlist[];
- Xextern errno;
- X#endif
- X
- X#define errsys (sys_errlist[errno])
- X
- 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 static int fn; /* start with 0, then remember for next time */
- X ask:
- X chcs[2] = plt_in_polar ? "Polar coords" : "Cartesian coords";
- X switch (popup(chcs, fn, npltlines > 0 ? 4 : 3)) {
- X case 0: fn = 0; plt_select_fields(); goto ask;
- X case 1: fn = 1; plt_file(); goto ask;
- X case 2: fn = 2; plt_in_polar ^= 1; goto ask;
- X case 3: fn = 3; plt_turn_on(); break;
- X default: 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 (void) 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, (char *)0) == 0
- X && flog_get (plp->pl_rcpy, &y, (char *)0) == 0) {
- X (void) fprintf (plt_fp, "%c,%.12g,%.12g", plp->pl_label,
- X x, y);
- X if (flog_get (plp->pl_rcpz, &z, (char *)0) == 0)
- X (void) fprintf (plt_fp, ",%.12g", z);
- X (void) 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 f = rcfpack(R_UT,C_UTV,0); /* TODO: start where main was? */
- X int sf = rcfpack (R_SRCH, C_SRCH, 0);
- X char buf[64];
- X int i;
- X int tmpf;
- X
- X plt_reset();
- X for (i = 0; i < MAXPLTLINES; i++) {
- X (void) sprintf (buf, "select x field for line %d", i+1);
- X f = sel_fld (f, alt_menumask()|F_PLT, buf, hlp);
- X if (!f)
- X break;
- X if (flog_add (f) < 0) {
- X f_msg (sry);
- X break;
- X }
- X pltlines[i].pl_rcpx = f;
- X if (f == sf)
- X pltsrchfld = 1;
- X
- X (void) sprintf (buf, "select y field for line %d", i+1);
- X f = sel_fld (f, alt_menumask()|F_PLT, buf, hlp);
- X if (!f) {
- X (void) flog_delete (pltlines[i].pl_rcpx);
- X break;
- X }
- X if (flog_add (f) < 0) {
- X (void) flog_delete (pltlines[i].pl_rcpx);
- X f_msg (sry);
- X break;
- X }
- X pltlines[i].pl_rcpy = f;
- X if (f == sf)
- X pltsrchfld = 1;
- X
- X (void) sprintf (buf, "select z field for line %d (q for no z)",i+1);
- X tmpf = sel_fld (f, alt_menumask()|F_PLT, buf, hlp);
- X if (tmpf) {
- X if (flog_add (tmpf) < 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 = tmpf;
- X if (tmpf == sf)
- X pltsrchfld = 1;
- X f = tmpf;
- X }
- X
- X do {
- X (void) sprintf(buf,"enter a one-character label for line %d: ",
- X 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 (void) 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[NC];
- 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 (void) 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 (void) 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 (void) sprintf (buf, "can not open %s: %s", plt_filename, errsys);
- X f_prompt (buf);
- X (void)read_char();
- X } else {
- X /* add a title if desired */
- X static char tp[] = "Title (q to skip): ";
- X f_prompt (tp);
- X if (read_line (fnq, PW - sizeof(tp)) > 0)
- X (void) fprintf (plt_fp, "* %s\n", fnq);
- 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 (void) 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 (void) 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 (void) fclose (pfp);
- X } else {
- X char buf[NC];
- X (void) 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 if (sscanf (buf, fmt, &c, &x, &y) != 3)
- X continue;
- 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 if (sscanf (buf, fmt, &c, &x, &y) != 3)
- X continue;
- 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, "%g", maxy);
- X f_double (NR-1, 1, "%g", miny);
- X f_double (NR, 1, "%g", minx);
- X f_double (NR, NC-10, "%g", 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 if (sscanf (buf, fmt, &c, &r, &th) != 3)
- X continue;
- 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 if (sscanf (buf, fmt, &c, &r, &th) != 3)
- X continue;
- 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, "%g", maxr);
- X }
- X
- X /* hit any key to resume... */
- X (void) read_char();
- X redraw_screen (2); /* full redraw */
- X}
- END_OF_FILE
- if test 11208 -ne `wc -c <'plot.c'`; then
- echo shar: \"'plot.c'\" unpacked with wrong size!
- fi
- # end of 'plot.c'
- fi
- if test -f 'srch.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'srch.c'\"
- else
- echo shar: Extracting \"'srch.c'\" \(8160 characters\)
- sed "s/^X//" >'srch.c' <<'END_OF_FILE'
- X/* this file contains functions to support iterative ephem searches.
- X * we support several kinds of searching and solving algorithms.
- X * values used in the evaluations come from the field logging flog.c system.
- X * the expressions being evaluated are compiled and executed from compiler.c.
- X */
- X
- X#include <stdio.h>
- X#include <math.h>
- X#include "screen.h"
- X
- Xextern char *strcpy();
- X
- Xstatic int (*srch_f)();
- Xstatic int srch_tmscalled;
- Xstatic char expbuf[NC]; /* [0] == '\0' when expression is invalid */
- Xstatic double tmlimit = 1./60.; /* search accuracy, in hrs; def is one minute */
- X
- X
- Xsrch_setup()
- X{
- X int srch_minmax(), srch_solve0(), srch_binary();
- X static char *chcs[] = {
- X "Find extreme", "Find 0", "Binary", "New function", "Accuracy",
- X "Stop"
- X };
- X static int fn; /* start with 0, then remember for next time */
- X
- X /* let op select algorithm, edit, set accuracy
- X * or stop if currently searching
- X * algorithms require a function.
- X */
- X ask:
- X switch (popup(chcs, fn, srch_f ? 6 : 5)) {
- X case 0: fn = 0;
- X if (expbuf[0] == '\0')
- X set_function();
- X srch_f = expbuf[0] ? srch_minmax : (int (*)())0;
- X if (srch_f)
- X break;
- X else
- X goto ask;
- X case 1: fn = 1;
- X if (expbuf[0] == '\0')
- X set_function();
- X srch_f = expbuf[0] ? srch_solve0 : (int (*)())0;
- X if (srch_f)
- X break;
- X else
- X goto ask;
- X case 2: fn = 2;
- X if (expbuf[0] == '\0')
- X set_function();
- X srch_f = expbuf[0] ? srch_binary : (int (*)())0;
- X if (srch_f)
- X break;
- X else
- X goto ask;
- X case 3: fn = 3; srch_f = 0; set_function(); goto ask;
- X case 4: fn = 4; srch_f = 0; set_accuracy(); goto ask;
- X case 5: srch_f = 0; srch_prstate(0); return;
- X default: return;
- X }
- X
- X /* new search */
- X srch_tmscalled = 0;
- X srch_prstate (0);
- X}
- X
- X/* if searching is in effect call the search type function.
- X * it might modify *tmincp according to where it next wants to eval.
- X * (remember tminc is in hours, not days).
- X * if searching ends for any reason it is also turned off.
- X * also, flog the new value.
- X * return 0 if caller can continue or -1 if it is time to stop.
- X */
- Xsrch_eval(mjd, tmincp)
- Xdouble mjd;
- Xdouble *tmincp;
- X{
- X char errbuf[128];
- X int s;
- X double v;
- X
- X if (!srch_f)
- X return (0);
- X
- X if (execute_expr (&v, errbuf) < 0) {
- X srch_f = 0;
- X f_msg (errbuf);
- X } else {
- X s = (*srch_f)(mjd, v, tmincp);
- X if (s < 0)
- X srch_f = 0;
- X (void) flog_log (R_SRCH, C_SRCH, v, "");
- X srch_tmscalled++;
- X }
- X
- X srch_prstate (0);
- X return (s);
- X}
- X
- X/* print state of searching. */
- Xsrch_prstate (force)
- Xint force;
- X{
- X int srch_minmax(), srch_solve0(), srch_binary();
- X static (*last)();
- X
- X if (force || srch_f != last) {
- X f_string (R_SRCH, C_SRCHV,
- X srch_f == srch_minmax ? "Extrema" :
- X srch_f == srch_solve0 ? " Find 0" :
- X srch_f == srch_binary ? " Binary" :
- X " off");
- X last = srch_f;
- X }
- X}
- X
- Xsrch_ison()
- X{
- X return (srch_f != 0);
- X}
- X
- X/* display current expression. then if type in at least one char make it the
- X * current expression IF it compiles ok.
- X * TODO: editing?
- X */
- Xstatic
- Xset_function()
- X{
- X static char prompt[] = "Function: ";
- X char newexp[NC];
- X int s;
- X
- X f_prompt (prompt);
- X (void) fputs (expbuf, stdout);
- X c_pos (R_PROMPT, sizeof(prompt));
- X
- X s = read_line (newexp, PW-sizeof(prompt));
- X if (s >= 0) {
- X char errbuf[NC];
- X if (s > 0 && compile_expr (newexp, errbuf) < 0)
- X f_msg (errbuf);
- X else
- X (void) strcpy (expbuf, newexp);
- X }
- X}
- X
- Xstatic
- Xset_accuracy()
- X{
- X static char p[] = "Desired accuracy ( hrs): ";
- X int hrs, mins, secs;
- X char buf[NC];
- X
- X f_prompt (p);
- X f_time (R_PROMPT, C_PROMPT+18, tmlimit); /* place in blank spot */
- X c_pos (R_PROMPT, sizeof(p));
- X if (read_line (buf, PW-sizeof(p)) > 0) {
- X f_dec_sexsign (tmlimit, &hrs, &mins, &secs);
- X f_sscansex (buf, &hrs, &mins, &secs);
- X sex_dec (hrs, mins, secs, &tmlimit);
- X }
- X}
- X
- X/* use successive paraboloidal fits to find when expression is at a
- X * local minimum or maximum.
- X */
- Xstatic
- Xsrch_minmax(mjd, v, tmincp)
- Xdouble mjd;
- Xdouble v;
- Xdouble *tmincp;
- X{
- X static double base; /* for better stability */
- X static double x_1, x_2, x_3; /* keep in increasing order */
- X static double y_1, y_2, y_3;
- X double xm, a, b;
- X
- X if (srch_tmscalled == 0) {
- X base = mjd;
- X x_1 = 0.0;
- X y_1 = v;
- X return (0);
- X }
- X mjd -= base;
- X if (srch_tmscalled == 1) {
- X /* put in one of first two slots */
- X if (mjd < x_1) {
- X x_2 = x_1; y_2 = y_1;
- X x_1 = mjd; y_1 = v;
- X } else {
- X x_2 = mjd; y_2 = v;
- X }
- X return (0);
- X }
- X if (srch_tmscalled == 2 || fabs(mjd - x_1) < fabs(mjd - x_3)) {
- X /* closer to x_1 so discard x_3.
- X * or if it's our third value we know to "discard" x_3.
- X */
- X if (mjd > x_2) {
- X x_3 = mjd; y_3 = v;
- X } else {
- X x_3 = x_2; y_3 = y_2;
- X if (mjd > x_1) {
- X x_2 = mjd; y_2 = v;
- X } else {
- X x_2 = x_1; y_2 = y_1;
- X x_1 = mjd; y_1 = v;
- X }
- X }
- X if (srch_tmscalled == 2)
- X return (0);
- X } else {
- X /* closer to x_3 so discard x_1 */
- X if (mjd < x_2) {
- X x_1 = mjd; y_1 = v;
- X } else {
- X x_1 = x_2; y_1 = y_2;
- X if (mjd < x_3) {
- X x_2 = mjd; y_2 = v;
- X } else {
- X x_2 = x_3; y_2 = y_3;
- X x_3 = mjd; y_3 = v;
- X }
- X }
- X }
- X
- X#ifdef TRACEMM
- X { char buf[NC];
- X sprintf (buf, "x_1=%g y_1=%g x_2=%g y_2=%g x_3=%g y_3=%g",
- X x_1, y_1, x_2, y_2, x_3, y_3);
- X f_msg (buf);
- X }
- X#endif
- X a = y_1*(x_2-x_3) - y_2*(x_1-x_3) + y_3*(x_1-x_2);
- X if (fabs(a) < 1e-10) {
- X /* near-0 zero denominator, ie, curve is pretty flat here,
- X * so assume we are done enough.
- X * signal this by forcing a 0 tminc.
- X */
- X *tmincp = 0.0;
- X return (-1);
- X }
- X b = (x_1*x_1)*(y_2-y_3) - (x_2*x_2)*(y_1-y_3) + (x_3*x_3)*(y_1-y_2);
- X xm = -b/(2.0*a);
- X *tmincp = (xm - mjd)*24.0;
- X return (fabs (*tmincp) < tmlimit ? -1 : 0);
- X}
- X
- X/* use secant method to solve for time when expression passes through 0.
- X */
- Xstatic
- Xsrch_solve0(mjd, v, tmincp)
- Xdouble mjd;
- Xdouble v;
- Xdouble *tmincp;
- X{
- X static double x0, x_1; /* x(n-1) and x(n) */
- X static double y_0, y_1; /* y(n-1) and y(n) */
- X double x_2; /* x(n+1) */
- X double df; /* y(n) - y(n-1) */
- X
- X switch (srch_tmscalled) {
- X case 0: x0 = mjd; y_0 = v; return(0);
- X case 1: x_1 = mjd; y_1 = v; break;
- X default: x0 = x_1; y_0 = y_1; x_1 = mjd; y_1 = v; break;
- X }
- X
- X df = y_1 - y_0;
- X if (fabs(df) < 1e-10) {
- X /* near-0 zero denominator, ie, curve is pretty flat here,
- X * so assume we are done enough.
- X * signal this by forcing a 0 tminc.
- X */
- X *tmincp = 0.0;
- X return (-1);
- X }
- X x_2 = x_1 - y_1*(x_1-x0)/df;
- X *tmincp = (x_2 - mjd)*24.0;
- X return (fabs (*tmincp) < tmlimit ? -1 : 0);
- X}
- X
- X/* binary search for time when expression changes from its initial state.
- X * if the change is outside the initial tminc range, then keep searching in that
- X * direction by tminc first before starting to divide down.
- X */
- Xstatic
- Xsrch_binary(mjd, v, tmincp)
- Xdouble mjd;
- Xdouble v;
- Xdouble *tmincp;
- X{
- X static double lb, ub; /* lower and upper bound */
- X static int initial_state;
- X int this_state = v >= 0.5;
- X
- X#define FLUNDEF -9e10
- X
- X if (srch_tmscalled == 0) {
- X if (*tmincp >= 0.0) {
- X /* going forwards in time so first mjd is lb and no ub yet */
- X lb = mjd;
- X ub = FLUNDEF;
- X } else {
- X /* going backwards in time so first mjd is ub and no lb yet */
- X ub = mjd;
- X lb = FLUNDEF;
- X }
- X initial_state = this_state;
- X return (0);
- X }
- X
- X if (ub != FLUNDEF && lb != FLUNDEF) {
- X if (this_state == initial_state)
- X lb = mjd;
- X else
- X ub = mjd;
- X *tmincp = ((lb + ub)/2.0 - mjd)*24.0;
- X#ifdef TRACEBIN
- X { char buf[NC];
- X sprintf (buf, "lb=%g ub=%g tminc=%g mjd=%g is=%d ts=%d",
- X lb, ub, *tmincp, mjd, initial_state, this_state);
- X f_msg (buf);
- X }
- X#endif
- X /* signal to stop if asking for time change less than TMLIMIT */
- X return (fabs (*tmincp) < tmlimit ? -1 : 0);
- X } else if (this_state != initial_state) {
- X /* gone past; turn around half way */
- X if (*tmincp >= 0.0)
- X ub = mjd;
- X else
- X lb = mjd;
- X *tmincp /= -2.0;
- X return (0);
- X } else {
- X /* just keep going, looking for first state change but we keep
- X * learning the lower (or upper, if going backwards) bound.
- X */
- X if (*tmincp >= 0.0)
- X lb = mjd;
- X else
- X ub = mjd;
- X return (0);
- X }
- X}
- END_OF_FILE
- if test 8160 -ne `wc -c <'srch.c'`; then
- echo shar: \"'srch.c'\" unpacked with wrong size!
- fi
- # end of 'srch.c'
- fi
- echo shar: End of archive 7 \(of 9\).
- cp /dev/null ark7isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 9 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-