home *** CD-ROM | disk | FTP | other *** search
- /* find rise and set circumstances, ie, riset_cir() and related functions. */
-
- #include <stdio.h>
- #include <math.h>
- #if defined(__STDC__)
- #include <stdlib.h>
- #endif
- #include "astro.h"
- #include "circum.h"
-
- #if defined(__STDC__) || defined(__cplusplus)
- #define P_(s) s
- #else
- #define P_(s) ()
- #endif
-
- extern double mjd_day P_((double jd));
- extern int obj_cir P_((Now *np, Obj *op));
- extern void now_lst P_((Now *np, double *lst));
- extern void range P_((double *v, double r));
- extern void refract P_((double pr, double tr, double ta, double *aa));
- extern void riset P_((double ra, double dec, double lati, double dis, double *lstr, double *lsts, double *azr, double *azs, int *status));
- extern void riset_cir P_((Now *np, Obj *op, double dis, RiseSet *rp));
- extern void ta_par P_((double tha, double tdec, double phi, double ht, double ehp, double *aha, double *adec));
- extern void unrefract P_((double pr, double tr, double aa, double *ta));
-
- void riset_cir P_((Now *np, Obj *op, double dis, RiseSet *rp));
- void twilight_cir P_((Now *np, double dis, double *dawn, double *dusk, int *status));
- static void stationary_riset P_((Obj *op, Now *np, double dis, double *lstr, double *lsts, double *lstt, double *azr, double *azs, double *altt, int *status));
- static void transit P_((double r, double d, Now *np, double *lstt, double *altt));
-
- #undef P_
-
-
- #define TMACC (15./3600.) /* convergence accuracy, hours */
-
- /* find where and when an object, op, will rise and set and
- * it's transit circumstances. all times are local, angles rads e of n.
- * dis is the angle down from an ideal horizon, in rads (see riset()).
- */
- void
- riset_cir (np, op, dis, rp)
- Now *np;
- Obj *op;
- double dis;
- RiseSet *rp;
- {
- #define MAXPASSES 6
- double lstr, lsts, lstt; /* local sidereal times of rising/setting */
- double lnoon; /* mjd of local noon */
- double x; /* discarded tmp value */
- Now n; /* copy to move time around */
- Obj o; /* copy to get circumstances at n */
- double lst; /* lst at local noon */
- double diff, lastdiff; /* iterative improvement to mjd0 */
- int pass;
- int rss;
-
- /* find mjd of local noon -- all iterations start then */
- lnoon = mjd_day(mjd - tz/24.0) + (12.0 + tz)/24.0;
-
- /* work with local copies so we can move the time around */
- n = *np;
- o = *op;
-
- /* assume no problems initially */
- rp->rs_flags = 0;
-
- /* first approximation is to find rise/set times of a fixed object
- * at the current epoch in its position at local noon.
- */
- n.n_mjd = lnoon;
- n.n_epoch = EOD;
- now_lst (&n, &lst); /* lst at local noon */
- stationary_riset (&o, &n, dis, &lstr, &lsts, &lstt, &x, &x, &x, &rss);
-
- chkrss: /* come here to check rss status and control next step */
- switch (rss) {
- case 0: break;
- case 1: rp->rs_flags = RS_NEVERUP; return;
- case -1: rp->rs_flags = RS_CIRCUMPOLAR; goto dotransit;
- default: rp->rs_flags = RS_ERROR; return;
- }
-
- /* find a better approximation to the rising circumstances based on
- * more passes, each using a "fixed" object at the location at
- * previous approximation of the rise time.
- */
- lastdiff = 1000.0;
- for (pass = 1; pass < MAXPASSES; pass++) {
- diff = (lstr - lst)*SIDRATE; /* next guess at rise time wrt noon */
- if (diff > 12.0)
- diff -= 24.0*SIDRATE; /* not tomorrow, today */
- else if (diff < -12.0)
- diff += 24.0*SIDRATE; /* not yesterday, today */
- n.n_mjd = lnoon + diff/24.0; /* next guess at mjd of rise */
- stationary_riset (&o, &n, dis, &lstr, &x, &x, &rp->rs_riseaz,
- &x, &x, &rss);
- if (rss != 0) goto chkrss;
- if (fabs (diff - lastdiff) < TMACC)
- break;
- lastdiff = diff;
- }
- if (pass == MAXPASSES)
- rp->rs_flags |= RS_NORISE; /* didn't converge - no rise today */
- else {
- rp->rs_risetm = 12.0 + diff;
- if (!is_planet(op, MOON) &&
- (rp->rs_risetm <= 24.0*(1.0-SIDRATE)
- || rp->rs_risetm >= 24.0*SIDRATE))
- rp->rs_flags |= RS_2RISES;
- }
-
- /* find a better approximation to the setting circumstances based on
- * more passes, each using a "fixed" object at the location at
- * previous approximation of the set time.
- */
- lastdiff = 1000.0;
- for (pass = 1; pass < MAXPASSES; pass++) {
- diff = (lsts - lst)*SIDRATE; /* next guess at set time wrt noon */
- if (diff > 12.0)
- diff -= 24.0*SIDRATE; /* not tomorrow, today */
- else if (diff < -12.0)
- diff += 24.0*SIDRATE; /* not yesterday, today */
- n.n_mjd = lnoon + diff/24.0; /* next guess at mjd of set */
- stationary_riset (&o, &n, dis, &x, &lsts, &x, &x,
- &rp->rs_setaz, &x, &rss);
- if (rss != 0) goto chkrss;
- if (fabs (diff - lastdiff) < TMACC)
- break;
- lastdiff = diff;
- }
- if (pass == MAXPASSES)
- rp->rs_flags |= RS_NOSET; /* didn't converge - no set today */
- else {
- rp->rs_settm = 12.0 + diff;
- if (!is_planet(op, MOON) &&
- (rp->rs_settm <= 24.0*(1.0-SIDRATE)
- || rp->rs_settm >= 24.0*SIDRATE))
- rp->rs_flags |= RS_2SETS;
- }
-
- dotransit:
- /* find a better approximation to the transit circumstances based on
- * more passes, each using a "fixed" object at the location at
- * previous approximation of the transit time.
- */
- lastdiff = 1000.0;
- for (pass = 1; pass < MAXPASSES; pass++) {
- diff = (lstt - lst)*SIDRATE; /*next guess at transit time wrt noon*/
- if (diff > 12.0)
- diff -= 24.0*SIDRATE; /* not tomorrow, today */
- else if (diff < -12.0)
- diff += 24.0*SIDRATE; /* not yesterday, today */
- n.n_mjd = lnoon + diff/24.0; /* next guess at mjd of transit */
- stationary_riset (&o, &n, dis, &x, &x, &lstt, &x, &x,
- &rp->rs_tranalt, &rss);
- if (fabs (diff - lastdiff) < TMACC)
- break;
- lastdiff = diff;
- }
- if (pass == MAXPASSES)
- rp->rs_flags |= RS_NOTRANS; /* didn't converge - no transit today */
- else {
- rp->rs_trantm = 12.0 + diff;
- if (!is_planet(op, MOON) &&
- (rp->rs_trantm <= 24.0*(1.0-SIDRATE)
- || rp->rs_trantm >= 24.0*SIDRATE))
- rp->rs_flags |= RS_2TRANS;
- }
- }
-
- /* find local times when sun is dis rads below horizon.
- */
- void
- twilight_cir (np, dis, dawn, dusk, status)
- Now *np;
- double dis;
- double *dawn, *dusk;
- int *status;
- {
- RiseSet rs;
- Obj o;
-
- o.type = PLANET;
- o.pl.code = SUN;
- riset_cir (np, &o, dis, &rs);
- *dawn = rs.rs_risetm;
- *dusk = rs.rs_settm;
- *status = rs.rs_flags;
- }
-
- /* find the local rise/set/transit circumstances of a fixed object, *op.
- * use lp to decide the day and the location circumstances.
- * fill *status is have any problems.
- */
- static void
- stationary_riset (op, np, dis, lstr, lsts, lstt, azr, azs, altt, status)
- Obj *op;
- Now *np;
- double dis;
- double *lstr, *lsts, *lstt;
- double *azr, *azs, *altt;
- int *status;
- {
- /* find object op's topocentric ra/dec at np..
- * (this must include parallax if it's in the solar system).
- */
- if (obj_cir (np, op) < 0) {
- printf ("stationary_riset: can't get object loc\n");
- exit (1);
- }
-
- if (is_ssobj(op)) {
- /* obj_cir() gives geocentric ra/dec; we need to account for
- * parallax in solar system objects to get topocentric ra/dec.
- */
- double tra, tdec;
- double ehp, lst, ha;
- if (is_planet(op, MOON))
- ehp = asin (6378.14/op->s_edist);
- else
- ehp = (2.*6378./146e6)/op->s_edist;
- now_lst (np, &lst);
- ha = hrrad(lst) - op->s_ra;
- ta_par (ha, op->s_dec, lat, elev, ehp, &ha, &tdec);
- tra = hrrad(lst) - ha;
- range (&tra, 2*PI);
- op->s_ra = tra;
- op->s_dec = tdec;
- }
-
- riset (op->s_ra, op->s_dec, lat, dis, lstr, lsts, azr, azs, status);
- transit (op->s_ra, op->s_dec, np, lstt, altt);
- }
-
-
- /* find when and how hi object at (r,d) is when it transits. */
- static void
- transit (r, d, np, lstt, altt)
- double r, d; /* ra and dec, rads */
- Now *np; /* for refraction info */
- double *lstt; /* local sidereal time of transit */
- double *altt; /* local, refracted, altitude at time of transit */
- {
- *lstt = radhr(r);
- *altt = PI/2 - lat + d;
- if (*altt > PI/2)
- *altt = PI - *altt;
- refract (pressure, temp, *altt, altt);
- }
-