downey@cs.umn.edu@dimed1.UUCP (08/31/90)
Posting-number: Volume 14, Issue 79 Submitted-by: downey@cs.umn.edu@dimed1.UUCP Archive-name: ephem-4.21/part04 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 4 (of 6)." # Contents: compiler.c plans.c watch.c # Wrapped by allbery@uunet on Thu Aug 30 20:46:35 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'compiler.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'compiler.c'\" else echo shar: Extracting \"'compiler.c'\" \(15331 characters\) sed "s/^X//" >'compiler.c' <<'END_OF_FILE' X/* module to compile and execute a c-style arithmetic expression. X * public entry points are compile_expr() and execute_expr(). X * X * one reason this is so nice and tight is that all opcodes are the same size X * (an int) and the tokens the parser returns are directly usable as opcodes, X * for the most part. constants and variables are compiled as an opcode X * with an offset into the auxiliary opcode tape, opx. X */ X X#include <math.h> X#ifdef VMS X#include <stdlib.h> X#endif X#include "screen.h" X X/* parser tokens and opcodes, as necessary */ X#define HALT 0 /* good value for HALT since program is inited to 0 */ X/* binary operators (precedences in table, below) */ X#define ADD 1 X#define SUB 2 X#define MULT 3 X#define DIV 4 X#define AND 5 X#define OR 6 X#define GT 7 X#define GE 8 X#define EQ 9 X#define NE 10 X#define LT 11 X#define LE 12 X/* unary op, precedence in NEG_PREC #define, below */ X#define NEG 13 X/* symantically operands, ie, constants, variables and all functions */ X#define CONST 14 X#define VAR 15 X#define ABS 16 /* add functions if desired just like this is done */ X/* purely tokens - never get compiled as such */ X#define LPAREN 255 X#define RPAREN 254 X#define ERR (-1) X X/* precedence of each of the binary operators. X * in case of a tie, compiler associates left-to-right. X * N.B. each entry's index must correspond to its #define! X */ Xstatic int precedence[] = {0,5,5,6,6,2,1,4,4,3,3,4,4}; X#define NEG_PREC 7 /* negation is highest */ X X/* execute-time operand stack */ X#define MAX_STACK 16 Xstatic double stack[MAX_STACK], *sp; X X/* space for compiled opcodes - the "program". X * opcodes go in lower 8 bits. X * when an opcode has an operand (as CONST and VAR) it is really in opx[] and X * the index is in the remaining upper bits. X */ X#define MAX_PROG 32 Xstatic int program[MAX_PROG], *pc; X#define OP_SHIFT 8 X#define OP_MASK 0xff X X/* auxiliary operand info. X * the operands (all but lower 8 bits) of CONST and VAR are really indeces X * into this array. thus, no point in making this any longer than you have X * bits more than 8 in your machine's int to index into it, ie, make X * MAX_OPX <= 1 << ((sizeof(int)-1)*8) X * also, the fld's must refer to ones being flog'd, so not point in more X * of these then that might be used for plotting and srching combined. X */ X#define MAX_OPX 16 Xtypedef union { X double opu_f; /* value when opcode is CONST */ X int opu_fld; /* rcfpack() of field when opcode is VAR */ X} OpX; Xstatic OpX opx[MAX_OPX]; Xstatic int opxidx; X X/* these are global just for easy/rapid access */ Xstatic int parens_nest; /* to check that parens end up nested */ Xstatic char *err_msg; /* caller provides storage; we point at it with this */ Xstatic char *cexpr, *lcexpr; /* pointers that move along caller's expression */ Xstatic int good_prog; /* != 0 when program appears to be good */ X X/* compile the given c-style expression. X * return 0 and set good_prog if ok, X * else return -1 and a reason message in errbuf. X */ Xcompile_expr (ex, errbuf) Xchar *ex; Xchar *errbuf; X{ X int instr; X X /* init the globals. X * also delete any flogs used in the previous program. X */ X cexpr = ex; X err_msg = errbuf; X pc = program; X opxidx = 0; X parens_nest = 0; X do { X instr = *pc++; X if ((instr & OP_MASK) == VAR) X flog_delete (opx[instr >> OP_SHIFT].opu_fld); X } while (instr != HALT); X X pc = program; X if (compile(0) == ERR) { X (void) sprintf (err_msg + strlen(err_msg), " at \"%.10s\"", lcexpr); X good_prog = 0; X return (-1); X } X *pc++ = HALT; X good_prog = 1; X return (0); X} X X/* execute the expression previously compiled with compile_expr(). X * return 0 with *vp set to the answer if ok, else return -1 with a reason X * why not message in errbuf. X */ Xexecute_expr (vp, errbuf) Xdouble *vp; Xchar *errbuf; X{ X int s; X X err_msg = errbuf; X sp = stack + MAX_STACK; /* grows towards lower addresses */ X pc = program; X s = execute(vp); X if (s < 0) X good_prog = 0; X return (s); X} X X/* this is a way for the outside world to ask whether there is currently a X * reasonable program compiled and able to execute. X */ Xprog_isgood() X{ X return (good_prog); X} X X/* get and return the opcode corresponding to the next token. X * leave with lcexpr pointing at the new token, cexpr just after it. X * also watch for mismatches parens and proper operator/operand alternation. X */ Xstatic Xnext_token () X{ X static char toomt[] = "More than %d terms"; X static char badop[] = "Illegal operator"; X int tok = ERR; /* just something illegal */ X char c; X X while ((c = *cexpr) == ' ') X cexpr++; X lcexpr = cexpr++; X X /* mainly check for a binary operator */ X switch (c) { X case '\0': --cexpr; tok = HALT; break; /* keep returning HALT */ X case '+': tok = ADD; break; /* compiler knows when it's really unary */ X case '-': tok = SUB; break; /* compiler knows when it's really negate */ X case '*': tok = MULT; break; X case '/': tok = DIV; break; X case '(': parens_nest++; tok = LPAREN; break; X case ')': X if (--parens_nest < 0) { X (void) sprintf (err_msg, "Too many right parens"); X return (ERR); X } else X tok = RPAREN; X break; X case '|': X if (*cexpr == '|') { cexpr++; tok = OR; } X else { (void) sprintf (err_msg, badop); return (ERR); } X break; X case '&': X if (*cexpr == '&') { cexpr++; tok = AND; } X else { (void) sprintf (err_msg, badop); return (ERR); } X break; X case '=': X if (*cexpr == '=') { cexpr++; tok = EQ; } X else { (void) sprintf (err_msg, badop); return (ERR); } X break; X case '!': X if (*cexpr == '=') { cexpr++; tok = NE; } X else { (void) sprintf (err_msg, badop); return (ERR); } X break; X case '<': X if (*cexpr == '=') { cexpr++; tok = LE; } X else tok = LT; X break; X case '>': X if (*cexpr == '=') { cexpr++; tok = GE; } X else tok = GT; X break; X } X X if (tok != ERR) X return (tok); X X /* not op so check for a constant, variable or function */ X if (isdigit(c) || c == '.') { X if (opxidx > MAX_OPX) { X (void) sprintf (err_msg, toomt, MAX_OPX); X return (ERR); X } X opx[opxidx].opu_f = atof (lcexpr); X tok = CONST | (opxidx++ << OP_SHIFT); X skip_double(); X } else if (isalpha(c)) { X /* check list of functions */ X if (strncmp (lcexpr, "abs", 3) == 0) { X cexpr += 2; X tok = ABS; X } else { X /* not a function, so assume it's a variable */ X int fld; X if (opxidx > MAX_OPX) { X (void) sprintf (err_msg, toomt, MAX_OPX); X return (ERR); X } X fld = parse_fieldname (); X if (fld < 0) { X (void) sprintf (err_msg, "Unknown field"); X return (ERR); X } else { X if (flog_add (fld) < 0) { /* register with field logger */ X (void) sprintf (err_msg, "Sorry; too many fields"); X return (ERR); X } X opx[opxidx].opu_fld = fld; X tok = VAR | (opxidx++ << OP_SHIFT); X } X } X } X X return (tok); X} X X/* move cexpr on past a double. X * allow sci notation. X * no need to worry about a leading '-' or '+' but allow them after an 'e'. X * TODO: this handles all the desired cases, but also admits a bit too much X * such as things like 1eee2...3. geeze; to skip a double right you almost X * have to go ahead and crack it! X */ Xstatic Xskip_double() X{ X int sawe = 0; /* so we can allow '-' or '+' right after an 'e' */ X X while (1) { X char c = *cexpr; X if (isdigit(c) || c=='.' || (sawe && (c=='-' || c=='+'))) { X sawe = 0; X cexpr++; X } else if (c == 'e') { X sawe = 1; X cexpr++; X } else X break; X } X} X X/* call this whenever you want to dig out the next (sub)expression. X * keep compiling instructions as long as the operators are higher precedence X * than prec, then return that "look-ahead" token that wasn't (higher prec). X * if error, fill in a message in err_msg[] and return ERR. X */ Xstatic Xcompile (prec) Xint prec; X{ X int expect_binop = 0; /* set after we have seen any operand. X * used by SUB so it can tell if it really X * should be taken to be a NEG instead. X */ X int tok = next_token (); X X while (1) { X int p; X if (tok == ERR) X return (ERR); X if (pc - program >= MAX_PROG) { X (void) sprintf (err_msg, "Program is too long"); X return (ERR); X } X X /* check for special things like functions, constants and parens */ X switch (tok & OP_MASK) { X case HALT: return (tok); X case ADD: X if (expect_binop) X break; /* procede with binary addition */ X /* just skip a unary positive(?) */ X tok = next_token(); X continue; X case SUB: X if (expect_binop) X break; /* procede with binary subtract */ X tok = compile (NEG_PREC); X *pc++ = NEG; X expect_binop = 1; X continue; X case ABS: /* other funcs would be handled the same too ... */ X /* eat up the function parenthesized argument */ X if (next_token() != LPAREN || compile (0) != RPAREN) { X (void) sprintf (err_msg, "Function arglist error"); X return (ERR); X } X /* then handled same as ... */ X case CONST: /* handled same as... */ X case VAR: X *pc++ = tok; X tok = next_token(); X expect_binop = 1; X continue; X case LPAREN: X if (compile (0) != RPAREN) { X (void) sprintf (err_msg, "Unmatched left paren"); X return (ERR); X } X tok = next_token(); X expect_binop = 1; X continue; X case RPAREN: X return (RPAREN); X } X X /* everything else is a binary operator */ X p = precedence[tok]; X if (p > prec) { X int newtok = compile (p); X if (newtok == ERR) X return (ERR); X *pc++ = tok; X expect_binop = 1; X tok = newtok; X } else X return (tok); X } X} X X/* "run" the program[] compiled with compile(). X * if ok, return 0 and the final result, X * else return -1 with a reason why not message in err_msg. X */ Xstatic Xexecute(result) Xdouble *result; X{ X int instr; X X do { X instr = *pc++; X switch (instr & OP_MASK) { X /* put these in numberic order so hopefully even the dumbest X * compiler will choose to use a jump table, not a cascade of ifs. X */ X case HALT: break; /* outer loop will stop us */ X case ADD: sp[1] = sp[1] + sp[0]; sp++; break; X case SUB: sp[1] = sp[1] - sp[0]; sp++; break; X case MULT: sp[1] = sp[1] * sp[0]; sp++; break; X case DIV: sp[1] = sp[1] / sp[0]; sp++; break; X case AND: sp[1] = sp[1] && sp[0] ? 1 : 0; sp++; break; X case OR: sp[1] = sp[1] || sp[0] ? 1 : 0; sp++; break; X case GT: sp[1] = sp[1] > sp[0] ? 1 : 0; sp++; break; X case GE: sp[1] = sp[1] >= sp[0] ? 1 : 0; sp++; break; X case EQ: sp[1] = sp[1] == sp[0] ? 1 : 0; sp++; break; X case NE: sp[1] = sp[1] != sp[0] ? 1 : 0; sp++; break; X case LT: sp[1] = sp[1] < sp[0] ? 1 : 0; sp++; break; X case LE: sp[1] = sp[1] <= sp[0] ? 1 : 0; sp++; break; X case NEG: *sp = -*sp; break; X case CONST: *--sp = opx[instr >> OP_SHIFT].opu_f; break; X case VAR: X if (flog_get(opx[instr>>OP_SHIFT].opu_fld, --sp, (char *)0)<0) { X (void) sprintf (err_msg, "Bug! VAR field not logged"); X return (-1); X } X break; X case ABS: *sp = fabs (*sp); break; X default: X (void) sprintf (err_msg, "Bug! bad opcode: 0x%x", instr); X return (-1); X } X if (sp < stack) { X (void) sprintf (err_msg, "Runtime stack overflow"); X return (-1); X } else if (sp - stack > MAX_STACK) { X (void) sprintf (err_msg, "Bug! runtime stack underflow"); X return (-1); X } X } while (instr != HALT); X X /* result should now be on top of stack */ X if (sp != &stack[MAX_STACK - 1]) { X (void) sprintf (err_msg, "Bug! stack has %d items", X MAX_STACK - (sp-stack)); X return (-1); X } X *result = *sp; X return (0); X} X Xstatic Xisdigit(c) Xchar c; X{ X return (c >= '0' && c <= '9'); X} X Xstatic Xisalpha (c) Xchar c; X{ X return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')); X} X X/* starting with lcexpr pointing at a string expected to be a field name, X * return an rcfpack(r,c,0) of the field else -1 if bad. X * when return, leave lcexpr alone but move cexpr to just after the name. X */ Xstatic Xparse_fieldname () X{ X int r = -1, c = -1; /* anything illegal */ X char *fn = lcexpr; /* likely faster than using the global */ X char f0, f1; X char *dp; X X /* search for first thing not an alpha char. X * leave it in f0 and leave dp pointing to it. X */ X dp = fn; X while (isalpha(f0 = *dp)) X dp++; X X /* crack the new field name. X * when done trying, leave dp pointing at first char just after it. X * set r and c if we recognized it. X */ X if (f0 == '.') { X /* planet.column pair. X * first crack the planet portion (pointed to by fn): set r. X * then the second portion (pointed to by dp+1): set c. X */ X f0 = fn[0]; X f1 = fn[1]; X switch (f0) { X case 'j': X r = R_JUPITER; X break; X case 'm': X if (f1 == 'a') r = R_MARS; X else if (f1 == 'e') r = R_MERCURY; X else if (f1 == 'o') r = R_MOON; X break; X case 'n': X r = R_NEPTUNE; X break; X case 'p': X r = R_PLUTO; X break; X case 's': X if (f1 == 'a') r = R_SATURN; X else if (f1 == 'u') r = R_SUN; X break; X case 'u': X r = R_URANUS; X break; X case 'x': X r = R_OBJX; X break; X case 'y': X r = R_OBJY; X break; X case 'v': X r = R_VENUS; X break; X } X X /* now crack the column (stuff after the dp) */ X dp++; /* point at good stuff just after the decimal pt */ X f0 = dp[0]; X f1 = dp[1]; X switch (f0) { X case 'a': X if (f1 == 'l') c = C_ALT; X else if (f1 == 'z') c = C_AZ; X break; X case 'd': X c = C_DEC; X break; X case 'e': X if (f1 == 'd') c = C_EDIST; X else if (f1 == 'l') c = C_ELONG; X break; X case 'h': X if (f1 == 'l') { X if (dp[2] == 'a') c = C_HLAT; X else if (dp[2] == 'o') c = C_HLONG; X } else if (f1 == 'r' || f1 == 'u') c = C_TUP; X break; X case 'j': X c = C_JUPITER; X break; X case 'm': X if (f1 == 'a') c = C_MARS; X else if (f1 == 'e') c = C_MERCURY; X else if (f1 == 'o') c = C_MOON; X break; X case 'n': X c = C_NEPTUNE; X break; X case 'p': X if (f1 == 'h') c = C_PHASE; X else if (f1 == 'l') c = C_PLUTO; X break; X case 'r': X if (f1 == 'a') { X if (dp[2] == 'z') c = C_RISEAZ; X else c = C_RA; X } else if (f1 == 't') c = C_RISETM; X break; X case 's': X if (f1 == 'a') { X if (dp[2] == 'z') c = C_SETAZ; X else c = C_SATURN; X } else if (f1 == 'd') c = C_SDIST; X else if (f1 == 'i') c = C_SIZE; X else if (f1 == 't') c = C_SETTM; X else if (f1 == 'u') c = C_SUN; X break; X case 't': X if (f1 == 'a') c = C_TRANSALT; X else if (f1 == 't') c = C_TRANSTM; X break; X case 'u': X c = C_URANUS; X break; X case 'x': X c = C_OBJX; X break; X case 'y': X c = C_OBJY; X break; X case 'v': X if (f1 == 'e') c = C_VENUS; X else if (f1 == 'm') c = C_MAG; X break; X } X X /* now skip dp on past the column stuff */ X while (isalpha(*dp)) X dp++; X } else { X /* no decimal point; some field in the top of the screen */ X f0 = fn[0]; X f1 = fn[1]; X switch (f0) { X case 'd': X if (f1 == 'a') r = R_DAWN, c = C_DAWNV; X else if (f1 == 'u') r = R_DUSK, c = C_DUSKV; X break; X case 'n': X r = R_LON, c = C_LONV; X break; X } X } X X cexpr = dp; X if (r <= 0 || c <= 0) return (-1); X return (rcfpack (r, c, 0)); X} END_OF_FILE if test 15331 -ne `wc -c <'compiler.c'`; then echo shar: \"'compiler.c'\" unpacked with wrong size! fi # end of 'compiler.c' fi if test -f 'plans.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'plans.c'\" else echo shar: Extracting \"'plans.c'\" \(17647 characters\) sed "s/^X//" >'plans.c' <<'END_OF_FILE' X#include <stdio.h> X#include <math.h> X#include "astro.h" X X#define TWOPI (2*PI) X#define mod2PI(x) ((x) - (long)((x)/TWOPI)*TWOPI) X X/* given a modified Julian date, mjd, and a planet, p, find: X * lpd0: heliocentric longitude, X * psi0: heliocentric latitude, X * rp0: distance from the sun to the planet, X * rho0: distance from the Earth to the planet, X * none corrected for light time, ie, they are the true values for the X * given instant. X * lam: geocentric ecliptic longitude, X * bet: geocentric ecliptic latitude, X * each corrected for light time, ie, they are the apparent values as X * seen from the center of the Earth for the given instant. X * dia: angular diameter in arcsec at 1 AU, X * mag: visual magnitude when 1 AU from sun and earth at 0 phase angle. X * X * all angles are in radians, all distances in AU. X * the mean orbital elements are found by calling pelement(), then mutual X * perturbation corrections are applied as necessary. X * X * corrections for nutation and abberation must be made by the caller. The RA X * and DEC calculated from the fully-corrected ecliptic coordinates are then X * the apparent geocentric coordinates. Further corrections can be made, if X * required, for atmospheric refraction and geocentric parallax although the X * intrinsic error herein of about 10 arcseconds is usually the dominant X * error at this stage. X * TODO: combine the several intermediate expressions when get a good compiler. X */ Xplans (mjd, p, lpd0, psi0, rp0, rho0, lam, bet, dia, mag) Xdouble mjd; Xint p; Xdouble *lpd0, *psi0, *rp0, *rho0, *lam, *bet, *dia, *mag; X{ X static double plan[8][9]; X static double lastmjd = -10000; X double dl; /* perturbation correction for longitude */ X double dr; /* " orbital radius */ X double dml; /* " mean longitude */ X double ds; /* " eccentricity */ X double dm; /* " mean anomaly */ X double da; /* " semi-major axis */ X double dhl; /* " heliocentric longitude */ X double lsn, rsn;/* true geocentric longitude of sun and sun-earth rad */ X double mas; /* mean anomaly of the sun */ X double re; /* radius of earth's orbit */ X double lg; /* longitude of earth */ X double map[8]; /* array of mean anomalies for each planet */ X double lpd, psi, rp, rho; X double ll, sll, cll; X double t; X double dt; X int pass; X int j; X double s, ma; X double nu, ea; X double lp, om; X double lo, slo, clo; X double inc, y; X double spsi, cpsi; X double rpd; X X /* only need to fill in plan[] once for a given mjd */ X if (mjd != lastmjd) { X pelement (mjd, plan); X lastmjd = mjd; X } X X dt = 0; X t = mjd/36525.; X sunpos (mjd, &lsn, &rsn); X masun (mjd, &mas); X re = rsn; X lg = lsn+PI; X X /* first find the true position of the planet at mjd. X * then repeat a second time for a slightly different time based X * on the position found in the first pass to account for light-travel X * time. X */ X for (pass = 0; pass < 2; pass++) { X X for (j = 0; j < 8; j++) X map[j] = degrad(plan[j][0]-plan[j][2]-dt*plan[j][1]); X X /* set initial corrections to 0. X * then modify as necessary for the planet of interest. X */ X dl = 0; X dr = 0; X dml = 0; X ds = 0; X dm = 0; X da = 0; X dhl = 0; X X switch (p) { X X case MERCURY: X p_mercury (map, &dl, &dr); X break; X X case VENUS: X p_venus (t, mas, map, &dl, &dr, &dml, &dm); X break; X X case MARS: X p_mars (mas, map, &dl, &dr, &dml, &dm); X break; X X case JUPITER: X p_jupiter (t, plan[p][3], &dml, &ds, &dm, &da); X break; X X case SATURN: X p_saturn (t, plan[p][3], &dml, &ds, &dm, &da, &dhl); X break; X X case URANUS: X p_uranus (t, plan[p][3], &dl, &dr, &dml, &ds, &dm, &da, &dhl); X break; X X case NEPTUNE: X p_neptune (t, plan[p][3], &dl, &dr, &dml, &ds, &dm, &da, &dhl); X break; X X case PLUTO: X /* no perturbation theory for pluto */ X break; X } X X s = plan[p][3]+ds; X ma = map[p]+dm; X anomaly (ma, s, &nu, &ea); X rp = (plan[p][6]+da)*(1-s*s)/(1+s*cos(nu)); X lp = raddeg(nu)+plan[p][2]+raddeg(dml-dm); X lp = degrad(lp); X om = degrad(plan[p][5]); X lo = lp-om; X slo = sin(lo); X clo = cos(lo); X inc = degrad(plan[p][4]); X rp = rp+dr; X spsi = slo*sin(inc); X y = slo*cos(inc); X psi = asin(spsi)+dhl; X spsi = sin(psi); X lpd = atan(y/clo)+om+degrad(dl); X if (clo<0) lpd += PI; X range (&lpd, TWOPI); X cpsi = cos(psi); X rpd = rp*cpsi; X ll = lpd-lg; X rho = sqrt(re*re+rp*rp-2*re*rp*cpsi*cos(ll)); X X /* when we view a planet we see it in the position it occupied X * dt days ago, where rho is the distance between it and earth, X * in AU. use this as the new time for the next pass. X */ X dt = rho*5.775518e-3; X X if (pass == 0) { X /* save heliocentric coordinates after first pass since, being X * true, they are NOT to be corrected for light-travel time. X */ X *lpd0 = lpd; X range (lpd0, TWOPI); X *psi0 = psi; X *rp0 = rp; X *rho0 = rho; X } X } X X sll = sin(ll); X cll = cos(ll); X if (p < MARS) X *lam = atan(-1*rpd*sll/(re-rpd*cll))+lg+PI; X else X *lam = atan(re*sll/(rpd-re*cll))+lpd; X range (lam, TWOPI); X *bet = atan(rpd*spsi*sin(*lam-lpd)/(cpsi*re*sll)); X *dia = plan[p][7]; X *mag = plan[p][8]; X} X X/* set auxilliary variables used for jupiter, saturn, uranus, and neptune */ Xstatic Xaux_jsun (t, x1, x2, x3, x4, x5, x6) Xdouble t; Xdouble *x1, *x2, *x3, *x4, *x5, *x6; X{ X *x1 = t/5+0.1; X *x2 = mod2PI(4.14473+5.29691e1*t); X *x3 = mod2PI(4.641118+2.132991e1*t); X *x4 = mod2PI(4.250177+7.478172*t); X *x5 = 5 * *x3 - 2 * *x2; X *x6 = 2 * *x2 - 6 * *x3 + 3 * *x4; X} X X/* find the mean anomaly of the sun at mjd. X * this is the same as that used in sun() but when it was converted to C it X * was not known it would be required outside that routine. X * TODO: add an argument to sun() to return mas and eliminate this routine. X */ Xstatic Xmasun (mjd, mas) Xdouble mjd; Xdouble *mas; X{ X double t, t2; X double a, b; X X t = mjd/36525; X t2 = t*t; X a = 9.999736042e1*t; X b = 360.*(a-(long)a); X *mas = degrad (3.5847583e2-(1.5e-4+3.3e-6*t)*t2+b); X} X X/* perturbations for mercury */ Xstatic Xp_mercury (map, dl, dr) Xdouble map[]; Xdouble *dl, *dr; X{ X *dl = 2.04e-3*cos(5*map[2-1]-2*map[1-1]+2.1328e-1)+ X 1.03e-3*cos(2*map[2-1]-map[1-1]-2.8046)+ X 9.1e-4*cos(2*map[3]-map[1-1]-6.4582e-1)+ X 7.8e-4*cos(5*map[2-1]-3*map[1-1]+1.7692e-1); X X *dr = 7.525e-6*cos(2*map[3]-map[1-1]+9.25251e-1)+ X 6.802e-6*cos(5*map[2-1]-3*map[1-1]-4.53642)+ X 5.457e-6*cos(2*map[2-1]-2*map[1-1]-1.24246)+ X 3.569e-6*cos(5*map[2-1]-map[1-1]-1.35699); X} X X/* ....venus */ Xstatic Xp_venus (t, mas, map, dl, dr, dml, dm) Xdouble t, mas, map[]; Xdouble *dl, *dr, *dml, *dm; X{ X *dml = degrad (7.7e-4*sin(4.1406+t*2.6227)); X *dm = *dml; X X *dl = 3.13e-3*cos(2*mas-2*map[2-1]-2.587)+ X 1.98e-3*cos(3*mas-3*map[2-1]+4.4768e-2)+ X 1.36e-3*cos(mas-map[2-1]-2.0788)+ X 9.6e-4*cos(3*mas-2*map[2-1]-2.3721)+ X 8.2e-4*cos(map[3]-map[2-1]-3.6318); X X *dr = 2.2501e-5*cos(2*mas-2*map[2-1]-1.01592)+ X 1.9045e-5*cos(3*mas-3*map[2-1]+1.61577)+ X 6.887e-6*cos(map[3]-map[2-1]-2.06106)+ X 5.172e-6*cos(mas-map[2-1]-5.08065e-1)+ X 3.62e-6*cos(5*mas-4*map[2-1]-1.81877)+ X 3.283e-6*cos(4*mas-4*map[2-1]+1.10851)+ X 3.074e-6*cos(2*map[3]-2*map[2-1]-9.62846e-1); X} X X/* ....mars */ Xstatic Xp_mars (mas, map, dl, dr, dml, dm) Xdouble mas, map[]; Xdouble *dl, *dr, *dml, *dm; X{ X double a; X X a = 3*map[3]-8*map[2]+4*mas; X *dml = degrad (-1*(1.133e-2*sin(a)+9.33e-3*cos(a))); X *dm = *dml; X X *dl = 7.05e-3*cos(map[3]-map[2]-8.5448e-1)+ X 6.07e-3*cos(2*map[3]-map[2]-3.2873)+ X 4.45e-3*cos(2*map[3]-2*map[2]-3.3492)+ X 3.88e-3*cos(mas-2*map[2]+3.5771e-1)+ X 2.38e-3*cos(mas-map[2]+6.1256e-1)+ X 2.04e-3*cos(2*mas-3*map[2]+2.7688)+ X 1.77e-3*cos(3*map[2]-map[2-1]-1.0053)+ X 1.36e-3*cos(2*mas-4*map[2]+2.6894)+ X 1.04e-3*cos(map[3]+3.0749e-1); X X *dr = 5.3227e-5*cos(map[3]-map[2]+7.17864e-1)+ X 5.0989e-5*cos(2*map[3]-2*map[2]-1.77997)+ X 3.8278e-5*cos(2*map[3]-map[2]-1.71617)+ X 1.5996e-5*cos(mas-map[2]-9.69618e-1)+ X 1.4764e-5*cos(2*mas-3*map[2]+1.19768)+ X 8.966e-6*cos(map[3]-2*map[2]+7.61225e-1); X *dr += 7.914e-6*cos(3*map[3]-2*map[2]-2.43887)+ X 7.004e-6*cos(2*map[3]-3*map[2]-1.79573)+ X 6.62e-6*cos(mas-2*map[2]+1.97575)+ X 4.93e-6*cos(3*map[3]-3*map[2]-1.33069)+ X 4.693e-6*cos(3*mas-5*map[2]+3.32665)+ X 4.571e-6*cos(2*mas-4*map[2]+4.27086)+ X 4.409e-6*cos(3*map[3]-map[2]-2.02158); X} X X/* ....jupiter */ Xstatic Xp_jupiter (t, s, dml, ds, dm, da) Xdouble t, s; Xdouble *dml, *ds, *dm, *da; X{ X double dp; X double x1, x2, x3, x4, x5, x6, x7; X double sx3, cx3, s2x3, c2x3; X double sx5, cx5, s2x5; X double sx6; X double sx7, cx7, s2x7, c2x7, s3x7, c3x7, s4x7, c4x7, c5x7; X X aux_jsun (t, &x1, &x2, &x3, &x4, &x5, &x6); X x7 = x3-x2; X sx3 = sin(x3); X cx3 = cos(x3); X s2x3 = sin(2*x3); X c2x3 = cos(2*x3); X sx5 = sin(x5); X cx5 = cos(x5); X s2x5 = sin(2*x5); X sx6 = sin(x6); X sx7 = sin(x7); X cx7 = cos(x7); X s2x7 = sin(2*x7); X c2x7 = cos(2*x7); X s3x7 = sin(3*x7); X c3x7 = cos(3*x7); X s4x7 = sin(4*x7); X c4x7 = cos(4*x7); X c5x7 = cos(5*x7); X X *dml = (3.31364e-1-(1.0281e-2+4.692e-3*x1)*x1)*sx5+ X (3.228e-3-(6.4436e-2-2.075e-3*x1)*x1)*cx5- X (3.083e-3+(2.75e-4-4.89e-4*x1)*x1)*s2x5+ X 2.472e-3*sx6+1.3619e-2*sx7+1.8472e-2*s2x7+6.717e-3*s3x7+ X 2.775e-3*s4x7+6.417e-3*s2x7*sx3+ X (7.275e-3-1.253e-3*x1)*sx7*sx3+ X 2.439e-3*s3x7*sx3-(3.5681e-2+1.208e-3*x1)*sx7*cx3; X *dml += -3.767e-3*c2x7*sx3-(3.3839e-2+1.125e-3*x1)*cx7*sx3- X 4.261e-3*s2x7*cx3+ X (1.161e-3*x1-6.333e-3)*cx7*cx3+ X 2.178e-3*cx3-6.675e-3*c2x7*cx3-2.664e-3*c3x7*cx3- X 2.572e-3*sx7*s2x3-3.567e-3*s2x7*s2x3+2.094e-3*cx7*c2x3+ X 3.342e-3*c2x7*c2x3; X *dml = degrad(*dml); X X *ds = (3606+(130-43*x1)*x1)*sx5+(1289-580*x1)*cx5-6764*sx7*sx3- X 1110*s2x7*sx3-224*s3x7*sx3-204*sx3+(1284+116*x1)*cx7*sx3+ X 188*c2x7*sx3+(1460+130*x1)*sx7*cx3+224*s2x7*cx3-817*cx3+ X 6074*cx3*cx7+992*c2x7*cx3+ X 508*c3x7*cx3+230*c4x7*cx3+108*c5x7*cx3; X *ds += -(956+73*x1)*sx7*s2x3+448*s2x7*s2x3+137*s3x7*s2x3+ X (108*x1-997)*cx7*s2x3+480*c2x7*s2x3+148*c3x7*s2x3+ X (99*x1-956)*sx7*c2x3+490*s2x7*c2x3+ X 158*s3x7*c2x3+179*c2x3+(1024+75*x1)*cx7*c2x3- X 437*c2x7*c2x3-132*c3x7*c2x3; X *ds *= 1e-7; X X dp = (7.192e-3-3.147e-3*x1)*sx5-4.344e-3*sx3+ X (x1*(1.97e-4*x1-6.75e-4)-2.0428e-2)*cx5+ X 3.4036e-2*cx7*sx3+(7.269e-3+6.72e-4*x1)*sx7*sx3+ X 5.614e-3*c2x7*sx3+2.964e-3*c3x7*sx3+3.7761e-2*sx7*cx3+ X 6.158e-3*s2x7*cx3- X 6.603e-3*cx7*cx3-5.356e-3*sx7*s2x3+2.722e-3*s2x7*s2x3+ X 4.483e-3*cx7*s2x3-2.642e-3*c2x7*s2x3+4.403e-3*sx7*c2x3- X 2.536e-3*s2x7*c2x3+5.547e-3*cx7*c2x3-2.689e-3*c2x7*c2x3; X X *dm = *dml-(degrad(dp)/s); X X *da = 205*cx7-263*cx5+693*c2x7+312*c3x7+147*c4x7+299*sx7*sx3+ X 181*c2x7*sx3+204*s2x7*cx3+111*s3x7*cx3-337*cx7*cx3- X 111*c2x7*cx3; X *da *= 1e-6; X} X X/* ....saturn */ Xstatic Xp_saturn (t, s, dml, ds, dm, da, dhl) Xdouble t, s; Xdouble *dml, *ds, *dm, *da, *dhl; X{ X double dp; X double x1, x2, x3, x4, x5, x6, x7, x8; X double sx3, cx3, s2x3, c2x3, s3x3, c3x3, s4x3, c4x3; X double sx5, cx5, s2x5, c2x5; X double sx6; X double sx7, cx7, s2x7, c2x7, s3x7, c3x7, s4x7, c4x7, c5x7, s5x7; X double s2x8, c2x8, s3x8, c3x8; X X aux_jsun (t, &x1, &x2, &x3, &x4, &x5, &x6); X x7 = x3-x2; X sx3 = sin(x3); X cx3 = cos(x3); X s2x3 = sin(2*x3); X c2x3 = cos(2*x3); X sx5 = sin(x5); X cx5 = cos(x5); X s2x5 = sin(2*x5); X sx6 = sin(x6); X sx7 = sin(x7); X cx7 = cos(x7); X s2x7 = sin(2*x7); X c2x7 = cos(2*x7); X s3x7 = sin(3*x7); X c3x7 = cos(3*x7); X s4x7 = sin(4*x7); X c4x7 = cos(4*x7); X c5x7 = cos(5*x7); X X s3x3 = sin(3*x3); X c3x3 = cos(3*x3); X s4x3 = sin(4*x3); X c4x3 = cos(4*x3); X c2x5 = cos(2*x5); X s5x7 = sin(5*x7); X x8 = x4-x3; X s2x8 = sin(2*x8); X c2x8 = cos(2*x8); X s3x8 = sin(3*x8); X c3x8 = cos(3*x8); X X *dml = 7.581e-3*s2x5-7.986e-3*sx6-1.48811e-1*sx7-4.0786e-2*s2x7- X (8.14181e-1-(1.815e-2-1.6714e-2*x1)*x1)*sx5- X (1.0497e-2-(1.60906e-1-4.1e-3*x1)*x1)*cx5-1.5208e-2*s3x7- X 6.339e-3*s4x7-6.244e-3*sx3-1.65e-2*s2x7*sx3+ X (8.931e-3+2.728e-3*x1)*sx7*sx3-5.775e-3*s3x7*sx3+ X (8.1344e-2+3.206e-3*x1)*cx7*sx3+1.5019e-2*c2x7*sx3; X *dml += (8.5581e-2+2.494e-3*x1)*sx7*cx3+1.4394e-2*c2x7*cx3+ X (2.5328e-2-3.117e-3*x1)*cx7*cx3+ X 6.319e-3*c3x7*cx3+6.369e-3*sx7*s2x3+9.156e-3*s2x7*s2x3+ X 7.525e-3*s3x8*s2x3-5.236e-3*cx7*c2x3-7.736e-3*c2x7*c2x3- X 7.528e-3*c3x8*c2x3; X *dml = degrad(*dml); X X *ds = (-7927+(2548+91*x1)*x1)*sx5+(13381+(1226-253*x1)*x1)*cx5+ X (248-121*x1)*s2x5-(305+91*x1)*c2x5+412*s2x7+12415*sx3+ X (390-617*x1)*sx7*sx3+(165-204*x1)*s2x7*sx3+26599*cx7*sx3- X 4687*c2x7*sx3-1870*c3x7*sx3-821*c4x7*sx3- X 377*c5x7*sx3+497*c2x8*sx3+(163-611*x1)*cx3; X *ds += -12696*sx7*cx3-4200*s2x7*cx3-1503*s3x7*cx3-619*s4x7*cx3- X 268*s5x7*cx3-(282+1306*x1)*cx7*cx3+(-86+230*x1)*c2x7*cx3+ X 461*s2x8*cx3-350*s2x3+(2211-286*x1)*sx7*s2x3- X 2208*s2x7*s2x3-568*s3x7*s2x3-346*s4x7*s2x3- X (2780+222*x1)*cx7*s2x3+(2022+263*x1)*c2x7*s2x3+248*c3x7*s2x3+ X 242*s3x8*s2x3+467*c3x8*s2x3-490*c2x3-(2842+279*x1)*sx7*c2x3; X *ds += (128+226*x1)*s2x7*c2x3+224*s3x7*c2x3+ X (-1594+282*x1)*cx7*c2x3+(2162-207*x1)*c2x7*c2x3+ X 561*c3x7*c2x3+343*c4x7*c2x3+469*s3x8*c2x3-242*c3x8*c2x3- X 205*sx7*s3x3+262*s3x7*s3x3+208*cx7*c3x3-271*c3x7*c3x3- X 382*c3x7*s4x3-376*s3x7*c4x3; X *ds *= 1e-7; X X dp = (7.7108e-2+(7.186e-3-1.533e-3*x1)*x1)*sx5-7.075e-3*sx7+ X (4.5803e-2-(1.4766e-2+5.36e-4*x1)*x1)*cx5-7.2586e-2*cx3- X 7.5825e-2*sx7*sx3-2.4839e-2*s2x7*sx3-8.631e-3*s3x7*sx3- X 1.50383e-1*cx7*cx3+2.6897e-2*c2x7*cx3+1.0053e-2*c3x7*cx3- X (1.3597e-2+1.719e-3*x1)*sx7*s2x3+1.1981e-2*s2x7*c2x3; X dp += -(7.742e-3-1.517e-3*x1)*cx7*s2x3+ X (1.3586e-2-1.375e-3*x1)*c2x7*c2x3- X (1.3667e-2-1.239e-3*x1)*sx7*c2x3+ X (1.4861e-2+1.136e-3*x1)*cx7*c2x3- X (1.3064e-2+1.628e-3*x1)*c2x7*c2x3; X X *dm = *dml-(degrad(dp)/s); X X *da = 572*sx5-1590*s2x7*cx3+2933*cx5-647*s3x7*cx3+33629*cx7- X 344*s4x7*cx3-3081*c2x7+2885*cx7*cx3-1423*c3x7+ X (2172+102*x1)*c2x7*cx3-671*c4x7+296*c3x7*cx3-320*c5x7- X 267*s2x7*s2x3+1098*sx3-778*cx7*s2x3-2812*sx7*sx3; X *da += 495*c2x7*s2x3+688*s2x7*sx3+250*c3x7*s2x3-393*s3x7*sx3- X 856*sx7*c2x3-228*s4x7*sx3+441*s2x7*c2x3+2138*cx7*sx3+ X 296*c2x7*c2x3-999*c2x7*sx3+211*c3x7*c2x3-642*c3x7*sx3- X 427*sx7*s3x3-325*c4x7*sx3+398*s3x7*s3x3-890*cx3+ X 344*cx7*c3x3+2206*sx7*cx3-427*c3x7*c3x3; X *da *= 1e-6; X X *dhl = 7.47e-4*cx7*sx3+1.069e-3*cx7*cx3+2.108e-3*s2x7*s2x3+ X 1.261e-3*c2x7*s2x3+1.236e-3*s2x7*c2x3-2.075e-3*c2x7*c2x3; X *dhl = degrad(*dhl); X} X X/* ....uranus */ Xstatic Xp_uranus (t, s, dl, dr, dml, ds, dm, da, dhl) Xdouble t, s; Xdouble *dl, *dr, *dml, *ds, *dm, *da, *dhl; X{ X double dp; X double x1, x2, x3, x4, x5, x6; X double x8, x9, x10, x11, x12; X double sx4, cx4, s2x4, c2x4; X double sx9, cx9, s2x9, c2x9; X double sx11, cx11; X X aux_jsun (t, &x1, &x2, &x3, &x4, &x5, &x6); X X x8 = mod2PI(1.46205+3.81337*t); X x9 = 2*x8-x4; X sx9 = sin(x9); X cx9 = cos(x9); X s2x9 = sin(2*x9); X c2x9 = cos(2*x9); X X x10 = x4-x2; X x11 = x4-x3; X x12 = x8-x4; X X *dml = (8.64319e-1-1.583e-3*x1)*sx9+(8.2222e-2-6.833e-3*x1)*cx9+ X 3.6017e-2*s2x9-3.019e-3*c2x9+8.122e-3*sin(x6); X *dml = degrad(*dml); X X dp = 1.20303e-1*sx9+6.197e-3*s2x9+(1.9472e-2-9.47e-4*x1)*cx9; X *dm = *dml-(degrad(dp)/s); X X *ds = (163*x1-3349)*sx9+20981*cx9+1311*c2x9; X *ds *= 1e-7; X X *da = -3.825e-3*cx9; X X *dl = (1.0122e-2-9.88e-4*x1)*sin(x4+x11)+ X (-3.8581e-2+(2.031e-3-1.91e-3*x1)*x1)*cos(x4+x11)+ X (3.4964e-2-(1.038e-3-8.68e-4*x1)*x1)*cos(2*x4+x11)+ X 5.594e-3*sin(x4+3*x12)-1.4808e-2*sin(x10)- X 5.794e-3*sin(x11)+2.347e-3*cos(x11)+9.872e-3*sin(x12)+ X 8.803e-3*sin(2*x12)-4.308e-3*sin(3*x12); X X sx11 = sin(x11); X cx11 = cos(x11); X sx4 = sin(x4); X cx4 = cos(x4); X s2x4 = sin(2*x4); X c2x4 = cos(2*x4); X *dhl = (4.58e-4*sx11-6.42e-4*cx11-5.17e-4*cos(4*x12))*sx4- X (3.47e-4*sx11+8.53e-4*cx11+5.17e-4*sin(4*x11))*cx4+ X 4.03e-4*(cos(2*x12)*s2x4+sin(2*x12)*c2x4); X *dhl = degrad(*dhl); X X *dr = -25948+4985*cos(x10)-1230*cx4+3354*cos(x11)+904*cos(2*x12)+ X 894*(cos(x12)-cos(3*x12))+(5795*cx4-1165*sx4+1388*c2x4)*sx11+ X (1351*cx4+5702*sx4+1388*s2x4)*cos(x11); X *dr *= 1e-6; X} X X/* ....neptune */ Xstatic Xp_neptune (t, s, dl, dr, dml, ds, dm, da, dhl) Xdouble t, s; Xdouble *dl, *dr, *dml, *ds, *dm, *da, *dhl; X{ X double dp; X double x1, x2, x3, x4, x5, x6; X double x8, x9, x10, x11, x12; X double sx8, cx8; X double sx9, cx9, s2x9, c2x9; X double s2x12, c2x12; X X aux_jsun (t, &x1, &x2, &x3, &x4, &x5, &x6); X X x8 = mod2PI(1.46205+3.81337*t); X x9 = 2*x8-x4; X sx9 = sin(x9); X cx9 = cos(x9); X s2x9 = sin(2*x9); X c2x9 = cos(2*x9); X X x10 = x8-x2; X x11 = x8-x3; X x12 = x8-x4; X X *dml = (1.089e-3*x1-5.89833e-1)*sx9+(4.658e-3*x1-5.6094e-2)*cx9- X 2.4286e-2*s2x9; X *dml = degrad(*dml); X X dp = 2.4039e-2*sx9-2.5303e-2*cx9+6.206e-3*s2x9-5.992e-3*c2x9; X X *dm = *dml-(degrad(dp)/s); X X *ds = 4389*sx9+1129*s2x9+4262*cx9+1089*c2x9; X *ds *= 1e-7; X X *da = 8189*cx9-817*sx9+781*c2x9; X *da *= 1e-6; X X s2x12 = sin(2*x12); X c2x12 = cos(2*x12); X sx8 = sin(x8); X cx8 = cos(x8); X *dl = -9.556e-3*sin(x10)-5.178e-3*sin(x11)+2.572e-3*s2x12- X 2.972e-3*c2x12*sx8-2.833e-3*s2x12*cx8; X X *dhl = 3.36e-4*c2x12*sx8+3.64e-4*s2x12*cx8; X *dhl = degrad(*dhl); X X *dr = -40596+4992*cos(x10)+2744*cos(x11)+2044*cos(x12)+1051*c2x12; X *dr *= 1e-6; X} X END_OF_FILE if test 17647 -ne `wc -c <'plans.c'`; then echo shar: \"'plans.c'\" unpacked with wrong size! fi # end of 'plans.c' fi if test -f 'watch.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'watch.c'\" else echo shar: Extracting \"'watch.c'\" \(11959 characters\) sed "s/^X//" >'watch.c' <<'END_OF_FILE' X/* these functions allow you to watch the sky or the solar system via a X * simple character-graphics representation on the screen. X * the interaction starts by using the current time. then control with X * END returns to table form; or X * RETURN advances time by one StpSz; or X * h advances once by 1 hour; or X * d advances once by 24 hours (1 day); or X * w advances once by 7 days (1 week); or X * any other key free runs by StpSz until any key is hit. X */ X X#include <stdio.h> X#include <math.h> X#include "astro.h" X#include "circum.h" X#include "screen.h" X X#define SSZCOL 1 /* column to show solar system z coords */ X X#define DOMESKY 0 /* flags for watch_sky() */ X#define ALTAZSKY 1 /* flags for watch_sky() */ X X#define SKYACC 3600. /* desired sky plot accuracy, in arc seconds */ X#define SSACC 3600. /* desired solar system plot accuracy, in arc secs */ X X/* macros to convert row(col) in range 1..NR(1..NC) to fraction in range 0..1 */ X#define r2fr(r) (((r)-1)/(NR-1)) X#define c2fc(c) (((c)-1)/(NC-1)) X#define fr2r(fr) ((int)((fr)*(NR-1)+.5)+1) X#define fc2c(fc) ((int)((fc)*(NC-1)+.5)+1) X X/* single-character tag for each body. X * order must match the #defines in astro.h and screen.h additions. X */ Xstatic char body_tags[] = "evmjsunpSMxy"; X X/* multiple and single loop prompts */ Xstatic char frprompt[] = "Running... press any key to stop."; Xstatic char qprompt[] = X"q to quit, RETURN/h/d/w to step by StpSz/hr/day/wk, or any other to freerun"; X X/* used to locate, record and then erase last plotted chars */ Xtypedef struct { X double l_fr, l_fc; /* 2d coords as 0..1 (lower left corner is [0,0]) */ X int l_r, l_c; /* screen 2d coords (upper left corner is [1,1]) */ X char l_tag; /* char to use to print on screen */ X} LastDraw; X Xstatic int trails; /* !0 if want to leave trails */ X Xwatch (np, tminc, wbodies) XNow *np; /* time now and on each step */ Xdouble tminc; /* hrs to increment time by each step */ Xint wbodies; /* each bit is !=0 if want that body */ X{ X static char *flds[4] = { X "Sky dome", "Alt/az sky", "Solar system" X }; X static int fn; /* begin with 0, then remember for next time */ X int didone = 0; X X while (1) { X int nf; X flds[3] = trails ? "Leave trails" : "No trails"; X if ((nf = popup (flds, fn, 4)) < 0) X break; X fn = nf; X switch (nf) { X case 0: watch_sky (DOMESKY, np, tminc, wbodies); didone = 1; break; X case 1: watch_sky (ALTAZSKY, np, tminc, wbodies); didone = 1; break; X case 2: watch_solarsystem (np, tminc, wbodies); didone = 1; break; X case 3: trails ^= 1; break; X } X } X X if (didone) X redraw_screen(2); X} X X/* full alt/az or dome sky view (like the popular astro mags). X * alt/az: north is at left and right of screen, south at center. X * 0 elevation is at bottom of screen, zenith at the top. X * dome: east is left, north is up. X */ Xstatic Xwatch_sky (style, np, tminc, wbodies) Xint style; /* DOMESKY or ALTAZSKY */ XNow *np; /* time now and on each step */ Xdouble tminc; /* hrs to increment time by each step */ Xint wbodies; /* each bit is !=0 if want */ X{ X static char east[] = "East"; X static char west[] = "West"; X static char north[] = "North"; X static char south[] = "South"; X double tminc0 = tminc; /* remember the original */ X /* two draw buffers so we can leave old up while calc new then X * erase and draw in one quick operation. always calc new in newp X * buffer and erase previous from lastp. buffers alternate roles. X */ X LastDraw ld0[NOBJ], ld1[NOBJ], *lp, *lastp = ld0, *newp = ld1; X int nlast = 0, nnew; X int once = 1; X double lmjd, tmp; X Sky s; X int p; X X /* clear screen and put up the permanent labels */ X c_erase(); X if (style == DOMESKY) { X f_string (fr2r(.5), fc2c(.5-.5/ASPECT)-7, "East |"); X f_char (fr2r(.5+.5*.707), fc2c(.5-.5*.707/ASPECT)-1, '\\'); X f_string (fr2r(1.), fc2c(.5)-2, south); X f_char (fr2r(.5+.5*.707), fc2c(.5+.5*.707/ASPECT)+1, '/'); X f_string (fr2r(.5), fc2c(.5+.5/ASPECT)+1, "| West"); X f_char (fr2r(.5-.5*.707), fc2c(.5+.5*.707/ASPECT)+1, '\\'); X f_string (2, NC/2-2, north); X f_char (fr2r(.5-.5*.707), fc2c(.5-.5*.707/ASPECT)-1, '/'); X } else { X f_string (NR, 1, north); X f_string (NR, NC/4, east); X f_string (NR, NC/2, south); X f_string (NR, 3*NC/4, west); X f_string (NR, NC-5, north); /* -1 more to avoid scrolling */ X f_string (2, NC/2-3, "Zenith"); X } X f_string (2, 1, tznm); X f_string (3, 1, "LST"); X X while (1) { X if (once) X print_updating(); X X /* calculate desired stuff into newp[] */ X nnew = 0; X for (p = nxtbody(-1); p != -1; p = nxtbody(p)) X if (wbodies & (1<<p)) { X (void) body_cir (p, SKYACC, np, &s); X if (s.s_alt >= 0) { X LastDraw *lnp = newp + nnew; X if (style == DOMESKY) { X tmp = 0.5 - s.s_alt/PI; X lnp->l_fr = 0.5 - tmp*cos(s.s_az); X lnp->l_fc = 0.5 - tmp*sin(s.s_az)/ASPECT; X } else { X lnp->l_fr = 1.0 - s.s_alt/(PI/2); X lnp->l_fc = s.s_az/(2*PI); X } X lnp->l_tag = body_tags[p]; X nnew++; X } X } X set_screencoords (newp, nnew); X X /* unless we want trails, X * erase any previous tags (in same order as written) from lastp[]. X */ X if (!trails) X for (lp = lastp; --nlast >= 0; lp++) X f_char (lp->l_r, lp->l_c, ' '); X X /* print LOCAL time and date we will be using */ X lmjd = mjd - tz/24.0; X f_time (2, 5, mjd_hr(lmjd)); X f_date (2, 14, mjd_day(lmjd)); X now_lst (np, &tmp); X f_time (3, 5, tmp); X X /* now draw new stuff from newp[] */ X for (lp = newp; lp < newp + nnew; lp++) X f_char (lp->l_r, lp->l_c, lp->l_tag); X X /* swap new and last roles and save new count */ X if (newp == ld0) X newp = ld1, lastp = ld0; X else X newp = ld0, lastp = ld1; X nlast = nnew; X X if (!once) X slp_sync(); X X if (once || (chk_char()==0 && read_char()!=0)) { X if (readwcmd (tminc0, &tminc, &once) < 0) X break; X } X X /* advance time */ X inc_mjd (np, tminc); X } X} X X/* solar system view, "down from the top", first point of aries to the right. X * always include earth. X */ Xstatic Xwatch_solarsystem (np, tminc, wbodies) XNow *np; /* time now and on each step */ Xdouble tminc; /* hrs to increment time by each step */ Xint wbodies; X{ X /* max au of each planet from sun; in astro.h #defines order */ X static double auscale[] = {.38, .75, 1.7, 5.2, 11., 20., 31., 50.}; X double tminc0 = tminc; /* remember the original */ X /* two draw buffers so we can leave old up while calc new then X * erase and draw in one quick operation. always calc new in newp X * buffer and erase previous from lastp. buffers alternate roles. X */ X LastDraw ld0[2*NOBJ], ld1[2*NOBJ], *lp, *lastp = ld0, *newp = ld1; X int nlast = 0, nnew; X int once = 1; X double lmjd; X double scale; X Sky s; X int p; X X /* set screen scale: largest au we will have to plot. X * never make it less than 1 au since we always show earth. X */ X scale = 1.0; X for (p = MARS; p <= PLUTO; p++) X if ((wbodies & (1<<p)) && auscale[p] > scale) X scale = auscale[p]; X X /* clear screen and put up the permanent labels */ X c_erase(); X f_string (2, 1, tznm); X X while (1) { X if (once) X print_updating(); X X /* calculate desired stuff into newp[]. X * fake a sun at center and add earth first. X * (we get earth's loc when ask for sun) X */ X nnew = 0; X set_ss (newp+nnew, 0.0, 0.0, 0.0, 'S'); X nnew += 2; X (void) body_cir (SUN, SSACC, np, &s); X set_ss (newp+nnew, s.s_edist/scale, s.s_hlong, 0.0, 'E'); X nnew += 2; X for (p = MERCURY; p <= PLUTO; p++) X if (p != MOON && (wbodies & (1<<p))) { X (void) body_cir (p, SSACC, np, &s); X set_ss (newp+nnew, s.s_sdist/scale, s.s_hlong, s.s_hlat, X body_tags[p]); X nnew += 2; X } X for (p = OBJX; p != -1; p = (p == OBJX) ? OBJY : -1) X if (wbodies & (1<<p)) { X (void) body_cir (p, SSACC, np, &s); X if (s.s_hlong != NOHELIO && s.s_sdist <= scale) { X set_ss (newp+nnew, s.s_sdist/scale, s.s_hlong, s.s_hlat, X body_tags[p]); X nnew += 2; X } X } X X set_screencoords (newp, nnew); X X /* unless we want trails, X * erase any previous tags (in same order as written) from lastp[]. X */ X if (!trails) X for (lp = lastp; --nlast >= 0; lp++) X safe_f_char (lp->l_r, lp->l_c, ' '); X X /* print LOCAL time and date we will be using */ X lmjd = mjd - tz/24.0; X f_time (2, 5, mjd_hr(lmjd)); X f_date (2, 14, mjd_day(lmjd)); X X /* now draw new stuff from newp[] */ X for (lp = newp; lp < newp + nnew; lp++) X safe_f_char (lp->l_r, lp->l_c, lp->l_tag); X X /* swap new and last roles and save new count */ X if (newp == ld0) X newp = ld1, lastp = ld0; X else X newp = ld0, lastp = ld1; X nlast = nnew; X X if (!once) X slp_sync(); X X if (once || (chk_char()==0 && read_char()!=0)) { X if (readwcmd (tminc0, &tminc, &once) < 0) X break; X } X X /* advance time */ X inc_mjd (np, tminc); X } X} X X/* fill in two LastDraw solar system entries, X * one for the x/y display, one for the z. X */ Xstatic Xset_ss (lp, dist, lg, lt, tag) XLastDraw *lp; Xdouble dist, lg, lt; /* scaled heliocentric distance, longitude and lat */ Xchar tag; X{ X lp->l_fr = 0.5 - dist*sin(lg)*0.5; X lp->l_fc = 0.5 + dist*cos(lg)*0.5/ASPECT; X lp->l_tag = tag; X lp++; X /* row is to show course helio altitude but since we resolve collisions X * by adjusting columns we can get more detail by smaller variations X * within one column. X */ X lp->l_fr = 0.5 - dist*sin(lt)*0.5; X lp->l_fc = c2fc(SSZCOL) + (1 - lp->l_fr)/NC; X lp->l_tag = tag; X} X X/* given a list of LastDraw structs with their l_{fr,fc} filled in, X * fill in their l_{r,c}. X * TODO: better collision avoidance. X */ Xstatic Xset_screencoords (lp, np) XLastDraw lp[]; Xint np; X{ X LastDraw *lpi; /* the current basis for comparison */ X LastDraw *lpj; /* the sweep over other existing cells */ X int i; /* index of the current basis cell, lpi */ X int j; /* index of sweep cell, lpj */ X int n; /* total cells placed so far (ie, # to check) */ X X /* idea is to place each new item onto the screen. X * after each placement, look for collisions. X * if find a colliding pair, move the one with the greater l_fc to X * the right one cell, then rescan for more collisions. X * this will yield a result that is sorted by columns by l_fc. X * TODO: don't just move to the right, try up too for true 2d adjusts. X */ X for (n = 0; n < np; n++) { X lpi = lp + n; X i = n; X lpi->l_r = fr2r(lpi->l_fr); X lpi->l_c = fc2c(lpi->l_fc); X chk: X for (j = 0; j < n; j++) { X lpj = lp + j; X if (i!=j && lpi->l_r == lpj->l_r && lpi->l_c == lpj->l_c) { X if (lpj->l_fc > lpi->l_fc) { X /* move lpj and use it as basis for checks now */ X lpi = lpj; X i = j; X } X if (++lpi->l_c > NC) X lpi->l_c = 1; X goto chk; X } X } X } X} X X/* since the solar system scaling is only approximate, and doesn't include X * object x/y at all, characters might get mapped off screen. this funtion X * guards against drawing chars off screen. it also moves a char being drawn X * on the lower right corner of the screem left one to avoid scrolling. X */ Xstatic Xsafe_f_char (r, c, tag) Xint r, c; Xchar tag; X{ X if (r >= 1 && r <= NR && c >= 1 && c <= NC) { X if (r == NR && c == NC) X c -= 1; X f_char (r, c, tag); X } X} X X/* see what the op wants to do now and update prompt/times accordingly. X * return -1 if we are finished, else 0. X */ Xstatic int Xreadwcmd (tminc0, tminc, once) Xdouble tminc0; Xdouble *tminc; Xint *once; X{ X f_prompt (qprompt); X X switch (read_char()) { X case END: /* back to table */ X return (-1); X case '\r': /* one StpSz step */ X *tminc = tminc0; X *once = 1; X break; X case 'h': /* one 1-hour step */ X *tminc = 1.0; X *once = 1; X break; X case 'd': /* one 24-hr step */ X *tminc = 24.0; X *once = 1; X break; X case 'w': /* 7 day step */ X *tminc = 7*24.0; X *once = 1; X break; X default: /* free-run */ X *once = 0; X f_prompt (frprompt); X } X return (0); X} END_OF_FILE if test 11959 -ne `wc -c <'watch.c'`; then echo shar: \"'watch.c'\" unpacked with wrong size! fi # end of 'watch.c' fi echo shar: End of archive 4 \(of 6\). cp /dev/null ark4isdone MISSING="" for I in 1 2 3 4 5 6 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 6 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0