home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
EFFO
/
pd8.lzh
/
SRC
/
objx.c
< prev
next >
Wrap
Text File
|
1990-04-13
|
21KB
|
851 lines
/* functions to save the user-definable objects, referred to as "x" and "y".
* this way, once defined, the objects can be quieried for position just like
* the other bodies, with obj_cir().
*/
#include <stdio.h>
#include <math.h>
#include "astro.h"
#include "circum.h"
#include "screen.h"
extern char *strcat(), *strcpy(), *strncpy(), *getenv();
static char *dbfile; /* !0 if set by -d option */
static char dbfdef[] = "ephem.db"; /* default database file name */
/* structures to describe objects of various types.
*/
typedef struct {
double f_ra; /* ra, rads, at given epoch */
double f_dec; /* dec, rads, at given epoch */
double f_mag; /* visual magnitude */
double f_epoch; /* the given epoch, as an mjd */
} ObjF; /* fixed object */
typedef struct {
double e_inc; /* inclination, degrees */
double e_Om; /* longitude of ascending node, degrees */
double e_om; /* argument of perihelion, degress */
double e_a; /* mean distance, aka, semi-maj axis, in AU */
double e_n; /* daily motion, degrees/day */
double e_e; /* eccentricity */
double e_M; /* mean anomaly, ie, degrees from perihelion at... */
double e_cepoch; /* epoch date (M reference), as an mjd */
double e_epoch; /* equinox year (inc/Om/om reference), as an mjd */
double e_H, e_G; /* magnitude model coefficients */
} ObjE; /* object in heliocentric elliptical orbit */
typedef struct {
double p_ep; /* epoch of perihelion, as an mjd */
double p_inc; /* inclination, rads */
double p_qp; /* perihelion distance, AU */
double p_ap; /* argument of perihelion, rads. */
double p_om; /* longitude of ascending node, rads */
double p_epoch; /* reference epoch, as an mjd */
double p_g, p_k; /* magnitude model coefficients */
} ObjP; /* object in heliocentric parabolic trajectory */
typedef struct {
int o_type; /* see flags, below */
int o_on; /* !=0 while object is active */
ObjF o_f;
ObjE o_e;
ObjP o_p;
} Obj;
#define FIXED 0 /* just simple ra/dec object */
#define ELLIPTICAL 1 /* elliptical orbital elements */
#define PARABOLIC 2 /* parabolic " */
static Obj objx;
static Obj objy;
/* run when Objx or y is picked from menu.
* we tell which by the planet code.
* let op define object and turn it on and off.
*/
obj_setup(p)
int p;
{
static char *pr[5] = {
"Fixed", "Elliptical", "Parabolic", "Lookup"
};
int f;
Obj *op;
op = (p == OBJX) ? &objx : &objy;
rechk:
/* start pointing at selection for current object type */
switch (op->o_type) {
case FIXED: f = 0; break;
case ELLIPTICAL: f = 1; break;
case PARABOLIC: f = 2; break;
}
ask:
pr[4] = op->o_on ? "On" : "Off";
switch (f = popup (pr, f, 5)) {
case 0: obj_dfixed(op, (char**)0); goto ask;
case 1: obj_delliptical(op, (char**)0); goto ask;
case 2: obj_dparabolic(op, (char**)0); goto ask;
case 3: obj_filelookup (p, (char *)0); goto rechk;
case 4: op->o_on ^= 1; break;
}
}
/* turn "on" or "off" but don't forget facts about object the object.
*/
obj_on (p)
int p;
{
if (p == OBJX)
objx.o_on = 1;
else
objy.o_on = 1;
}
obj_off (p)
int p;
{
if (p == OBJX)
objx.o_on = 0;
else
objy.o_on = 0;
}
/* return true if object is now on, else 0.
*/
obj_ison(p)
int p;
{
return ((p == OBJX) ? objx.o_on : objy.o_on);
}
/* set an alternate database file name.
* N.B. we assume the storage pointed to by name is permanent.
*/
obj_setdbfilename (name)
char *name;
{
dbfile = name;
}
/* fill in info about object x or y.
* most arguments and conditions are the same as for plans().
* only difference is that mag is already apparent, not absolute magnitude.
* this is called by body_cir() for object x and y just like plans() is called
* for the planets.
*/
obj_cir (jd, p, lpd0, psi0, rp0, rho0, lam, bet, mag)
double jd; /* mjd now */
int p; /* OBJX or OBJY */
double *lpd0; /* heliocentric longitude, or NOHELIO */
double *psi0; /* heliocentric latitude, or 0 if *lpd0 set to NOHELIO */
double *rp0; /* distance from the sun, or 0 */
double *rho0; /* true distance from the Earth, or 0 */
double *lam; /* apparent geocentric ecliptic longitude */
double *bet; /* apparent geocentric ecliptic latitude */
double *mag; /* APPARENT magnitude */
{
Obj *op = (p == OBJX) ? &objx : &objy;
switch (op->o_type) {
case FIXED: {
double xr, xd;
xr = op->o_f.f_ra;
xd = op->o_f.f_dec;
if (op->o_f.f_epoch != jd)
precess (op->o_f.f_epoch, jd, &xr, &xd);
eq_ecl (jd, xr, xd, bet, lam);
*lpd0 = NOHELIO;
*psi0 = *rp0 = *rho0 = 0.0;
*mag = op->o_f.f_mag;
}
break;
case PARABOLIC: {
double inc, ap, om;
double lpd, psi, rp, rho;
double dt;
int pass;
/* two passes to correct lam and bet for light travel time. */
dt = 0.0;
for (pass = 0; pass < 2; pass++) {
reduce_elements (op->o_p.p_epoch, jd-dt, op->o_p.p_inc,
op->o_p.p_ap, op->o_p.p_om, &inc, &ap, &om);
comet (jd-dt, op->o_p.p_ep, inc, ap, op->o_p.p_qp, om,
&lpd, &psi, &rp, &rho, lam, bet);
if (pass == 0) {
*lpd0 = lpd;
*psi0 = psi;
*rp0 = rp;
*rho0 = rho;
}
dt = rho*5.775518e-3; /* au to light-days */
}
*mag = op->o_p.p_g + 5*log10(*rho0) + 2.5*op->o_p.p_k*log10(*rp0);
}
break;
case ELLIPTICAL: {
/* this is basically the same code as pelement() and plans()
* combined and simplified for the special case of osculating
* (unperturbed) elements.
* inputs have been changed to match the Astronomical Almanac.
* we have added reduction of elements using reduce_elements().
*/
double dt, lg, lsn, rsn;
double nu, ea;
double ma, rp, lo, slo, clo;
double inc, psi, spsi, cpsi;
double y, lpd, rpd, ll, rho, sll, cll;
double om; /* arg of perihelion */
double Om; /* long of ascending node. */
double psi_t, Psi_1, Psi_2, beta;
double e;
int pass;
dt = 0;
sunpos (jd, &lsn, &rsn);
lg = lsn + PI;
e = op->o_e.e_e;
for (pass = 0; pass < 2; pass++) {
reduce_elements (op->o_e.e_epoch, jd-dt, degrad(op->o_e.e_inc),
degrad (op->o_e.e_om), degrad (op->o_e.e_Om),
&inc, &om, &Om);
ma = degrad (op->o_e.e_M
+ (jd - op->o_e.e_cepoch - dt) * op->o_e.e_n);
anomaly (ma, e, &nu, &ea);
rp= op->o_e.e_a * (1-e*e) / (1+e*cos(nu));
lo = nu + om;
slo = sin(lo);
clo = cos(lo);
spsi = slo*sin(inc);
y = slo*cos(inc);
psi = asin(spsi);
lpd = atan(y/clo)+Om;
if (clo<0) lpd += PI;
range (&lpd, 2*PI);
cpsi = cos(psi);
rpd = rp*cpsi;
ll = lpd-lg;
rho = sqrt(rsn*rsn+rp*rp-2*rsn*rp*cpsi*cos(ll));
dt = rho*5.775518e-3; /* light travel time, in days */
if (pass == 0) {
*lpd0 = lpd;
*psi0 = psi;
*rp0 = rp;
*rho0 = rho;
}
}
sll = sin(ll);
cll = cos(ll);
*lam = atan(rsn*sll/(rpd-rsn*cll))+lpd;
/* *lam = atan(-1*rpd*sll/(rsn-rpd*cll))+lg+PI; */
range (lam, 2*PI);
*bet = atan(rpd*spsi*sin(*lam-lpd)/(cpsi*rsn*sll));
beta = acos((rp*rp + rho*rho - rsn*rsn)/ (2*rp*rho));
psi_t = exp(log(tan(beta/2.0))*0.63);
Psi_1 = exp(-3.33*psi_t);
psi_t = exp(log(tan(beta/2.0))*1.22);
Psi_2 = exp(-1.87*psi_t);
*mag = op->o_e.e_H + 5.0*log10(rp*rho)
- 2.5*log10((1-op->o_e.e_G)*Psi_1 + op->o_e.e_G*Psi_2);
}
break;
}
}
/* define obj based on the ephem.cfg line, s.
* the "OBJX " or "OBJY " keyword is already skipped and used to set p.
* format: type,[other fields, as per corresponding ObjX typedef]
* N.B. we replace all ',' with '\0' within s IN PLACE.
* return 0 if ok, else print reason why not with f_msg() and return -1.
*/
obj_define (p, s)
int p; /* OBJX or OBJY */
char *s;
{
#define MAXARGS 20
char *av[MAXARGS]; /* point to each field for easy reference */
char c;
int ac;
Obj *op = (p == OBJX) ? &objx : &objy;
/* parse into comma separated fields */
ac = 0;
av[0] = s;
do {
c = *s++;
if (c == ',' || c == '\0') {
s[-1] = '\0';
av[++ac] = s;
}
} while (c);
if (ac < 1) {
f_msg ("No type for OBJX");
return (-1);
}
switch (av[0][0]) {
case 'f':
if (ac != 5) {
f_msg ("Need ra,dec,mag,epoch for \"fixed\" OBJ");
return (-1);
}
obj_dfixed (op, av+1);
break;
case 'p':
if (ac != 9) {
f_msg ("Need ep,inc,ap,qp,om,epoch,abs,lum for \"parabolic\" OBJ");
return (-1);
}
obj_dparabolic (op, av+1);
break;
case 'e':
if (ac != 12) {
f_msg ("Need inc,lan,aop,md,dm,ecc,ma,cep,ep,h,g for \"elliptical\" OBJ");
return (-1);
}
obj_delliptical (op, av+1);
break;
default:
f_msg ("Unknown OBJ type");
return (-1);
}
return (0);
}
/* search through an ephem database file for an entry and use it to define
* either OBJX or OBJY (as set by p).
* if a name, np, is not set then we ask for it.
* if -d was used use it; else if EPHEMDB env set use it, else use default.
*/
obj_filelookup (p, np)
int p; /* OBJX or OBJY */
char *np;
{
FILE *fp;
char *fn;
int nl;
char buf[160];
char name[64];
int found;
/* open the database file */
if (dbfile)
fn = dbfile;
else {
fn = getenv ("EPHEMDB");
if (!fn)
fn = dbfdef;
}
fp = fopen (fn, "r");
#ifdef OSK
if (!fp)
fp = fopen("/dd/sys/ephem.db","r");
#endif
if (!fp) {
sprintf (buf, "Can not open database file %s", fn);
f_msg(buf);
return;
}
/* set up object name in name with a trailing ',' */
if (np) {
(void) strncpy (name, np, sizeof(name)-2);
name[sizeof(name)-2] = '\0'; /* insure trailing '\0' */
} else {
f_prompt ("Object name: ");
if (read_line (name, sizeof(name)-2) <= 0)
return;
}
(void) strcat (name, ",");
/* search for line beginning with name followed by comma.
* then rest of line is the info.
*/
nl = strlen (name);
found = 0;
while (fgets (buf, sizeof(buf), fp))
if (strncmp (name, buf, nl) == 0) {
found = 1;
break;
}
fclose (fp);
if (found)
(void) obj_define (p, buf+nl);
else {
sprintf (buf, "%s not found", name);
f_msg (buf);
}
}
/* define a fixed object.
* args in av, in order, are ra, dec, magnitude and reference epoch.
* if av then it is a list of strings to use for each parameter, else must
* ask for each. the av option is for cracking the ephem.cfg line.
* if asking show current settings and leave unchanged if hit RETURN.
* END aborts without making any more changes.
* o_type is set to FIXED.
* N.B. we don't error check av in any way, not even for length.
*/
static
obj_dfixed (op, av)
Obj *op;
char *av[];
{
char buf[NC];
char *bp;
int sts;
op->o_type = FIXED;
if (av) {
bp = av[0];
sts = 1;
} else {
static char p[] = "RA (h:m:s): (";
f_prompt (p);
f_ra (R_PROMPT, C_PROMPT+sizeof(p)-1, op->o_f.f_ra);
printf (") ");
sts = read_line (buf, 8+1);
if (sts < 0)
return;
bp = buf;
}
if (sts > 0) {
int h, m, s;
f_dec_sexsign (radhr(op->o_f.f_ra), &h, &m, &s);
f_sscansex (bp, &h, &m, &s);
sex_dec (h, m, s, &op->o_f.f_ra);
op->o_f.f_ra = hrrad(op->o_f.f_ra);
}
if (av) {
bp = av[1];
sts = 1;
} else {
static char p[] = "Dec (d:m:s): (";
f_prompt (p);
f_angle (R_PROMPT, C_PROMPT+sizeof(p)-1, op->o_f.f_dec);
printf (") ");
sts = read_line (buf, 9+1);
if (sts < 0)
return;
bp = buf;
}
if (sts > 0) {
int dg, m, s;
f_dec_sexsign (raddeg(op->o_f.f_dec), &dg, &m, &s);
f_sscansex (bp, &dg, &m, &s);
sex_dec (dg, m, s, &op->o_f.f_dec);
op->o_f.f_dec = degrad(op->o_f.f_dec);
}
if (av) {
bp = av[2];
sts = 1;
} else {
static char p[] = "Magnitude: ";
f_prompt (p);
f_double (R_PROMPT, C_PROMPT+sizeof(p), "(%g) ", op->o_f.f_mag);
sts = read_line (buf, 8+1);
if (sts < 0)
return;
bp = buf;
}
if (sts > 0)
op->o_f.f_mag = atof (bp);
if (av) {
bp = av[3];
sts = 1;
} else {
static char p[] = "Reference epoch (UT Date, m/d.d/y or year.d): ";
double y;
f_prompt (p);
mjd_year (op->o_f.f_epoch, &y);
printf ("(%g) ", y);
sts = read_line (buf, 20);
if (sts < 0)
return;
bp = buf;
}
if (sts > 0)
crack_year (bp, &op->o_f.f_epoch);
}
/* define an object in an elliptical heliocentric orbit.
* 11 args in av, in order, are inclination, longitude of ascending node,
* argument of perihelion, mean distance (aka semi-major axis), daily
* motion, eccentricity, mean anomaly (ie, degrees from perihelion),
* epoch date (ie, time of the mean anomaly value), equinox year
* (ie, time of inc/lon/aop) absolute visual magnitude (H) and magnitude
* slope parameter (G).
* if av then it is a list of strings to use for each parameter, else must
* ask for each. the av option is for cracking the ephem.cfg line.
* if asking show current settings and leave unchanged if hit RETURN.
* END aborts without making any more changes.
* o_type is set to ELLIPTICAL.
* N.B. we don't error check av in any way, not even for length.
*/
static
obj_delliptical(op, av)
Obj *op;
char *av[];
{
char buf[NC];
char *bp;
int sts;
op->o_type = ELLIPTICAL;
if (av) {
bp = av[0];
sts = 1;
} else {
static char p[] = "Inclination (degs):";
f_prompt (p);
f_double (R_PROMPT, C_PROMPT+sizeof(p), "(%g) ", op->o_e.e_inc);
sts = read_line (buf, 8+1);
if (sts < 0)
return;
bp = buf;
}
if (sts > 0)
op->o_e.e_inc = atof(bp);
if (av) {
bp = av[1];
sts = 1;
} else {
static char p[] = "Longitude of ascending node (degs):";
f_prompt (p);
f_double (R_PROMPT, C_PROMPT+sizeof(p), "(%g) ", op->o_e.e_Om);
sts = read_line (buf, 8+1);
if (sts < 0)
return;
bp = buf;
}
if (sts > 0)
op->o_e.e_Om = atof(bp);
if (av) {
bp = av[2];
sts = 1;
} else {
static char p[] = "Argument of Perihelion (degs):";
f_prompt (p);
f_double (R_PROMPT, C_PROMPT+sizeof(p), "(%g) ", op->o_e.e_om);
sts = read_line (buf, 8+1);
if (sts < 0)
return;
bp = buf;
}
if (sts > 0)
op->o_e.e_om = atof(bp);
if (av) {
bp = av[3];
sts = 1;
} else {
static char p[] = "Mean distance (AU):";
f_prompt (p);
f_double (R_PROMPT, C_PROMPT+sizeof(p), "(%g) ", op->o_e.e_a);
sts = read_line (buf, 8+1);
if (sts < 0)
return;
bp = buf;
}
if (sts > 0)
op->o_e.e_a = atof(bp);
if (av) {
bp = av[4];
sts = 1;
} else {
static char p[] = "Daily motion (degs/day):";
f_prompt (p);
f_double (R_PROMPT, C_PROMPT+sizeof(p), "(%g) ", op->o_e.e_n);
sts = read_line (buf, 8+1);
if (sts < 0)
return;
bp = buf;
}
if (sts > 0)
op->o_e.e_n = atof(bp);
if (av) {
bp = av[5];
sts = 1;
} else {
static char p[] = "Eccentricity:";
f_prompt (p);
f_double (R_PROMPT, C_PROMPT+sizeof(p), "(%g) ", op->o_e.e_e);
sts = read_line (buf, 8+1);
if (sts < 0)
return;
bp = buf;
}
if (sts > 0)
op->o_e.e_e = atof(bp);
if (av) {
bp = av[6];
sts = 1;
} else {
static char p[] = "Mean anomaly (degs):";
f_prompt (p);
f_double (R_PROMPT, C_PROMPT+sizeof(p), "(%g) ", op->o_e.e_M);
sts = read_line (buf, 8+1);
if (sts < 0)
return;
bp = buf;
}
if (sts > 0)
op->o_e.e_M = atof(bp);
if (av) {
bp = av[7];
sts = 1;
} else {
static char p[] =
"Epoch date (UT Date, m/d.d/y or year.d): ";
int m, y;
double d;
f_prompt (p);
mjd_cal (op->o_e.e_cepoch, &m, &d, &y);
printf ("(%d/%g/%d) ", m, d, y);
sts = read_line (buf, 20);
if (sts < 0)
return;
bp = buf;
}
if (sts > 0)
crack_year (bp, &op->o_e.e_cepoch);
if (av) {
bp = av[8];
sts = 1;
} else {
static char p[] = "Equinox year (UT Date, m/d.d/y or year.d): ";
double y;
f_prompt (p);
mjd_year (op->o_e.e_epoch, &y);
printf ("(%g) ", y);
sts = read_line (buf, 20);
if (sts < 0)
return;
bp = buf;
}
if (sts > 0)
crack_year (bp, &op->o_e.e_epoch);
if (av) {
bp = av[9];
sts = 1;
} else {
static char p[] = "Absolute magnitude (H):";
f_prompt (p);
f_double (R_PROMPT, C_PROMPT+sizeof(p), "(%g) ", op->o_e.e_H);
sts = read_line (buf, 8+1);
if (sts < 0)
return;
bp = buf;
}
if (sts > 0)
op->o_e.e_H = atof(bp);
if (av) {
bp = av[10];
sts = 1;
} else {
static char p[] = "Magnitude slope parameter (G):";
f_prompt (p);
f_double (R_PROMPT, C_PROMPT+sizeof(p), "(%g) ", op->o_e.e_G);
sts = read_line (buf, 8+1);
if (sts < 0)
return;
bp = buf;
}
if (sts > 0)
op->o_e.e_G = atof(bp);
}
/* define an object in heliocentric parabolic orbit.
* 10 args in av, in order, are epoch of perihelion, inclination, argument of
* perihelion, perihelion distance, longitude of ascending node, reference
* epoch, absolute magnitude and luminosity index.
* if av then it is a list of strings to use for each parameter, else must
* ask for each. the av option is for cracking the ephem.cfg line.
* if asking show current settings and leave unchanged if hit RETURN.
* END aborts without making any more changes.
* o_type is set to PARABOLIC.
* N.B. we don't error check av in any way, not even for length.
*/
static
obj_dparabolic(op, av)
Obj *op;
char *av[];
{
char buf[NC];
char *bp;
int sts;
op->o_type = PARABOLIC;
if (av) {
bp = av[0];
sts = 1;
} else {
static char p[] =
"Epoch of perihelion (UT Date, m/d.d/y or year.d): ";
int m, y;
double d;
f_prompt (p);
mjd_cal (op->o_p.p_ep, &m, &d, &y);
printf ("(%d/%g/%d) ", m, d, y);
sts = read_line (buf, 20);
if (sts < 0)
return;
bp = buf;
}
if (sts > 0)
crack_year (bp, &op->o_p.p_ep);
if (av) {
bp = av[1];
sts = 1;
} else {
static char p[] = "Inclination (degs):";
f_prompt (p);
f_double(R_PROMPT,C_PROMPT+sizeof(p),"(%g) ",raddeg(op->o_p.p_inc));
sts = read_line (buf, 8+1);
if (sts < 0)
return;
bp = buf;
}
if (sts > 0)
op->o_p.p_inc = degrad(atof(bp));
if (av) {
bp = av[2];
sts = 1;
} else {
static char p[] = "Argument of perihelion (degs):";
f_prompt (p);
f_double(R_PROMPT,C_PROMPT+sizeof(p),"(%g) ",raddeg(op->o_p.p_ap));
sts = read_line (buf, 8+1);
if (sts < 0)
return;
bp = buf;
}
if (sts > 0)
op->o_p.p_ap = degrad(atof(bp));
if (av) {
bp = av[3];
sts = 1;
} else {
static char p[] = "Perihelion distance (AU):";
f_prompt (p);
f_double (R_PROMPT, C_PROMPT+sizeof(p), "(%g) ", op->o_p.p_qp);
sts = read_line (buf, 8+1);
if (sts < 0)
return;
bp = buf;
}
if (sts > 0)
op->o_p.p_qp = atof(bp);
if (av) {
bp = av[4];
sts = 1;
} else {
static char p[] = "Longitude of ascending node (degs):";
f_prompt (p);
f_double(R_PROMPT,C_PROMPT+sizeof(p),"(%g) ",raddeg(op->o_p.p_om));
sts = read_line (buf, 8+1);
if (sts < 0)
return;
bp = buf;
}
if (sts > 0)
op->o_p.p_om = degrad(atof(bp));
if (av) {
bp = av[5];
sts = 1;
} else {
static char p[] = "Reference epoch (UT Date, m/d.d/y or year.d): ";
double y;
f_prompt (p);
mjd_year (op->o_p.p_epoch, &y);
printf ("(%g) ", y);
sts = read_line (buf, 20);
if (sts < 0)
return;
bp = buf;
}
if (sts > 0)
crack_year (bp, &op->o_p.p_epoch);
if (av) {
bp = av[6];
sts = 1;
} else {
static char p[] = "Absolute magnitude (g):";
f_prompt (p);
f_double (R_PROMPT, C_PROMPT+sizeof(p), "(%g) ", op->o_p.p_g);
sts = read_line (buf, 8+1);
if (sts < 0)
return;
bp = buf;
}
if (sts > 0)
op->o_p.p_g = atof(bp);
if (av) {
bp = av[7];
sts = 1;
} else {
static char p[] = "Luminosity index (kappa):";
f_prompt (p);
f_double (R_PROMPT, C_PROMPT+sizeof(p), "(%g) ", op->o_p.p_k);
sts = read_line (buf, 8+1);
if (sts < 0)
return;
bp = buf;
}
if (sts > 0)
op->o_p.p_k = atof(bp);
}
/* given either a decimal year (xxxx. something) or a calendar (x/x/x)
* convert it to an mjd and store it at *p;
*/
static
crack_year (bp, p)
char *bp;
double *p;
{
if (decimal_year(bp)) {
double y = atof (bp);
year_mjd (y, p);
} else {
int m, y;
double d;
mjd_cal (*p, &m, &d, &y); /* init with current */
f_sscandate (bp, &m, &d, &y);
cal_mjd (m, d, y, p);
}
}