home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume19 / xephem / part18 < prev    next >
Encoding:
Text File  |  1993-05-15  |  77.2 KB  |  2,792 lines

  1. Newsgroups: comp.sources.x
  2. From: ecdowney@pobox.cca.cr.rockwell.com (Elwood Downey)
  3. Subject: v19i106:  xephem - astronomical ephemeris program, Part18/21
  4. Message-ID: <1993May10.221306.9578@sparky.imd.sterling.com>
  5. X-Md4-Signature: 2bb8b9ba0ca65d6e5b331f6d6a740967
  6. Date: Mon, 10 May 1993 22:13:06 GMT
  7. Approved: chris@sparky.imd.sterling.com
  8.  
  9. Submitted-by: ecdowney@pobox.cca.cr.rockwell.com (Elwood Downey)
  10. Posting-number: Volume 19, Issue 106
  11. Archive-name: xephem/part18
  12. Environment: X11r4, OSF/Motif
  13. Supersedes: xephem: Volume 16, Issue 112-134
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then feed it
  17. # into a shell via "sh file" or similar.  To overwrite existing files,
  18. # type "sh file -c".
  19. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  20. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  21. # Contents:  circum.c misc.c precess.c preferences.c skyviewmenu.c.3
  22. # Wrapped by chris@nova on Mon May 10 16:41:53 1993
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 18 (of 21)."'
  26. if test -f 'circum.c' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'circum.c'\"
  28. else
  29.   echo shar: Extracting \"'circum.c'\" \(20008 characters\)
  30.   sed "s/^X//" >'circum.c' <<'END_OF_FILE'
  31. X/* given a Now and an Obj with the object definition portion filled in,
  32. X * fill in the sky position (s_*) portions.
  33. X */
  34. X
  35. X#include <stdio.h>
  36. X#include <math.h>
  37. X#if defined(__STDC__)
  38. X#include <stdlib.h>
  39. X#endif
  40. X#include "astro.h"
  41. X#include "circum.h"
  42. X#include "preferences.h"
  43. X
  44. X#if defined(__STDC__) || defined(__cplusplus)
  45. X#define P_(s) s
  46. X#else
  47. X#define P_(s) ()
  48. X#endif
  49. X
  50. Xextern void anomaly P_((double ma, double s, double *nu, double *ea));
  51. Xextern void comet P_((double Mjd, double ep, double inc, double ap, double qp, double om, double *lpd, double *psi, double *rp, double *rho, double *lam, double *bet));
  52. Xextern void ecl_eq P_((double Mjd, double lati, double lngi, double *ra, double *dec));
  53. Xextern void eq_ecl P_((double Mjd, double ra, double dec, double *lati, double *lngi));
  54. Xextern void gk_mag P_((double g, double k, double rp, double rho, double *mp));
  55. Xextern void hadec_aa P_((double lati, double ha, double dec, double *alt, double *az));
  56. Xextern void hg_mag P_((double h, double g, double rp, double rho, double rsn, double *mp));
  57. Xextern void moon P_((double Mjd, double *lam, double *bet, double *hp));
  58. Xextern void now_lst P_((Now *np, double *lst));
  59. Xextern void nutation P_((double Mjd, double *deps, double *dpsi));
  60. Xextern void plans P_((double Mjd, int p, double *lpd0, double *psi0, double *rp0, double *rho0, double *lam, double *bet, double *dia, double *mag));
  61. Xextern void precess P_((double mjd1, double mjd2, double *ra, double *dec));
  62. Xextern void range P_((double *v, double r));
  63. Xextern void reduce_elements P_((double mjd0, double Mjd, double inc0, double ap0, double om0, double *inc, double *ap, double *om));
  64. Xextern void refract P_((double pr, double tr, double ta, double *aa));
  65. Xextern void sunpos P_((double Mjd, double *lsn, double *rsn));
  66. Xextern void ta_par P_((double tha, double tdec, double phi, double ht, double ehp, double *aha, double *adec));
  67. X
  68. Xint obj_cir P_((Now *np, Obj *op));
  69. Xstatic obj_planet P_((Now *np, Obj *op));
  70. Xstatic obj_fixed P_((Now *np, Obj *op));
  71. Xstatic obj_elliptical P_((Now *np, Obj *op));
  72. Xstatic obj_hyperbolic P_((Now *np, Obj *op));
  73. Xstatic obj_parabolic P_((Now *np, Obj *op));
  74. Xstatic sun_cir P_((Now *np, Obj *op));
  75. Xstatic moon_cir P_((Now *np, Obj *op));
  76. Xstatic void cir_sky P_((Now *np, double lpd, double psi, double rp, double rho, double lam, double bet, double lsn, double rsn, Obj *op));
  77. Xstatic void elongation P_((double lam, double bet, double lsn, double *el));
  78. X
  79. X#undef P_
  80. X
  81. X/* given a Now and an Obj, fill in the approprirate s_* fields within Obj.
  82. X * return 0 if all ok, else -1.
  83. X */
  84. Xobj_cir (np, op)
  85. XNow *np;
  86. XObj *op;
  87. X{
  88. X    switch (op->type) {
  89. X    case FIXED:     return (obj_fixed (np, op));
  90. X    case ELLIPTICAL: return (obj_elliptical (np, op));
  91. X    case HYPERBOLIC: return (obj_hyperbolic (np, op));
  92. X    case PARABOLIC:  return (obj_parabolic (np, op));
  93. X    case PLANET:     return (obj_planet (np, op));
  94. X    default:
  95. X        printf ("obj_cir() called with type %d\n", op->type);
  96. X        exit(1);
  97. X        return (-1);    /* just for lint */
  98. X    }
  99. X}
  100. X
  101. Xstatic
  102. Xobj_planet (np, op)
  103. XNow *np;
  104. XObj *op;
  105. X{
  106. X    double lsn, rsn;    /* true geoc lng of sun; dist from sn to earth*/
  107. X    double lpd, psi;    /* heliocentric ecliptic long and lat */
  108. X    double rp;        /* dist from sun */
  109. X    double rho;        /* dist from earth */
  110. X    double lam, bet;    /* geocentric ecliptic long and lat */
  111. X    double dia, mag;    /* angular diameter at 1 AU and magnitude */
  112. X    double f;        /* fractional phase from earth */
  113. X    int p;
  114. X
  115. X    /* validate code and check for a few special cases */
  116. X    p = op->pl.code;
  117. X    if (p < 0 || p > MOON) {
  118. X        printf ("unknown planet code: %d \n", p);
  119. X        exit(1);
  120. X    }
  121. X    else if (p == SUN)
  122. X        return (sun_cir (np, op));
  123. X    else if (p == MOON)
  124. X        return (moon_cir (np, op));
  125. X
  126. X
  127. X    /* find solar ecliptical longitude and distance to sun from earth */
  128. X    sunpos (mjd, &lsn, &rsn);
  129. X
  130. X    /* find helio long/lat; sun/planet and earth/plant dist; ecliptic
  131. X     * long/lat; diameter and mag.
  132. X     */
  133. X    plans(mjd, p, &lpd, &psi, &rp, &rho, &lam, &bet, &dia, &mag);
  134. X
  135. X    /* fill in all of op->s_* stuff except s_size and s_mag */
  136. X    cir_sky (np, lpd, psi, rp, rho, lam, bet, lsn, rsn, op);
  137. X
  138. X    /* compute magnitude and angular size */
  139. X    f = 0.25 * (((rp+rho)*(rp+rho) - rsn*rsn)/(rp*rho));
  140. X    op->s_mag = MAGSCALE * (mag + 5.0*log(rp*rho/sqrt(f))/log(10.0));
  141. X    op->s_size = dia/rho + 0.5;
  142. X
  143. X    return (0);
  144. X}
  145. X
  146. Xstatic
  147. Xobj_fixed (np, op)
  148. XNow *np;
  149. XObj *op;
  150. X{
  151. X    double lsn, rsn;    /* true geoc lng of sun, dist from sn to earth*/
  152. X    double lam, bet;    /* geocentric ecliptic long and lat */
  153. X    double lst;        /* local sidereal time */
  154. X    double ha;        /* local hour angle */
  155. X    double el;        /* elongation */
  156. X    double alt, az;        /* current alt, az */
  157. X    double ra, dec;        /* ra and dec at epoch of date */
  158. X
  159. X    /* set ra/dec to their values at epoch of date */
  160. X    ra = op->f_RA;
  161. X    dec = op->f_dec;
  162. X    precess (op->f_epoch, mjd, &ra, &dec);
  163. X
  164. X    /* set s_ra/dec at desired epoch.  */
  165. X    if (epoch == EOD) {
  166. X        op->s_ra = ra;
  167. X        op->s_dec = dec;
  168. X    } else {
  169. X        /* want a certain epoch -- if it's not what the database is at
  170. X         * we change the original to save time next time assuming the
  171. X         * user is likely to stick with this for a while.
  172. X         */
  173. X        if ((float)epoch != op->f_epoch) {
  174. X        double tra = op->f_RA, tdec = op->f_dec;
  175. X        float tepoch = epoch;    /* compare to float precision */
  176. X        precess (op->f_epoch, tepoch, &tra, &tdec);
  177. X        op->f_epoch = tepoch;
  178. X        op->f_RA = tra;
  179. X        op->f_dec = tdec;
  180. X        }
  181. X        op->s_ra = op->f_RA;
  182. X        op->s_dec = op->f_dec;
  183. X    }
  184. X
  185. X    /* convert equitorial ra/dec to geocentric ecliptic lat/long */
  186. X    eq_ecl (mjd, ra, dec, &bet, &lam);
  187. X
  188. X    /* find solar ecliptical longitude and distance to sun from earth */
  189. X    sunpos (mjd, &lsn, &rsn);
  190. X
  191. X    /* compute elongation from ecliptic long/lat and sun geocentric long */
  192. X    elongation (lam, bet, lsn, &el);
  193. X    el = raddeg(el);
  194. X    op->s_elong = el;
  195. X
  196. X    /* these are really the same fields ...
  197. X    op->s_mag = op->f_mag;
  198. X    op->s_size = op->f_size;
  199. X    */
  200. X
  201. X    /* alt, az: correct for refraction; use eod ra/dec. */
  202. X    now_lst (np, &lst);
  203. X    ha = hrrad(lst) - ra;
  204. X    hadec_aa (lat, ha, dec, &alt, &az);
  205. X    refract (pressure, temp, alt, &alt);
  206. X    op->s_alt = alt;
  207. X    op->s_az = az;
  208. X
  209. X    return (0);
  210. X}
  211. X
  212. X/* compute sky circumstances of an object in heliocentric elliptic orbit at *np.
  213. X */
  214. Xstatic
  215. Xobj_elliptical (np, op)
  216. XNow *np;
  217. XObj *op;
  218. X{
  219. X    double lsn, rsn;    /* true geoc lng of sun; dist from sn to earth*/
  220. X    double dt;        /* light travel time to object */
  221. X    double lg;        /* helio long of earth */
  222. X    double nu, ea;        /* true anomaly and eccentric anomaly */
  223. X    double ma;        /* mean anomaly */
  224. X    double rp;        /* distance from the sun */
  225. X    double lo, slo, clo;    /* angle from ascending node */
  226. X    double inc;        /* inclination */
  227. X    double psi, spsi, cpsi;    /* heliocentric latitude */
  228. X    double lpd;         /* heliocentric longitude */
  229. X    double rho;        /* distance from the Earth */
  230. X    double om;        /* arg of perihelion */
  231. X    double Om;        /* long of ascending node. */
  232. X    double lam;            /* geocentric ecliptic longitude */
  233. X    double bet;            /* geocentric ecliptic latitude */
  234. X    double e;        /* fast eccentricity */
  235. X    double ll, sll, cll;    /* helio angle between object and earth */
  236. X    double mag;        /* magnitude */
  237. X    double rpd;
  238. X    double y;
  239. X    int pass;
  240. X
  241. X    /* find location of earth from sun now */
  242. X    sunpos (mjd, &lsn, &rsn);
  243. X    lg = lsn + PI;
  244. X
  245. X    /* faster access to eccentricty */
  246. X    e = op->e_e;
  247. X
  248. X    /* mean daily motion is optional -- fill in from period if 0 */
  249. X    if (op->e_n == 0.0) {
  250. X        double a = op->e_a;
  251. X        op->e_n = 0.9856076686/sqrt(a*a*a);
  252. X    }
  253. X
  254. X    /* correct for light time by computing position at time mjd, then
  255. X     *   again at mjd-dt, where
  256. X     *   dt = time it takes light to travel earth-object distance.
  257. X     * this is basically the same code as pelement() and plans()
  258. X     *   combined and simplified for the special case of osculating
  259. X     *   (unperturbed) elements. we have added reduction of elements using
  260. X     *   reduce_elements().
  261. X     */
  262. X    dt = 0;
  263. X    for (pass = pref_get(PREF_ALGO)==PREF_ACCURATE ? 0 : 1; pass<2; pass++){
  264. X
  265. X        reduce_elements (op->e_epoch, mjd-dt, degrad(op->e_inc),
  266. X                degrad (op->e_om), degrad (op->e_Om),
  267. X                &inc, &om, &Om);
  268. X
  269. X        ma = degrad (op->e_M + (mjd - op->e_cepoch - dt) * op->e_n);
  270. X        anomaly (ma, e, &nu, &ea);
  271. X        rp = op->e_a * (1-e*e) / (1+e*cos(nu));
  272. X        lo = nu + om;
  273. X        slo = sin(lo);
  274. X        clo = cos(lo);
  275. X        spsi = slo*sin(inc);
  276. X        y = slo*cos(inc);
  277. X        psi = asin(spsi);
  278. X        lpd = atan(y/clo)+Om;
  279. X        if (clo<0) lpd += PI;
  280. X        range (&lpd, 2*PI);
  281. X        cpsi = cos(psi);
  282. X        rpd = rp*cpsi;
  283. X        ll = lpd-lg;
  284. X        rho = sqrt(rsn*rsn+rp*rp-2*rsn*rp*cpsi*cos(ll));
  285. X
  286. X        dt = rho*LTAU/3600.0/24.0;    /* light travel time, in days / AU */
  287. X    }
  288. X
  289. X    /* compute sin and cos of ll */
  290. X    sll = sin(ll);
  291. X    cll = cos(ll);
  292. X
  293. X    /* find geocentric ecliptic longitude and latitude */
  294. X    if (rpd < rsn)
  295. X        lam = atan(-1*rpd*sll/(rsn-rpd*cll))+lg+PI;
  296. X    else
  297. X        lam = atan(rsn*sll/(rpd-rsn*cll))+lpd;
  298. X    range (&lam, 2*PI);
  299. X    bet = atan(rpd*spsi*sin(lam-lpd)/(cpsi*rsn*sll));
  300. X
  301. X    /* fill in all of op->s_* stuff except s_size and s_mag */
  302. X    cir_sky (np, lpd, psi, rp, rho, lam, bet, lsn, rsn, op);
  303. X
  304. X    /* compute magnitude and size */
  305. X    if (op->e_mag.whichm == MAG_HG) {
  306. X        /* the H and G parameters from the Astro. Almanac.
  307. X         */
  308. X        hg_mag (op->e_mag.m1, op->e_mag.m2, rp, rho, rsn, &mag);
  309. X    } else {
  310. X        /* the g/k model of comets */
  311. X        gk_mag (op->e_mag.m1, op->e_mag.m2, rp, rho, &mag);
  312. X    }
  313. X    op->s_mag = mag * MAGSCALE;
  314. X    op->s_size = op->e_size / rho;
  315. X
  316. X    return (0);
  317. X}
  318. X
  319. X/* compute sky circumstances of an object in heliocentric hyperbolic orbit.
  320. X */
  321. Xstatic
  322. Xobj_hyperbolic (np, op)
  323. XNow *np;
  324. XObj *op;
  325. X{
  326. X    double lsn, rsn;    /* true geoc lng of sun; dist from sn to earth*/
  327. X    double dt;        /* light travel time to object */
  328. X    double lg;        /* helio long of earth */
  329. X    double nu, ea;        /* true anomaly and eccentric anomaly */
  330. X    double ma;        /* mean anomaly */
  331. X    double rp;        /* distance from the sun */
  332. X    double lo, slo, clo;    /* angle from ascending node */
  333. X    double inc;        /* inclination */
  334. X    double psi, spsi, cpsi;    /* heliocentric latitude */
  335. X    double lpd;         /* heliocentric longitude */
  336. X    double rho;        /* distance from the Earth */
  337. X    double om;        /* arg of perihelion */
  338. X    double Om;        /* long of ascending node. */
  339. X    double lam;            /* geocentric ecliptic longitude */
  340. X    double bet;            /* geocentric ecliptic latitude */
  341. X    double e;        /* fast eccentricity */
  342. X    double ll, sll, cll;    /* helio angle between object and earth */
  343. X    double n;        /* mean daily motion */
  344. X    double mag;        /* magnitude */
  345. X    double a;        /* mean distance */
  346. X    double rpd;
  347. X    double y;
  348. X    int pass;
  349. X
  350. X    /* find solar ecliptical longitude and distance to sun from earth */
  351. X    sunpos (mjd, &lsn, &rsn);
  352. X
  353. X    lg = lsn + PI;
  354. X    e = op->h_e;
  355. X    a = op->h_qp/(e - 1.0);
  356. X    n = .98563/sqrt(a*a*a);
  357. X
  358. X    /* correct for light time by computing position at time mjd, then
  359. X     *   again at mjd-dt, where
  360. X     *   dt = time it takes light to travel earth-object distance.
  361. X     */
  362. X    dt = 0;
  363. X    for (pass = pref_get(PREF_ALGO)==PREF_ACCURATE ? 0 : 1; pass<2; pass++){
  364. X
  365. X        reduce_elements (op->h_epoch, mjd-dt, degrad(op->h_inc),
  366. X                degrad (op->h_om), degrad (op->h_Om),
  367. X                &inc, &om, &Om);
  368. X
  369. X        ma = degrad ((mjd - op->h_ep - dt) * n);
  370. X        anomaly (ma, e, &nu, &ea);
  371. X        rp = a * (e*e-1.0) / (1.0+e*cos(nu));
  372. X        lo = nu + om;
  373. X        slo = sin(lo);
  374. X        clo = cos(lo);
  375. X        spsi = slo*sin(inc);
  376. X        y = slo*cos(inc);
  377. X        psi = asin(spsi);
  378. X        lpd = atan(y/clo)+Om;
  379. X        if (clo<0) lpd += PI;
  380. X        range (&lpd, 2*PI);
  381. X        cpsi = cos(psi);
  382. X        rpd = rp*cpsi;
  383. X        ll = lpd-lg;
  384. X        rho = sqrt(rsn*rsn+rp*rp-2*rsn*rp*cpsi*cos(ll));
  385. X
  386. X        dt = rho*5.775518e-3;    /* light travel time, in days */
  387. X    }
  388. X
  389. X    /* compute sin and cos of ll */
  390. X    sll = sin(ll);
  391. X    cll = cos(ll);
  392. X
  393. X    /* find geocentric ecliptic longitude and latitude */
  394. X    if (rpd < rsn)
  395. X        lam = atan(-1*rpd*sll/(rsn-rpd*cll))+lg+PI;
  396. X    else
  397. X        lam = atan(rsn*sll/(rpd-rsn*cll))+lpd;
  398. X    range (&lam, 2*PI);
  399. X    bet = atan(rpd*spsi*sin(lam-lpd)/(cpsi*rsn*sll));
  400. X
  401. X    /* fill in all of op->s_* stuff except s_size and s_mag */
  402. X    cir_sky (np, lpd, psi, rp, rho, lam, bet, lsn, rsn, op);
  403. X
  404. X    /* compute magnitude and size */
  405. X    gk_mag (op->h_g, op->h_k, rp, rho, &mag);
  406. X    op->s_mag = mag * MAGSCALE;
  407. X    op->s_size = op->h_size / rho;
  408. X
  409. X    return (0);
  410. X}
  411. X
  412. X/* compute sky circumstances of an object in heliocentric hyperbolic orbit.
  413. X */
  414. Xstatic
  415. Xobj_parabolic (np, op)
  416. XNow *np;
  417. XObj *op;
  418. X{
  419. X    double lsn, rsn;    /* true geoc lng of sun; dist from sn to earth*/
  420. X    double lam;            /* geocentric ecliptic longitude */
  421. X    double bet;            /* geocentric ecliptic latitude */
  422. X    double mag;        /* magnitude */
  423. X    double inc, om, Om;
  424. X    double lpd, psi, rp, rho;
  425. X    double dt;
  426. X    int pass;
  427. X
  428. X    /* find solar ecliptical longitude and distance to sun from earth */
  429. X    sunpos (mjd, &lsn, &rsn);
  430. X
  431. X    /* two passes to correct lam and bet for light travel time.e_ */
  432. X    dt = 0.0;
  433. X    for (pass = pref_get(PREF_ALGO)==PREF_ACCURATE ? 0 : 1; pass<2; pass++){
  434. X        reduce_elements (op->p_epoch, mjd-dt, degrad(op->p_inc),
  435. X        degrad(op->p_om), degrad(op->p_Om), &inc, &om, &Om);
  436. X        comet (mjd-dt, op->p_ep, inc, om, op->p_qp, Om,
  437. X                    &lpd, &psi, &rp, &rho, &lam, &bet);
  438. X        dt = rho*LTAU/3600.0/24.0;    /* light travel time, in days / AU */
  439. X    }
  440. X
  441. X    /* fill in all of op->s_* stuff except s_size and s_mag */
  442. X    cir_sky (np, lpd, psi, rp, rho, lam, bet, lsn, rsn, op);
  443. X
  444. X    /* compute magnitude and size */
  445. X    gk_mag (op->p_g, op->p_k, rp, rho, &mag);
  446. X    op->s_mag = mag * MAGSCALE;
  447. X    op->s_size = op->p_size / rho;
  448. X
  449. X    return (0);
  450. X}
  451. X
  452. X/* find sun's circumstances now.
  453. X */
  454. Xstatic
  455. Xsun_cir (np, op)
  456. XNow *np;
  457. XObj *op;
  458. X{
  459. X    double lsn, rsn;    /* true geoc lng of sun; dist from sn to earth*/
  460. X    double deps, dpsi;    /* nutation on obliquity and longitude */
  461. X    double lst;        /* local sidereal time */
  462. X    double ehp;        /* angular diamter of earth from object */
  463. X    double ha;        /* hour angle */
  464. X    double ra, dec;        /* ra and dec now */
  465. X    double alt, az;        /* alt and az */
  466. X    double dhlong;
  467. X
  468. X    sunpos (mjd, &lsn, &rsn);    /* sun's true ecliptic long and dist */
  469. X    nutation (mjd, &deps, &dpsi);    /* correct for nutation ... */
  470. X    lsn += dpsi;
  471. X    lsn -= degrad(20.4/3600);    /* and aberation */
  472. X
  473. X    op->s_edist = rsn;
  474. X    op->s_sdist = 0.0;
  475. X    op->s_elong = 0.0;
  476. X    op->s_phase = 100.0;
  477. X    op->s_size = raddeg(4.65242e-3/rsn)*3600*2;
  478. X    op->s_mag = MAGSCALE * -26.8;    /* TODO */
  479. X    dhlong = lsn-PI;    /* geo- to helio- centric */
  480. X    range (&dhlong, 2*PI);
  481. X    op->s_hlong = dhlong;
  482. X    op->s_hlat = 0.0;
  483. X
  484. X
  485. X    /* convert geocentric ecliptic lat/long to equitorial ra/dec of date */
  486. X    ecl_eq (mjd, 0.0, lsn, &ra, &dec);
  487. X
  488. X    /* find s_ra/dec at desired epoch */
  489. X    if (epoch == EOD) {
  490. X        op->s_ra = ra;
  491. X        op->s_dec = dec;
  492. X    } else {
  493. X        double tra = ra, tdec = dec;
  494. X        precess (mjd, epoch, &tra, &tdec);
  495. X        op->s_ra = tra;
  496. X        op->s_dec = tdec;
  497. X    }
  498. X
  499. X    /* find alt/az based on unprecessed ra/dec */
  500. X    now_lst (np, &lst);
  501. X    ha = hrrad(lst) - ra;
  502. X    ehp = (2.0 * 6378.0 / 146.0e6) / op->s_edist;
  503. X    ta_par (ha, dec, lat, elev, ehp, &ha, &dec);
  504. X    hadec_aa (lat, ha, dec, &alt, &az);
  505. X    refract (pressure, temp, alt, &alt);
  506. X    op->s_alt = alt;
  507. X    op->s_az = az;
  508. X    return (0);
  509. X}
  510. X
  511. X/* find moon's circumstances now.
  512. X */
  513. Xstatic
  514. Xmoon_cir (np, op)
  515. XNow *np;
  516. XObj *op;
  517. X{
  518. X    double lsn, rsn;    /* true geoc lng of sun; dist from sn to earth*/
  519. X    double deps, dpsi;    /* nutation on obliquity and longitude */
  520. X    double lst;        /* local sidereal time */
  521. X    double ehp;        /* angular diamter of earth from object */
  522. X    double ha;        /* hour angle */
  523. X    double ra, dec;        /* ra and dec now */
  524. X    double alt, az;        /* alt and az */
  525. X    double lam;            /* geocentric ecliptic longitude */
  526. X    double bet;            /* geocentric ecliptic latitude */
  527. X    double edistau;        /* earth-moon dist, in au */
  528. X    double el;        /* elongation, rads east */
  529. X
  530. X    moon (mjd, &lam, &bet, &ehp);    /* moon's true ecliptic loc */
  531. X    nutation (mjd, &deps, &dpsi);    /* correct for nutation */
  532. X    lam += dpsi;
  533. X    range (&lam, 2*PI);
  534. X
  535. X    op->s_edist = 6378.14/sin(ehp);    /* earth-moon dist, want km */
  536. X    op->s_size = 3600*31.22512*sin(ehp);/* moon angular dia, seconds */
  537. X    op->s_hlong = lam;        /* save geo in helio fields */
  538. X    op->s_hlat = bet;
  539. X
  540. X    /* convert geocentric ecliptic lat/long to equitorial ra/dec of date */
  541. X    ecl_eq (mjd, bet, lam, &ra, &dec);
  542. X
  543. X    /* find s_ra/dec at desired epoch */
  544. X    if (epoch == EOD) {
  545. X        op->s_ra = ra;
  546. X        op->s_dec = dec;
  547. X    } else {
  548. X        double tra = ra, tdec = dec;
  549. X        precess (mjd, epoch, &tra, &tdec);
  550. X        op->s_ra = tra;
  551. X        op->s_dec = tdec;
  552. X    }
  553. X
  554. X    sunpos (mjd, &lsn, &rsn);
  555. X    range (&lsn, 2*PI);
  556. X    elongation (lam, bet, lsn, &el);
  557. X
  558. X    /* solve triangle of earth, sun, and elongation for moon-sun dist */
  559. X    edistau = op->s_edist/1.495979e8;    /* km -> au */
  560. X    op->s_sdist= sqrt (edistau*edistau + rsn*rsn - 2.0*edistau*rsn*cos(el));
  561. X
  562. X    /* TODO: improve mag; this is based on a flat moon model. */
  563. X    op->s_mag = MAGSCALE * 
  564. X        (-12.7 + 2.5*(log10(PI) - log10(PI/2*(1+1.e-6-cos(el)))));
  565. X
  566. X    op->s_elong = raddeg(el);        /* want degrees */
  567. X    op->s_phase = fabs(el)/PI*100.0;    /* want non-negative % */
  568. X
  569. X    /* show topocentric alt/az by correcting ra/dec for parallax 
  570. X     * as well as refraction.
  571. X     * use unprecessed ra/dec.
  572. X     */
  573. X    now_lst (np, &lst);
  574. X    ha = hrrad(lst) - ra;
  575. X    ta_par (ha, dec, lat, elev, ehp, &ha, &dec);
  576. X    hadec_aa (lat, ha, dec, &alt, &az);
  577. X    refract (pressure, temp, alt, &alt);
  578. X    op->s_alt = alt;
  579. X    op->s_az = az;
  580. X
  581. X    return (0);
  582. X}
  583. X
  584. X/* fill in all of op->s_* stuff except s_size and s_mag */
  585. Xstatic void
  586. Xcir_sky (np, lpd, psi, rp, rho, lam, bet, lsn, rsn, op)
  587. XNow *np;
  588. Xdouble lpd, psi;    /* heliocentric ecliptic long and lat */
  589. Xdouble rp;        /* dist from sun */
  590. Xdouble rho;        /* dist from earth */
  591. Xdouble lam, bet;    /* true geocentric ecliptic long and lat */
  592. Xdouble lsn, rsn;    /* true geoc lng of sun; dist from sn to earth*/
  593. XObj *op;
  594. X{
  595. X    double a;        /* geoc angle between object and sun */
  596. X    double ra, dec;        /* ra and dec at epoch of date */
  597. X    double el;        /* elongation */
  598. X    double lst;        /* local sidereal time */
  599. X    double ehp;        /* ehp: angular dia of earth from body */
  600. X    double ha;        /* local hour angle */
  601. X    double f;        /* fractional phase from earth */
  602. X    double alt, az;        /* current alt, az */
  603. X    double deps, dpsi;    /* nutation on obliquity and longitude */
  604. X
  605. X    /* correct for nutation ... */
  606. X    nutation (mjd, &deps, &dpsi);
  607. X    lam += dpsi;
  608. X
  609. X    /* and correct for 20.4" aberation */
  610. X    a = lsn - lam;
  611. X    lam -= degrad(20.4/3600)*cos(a)/cos(bet);
  612. X    bet -= degrad(20.4/3600)*sin(a)*sin(bet);
  613. X
  614. X    /* convert geocentric ecliptic lat/long to equitorial ra/dec of date */
  615. X    ecl_eq (mjd, bet, lam, &ra, &dec);
  616. X
  617. X    /* set s_ra/s_dec to that of desired display epoch. */
  618. X    if (epoch == EOD) {
  619. X        op->s_ra = ra;
  620. X        op->s_dec = dec;
  621. X    } else {
  622. X        double tra = ra, tdec = dec;
  623. X        precess (mjd, epoch, &tra, &tdec);
  624. X        op->s_ra = tra;
  625. X        op->s_dec = tdec;
  626. X    }
  627. X
  628. X    /* set earth/planet and sun/planet distance */
  629. X    op->s_edist = rho;
  630. X    op->s_sdist = rp;
  631. X
  632. X    /* compute elongation and phase */
  633. X    elongation (lam, bet, lsn, &el);
  634. X    el = raddeg(el);
  635. X    op->s_elong = el;
  636. X    f = 0.25 * ((rp+rho)*(rp+rho) - rsn*rsn)/(rp*rho);
  637. X    op->s_phase = f*100.0; /* percent */
  638. X
  639. X    /* set heliocentric long/lat */
  640. X    op->s_hlong = lpd;
  641. X    op->s_hlat = psi;
  642. X
  643. X    /* alt, az: correct for parallax and refraction; use eod ra/dec. */
  644. X    now_lst (np, &lst);
  645. X    ha = hrrad(lst) - ra;
  646. X    ehp = (2.0*6378.0/146.0e6) / rho;
  647. X    ta_par (ha, dec, lat, elev, ehp, &ha, &dec);
  648. X    hadec_aa (lat, ha, dec, &alt, &az);
  649. X    refract (pressure, temp, alt, &alt);
  650. X    op->s_alt = alt;
  651. X    op->s_az = az;
  652. X}
  653. X
  654. X/* given geocentric ecliptic longitude and latitude, lam and bet, of some object
  655. X * and the longitude of the sun, lsn, find the elongation, el. this is the
  656. X * actual angular separation of the object from the sun, not just the difference
  657. X * in the longitude. the sign, however, IS set simply as a test on longitude
  658. X * such that el will be >0 for an evening object <0 for a morning object.
  659. X * to understand the test for el sign, draw a graph with lam going from 0-2*PI
  660. X *   down the vertical axis, lsn going from 0-2*PI across the hor axis. then
  661. X *   define the diagonal regions bounded by the lines lam=lsn+PI, lam=lsn and
  662. X *   lam=lsn-PI. the "morning" regions are any values to the lower left of the
  663. X *   first line and bounded within the second pair of lines.
  664. X * all angles in radians.
  665. X */
  666. Xstatic void
  667. Xelongation (lam, bet, lsn, el)
  668. Xdouble lam, bet, lsn;
  669. Xdouble *el;
  670. X{
  671. X    *el = acos(cos(bet)*cos(lam-lsn));
  672. X    if (lam>lsn+PI || lam>lsn-PI && lam<lsn) *el = - *el;
  673. X}
  674. END_OF_FILE
  675.   if test 20008 -ne `wc -c <'circum.c'`; then
  676.     echo shar: \"'circum.c'\" unpacked with wrong size!
  677.   fi
  678.   # end of 'circum.c'
  679. fi
  680. if test -f 'misc.c' -a "${1}" != "-c" ; then 
  681.   echo shar: Will not clobber existing file \"'misc.c'\"
  682. else
  683.   echo shar: Extracting \"'misc.c'\" \(19567 characters\)
  684.   sed "s/^X//" >'misc.c' <<'END_OF_FILE'
  685. X/* misc handy functions.
  686. X * every system has such, no?
  687. X */
  688. X
  689. X#include <stdio.h>
  690. X#include <ctype.h>
  691. X#include <math.h>
  692. X#if defined(__STDC__)
  693. X#include <stdlib.h>
  694. X#endif
  695. X#include <X11/Xlib.h>
  696. X#include <X11/cursorfont.h>
  697. X#include <Xm/Xm.h>
  698. X#include <Xm/PushB.h>
  699. X#include "astro.h"
  700. X#include "circum.h"
  701. X
  702. X#if defined(__STDC__) || defined(__cplusplus)
  703. X#define P_(s) s
  704. X#else
  705. X#define P_(s) ()
  706. X#endif
  707. X
  708. Xextern Now *mm_get_now P_((void));
  709. Xextern int listing_ison P_((void));
  710. Xextern int plot_ison P_((void));
  711. Xextern int srch_ison P_((void));
  712. Xextern void dm_newobj P_((int dbidx));
  713. Xextern void dm_selection_mode P_((int whether));
  714. Xextern void dm_update P_((Now *np, int how_much));
  715. Xextern void e_cursor P_((Cursor c));
  716. Xextern void e_selection_mode P_((int whether));
  717. Xextern void e_update P_((Now *np, int force));
  718. Xextern void f_showit P_((Widget w, char *s));
  719. Xextern void fs_date P_((char out[], double jd));
  720. Xextern void fs_time P_((char out[], double t));
  721. Xextern void jm_selection_mode P_((int whether));
  722. Xextern void jm_update P_((Now *np, int how_much));
  723. Xextern void lst_log P_((char *name, char *str));
  724. Xextern void lst_selection P_((char *name));
  725. Xextern void m_update P_((Now *np, int how_much));
  726. Xextern void mars_cursor P_((Cursor c));
  727. Xextern void mars_selection_mode P_((int whether));
  728. Xextern void mars_update P_((Now *np, int force));
  729. Xextern void mm_selection_mode P_((int whether));
  730. Xextern void obj_newdb P_((int appended));
  731. Xextern void obj_update P_((Now *np, int howmuch));
  732. Xextern void plt_log P_((char *name, double value));
  733. Xextern void plt_selection P_((char *name));
  734. Xextern void sm_selection_mode P_((int whether));
  735. Xextern void sm_update P_((Now *np, int how_much));
  736. Xextern void srch_log P_((char *name, double value));
  737. Xextern void srch_selection P_((char *name));
  738. Xextern void srch_selection_mode P_((int whether));
  739. Xextern void ss_newobj P_((int dbidx));
  740. Xextern void ss_update P_((Now *np, int how_much));
  741. Xextern void sv_newdb P_((int appended));
  742. Xextern void sv_newobj P_((int dbidx));
  743. Xextern void sv_update P_((Now *np, int how_much));
  744. Xextern void utc_gst P_((double Mjd, double utc, double *gst));
  745. Xextern void xe_msg P_((char *msg, int app_modal));
  746. X
  747. Xvoid set_something P_((Widget w, char *resource, char *value));
  748. Xvoid get_something P_((Widget w, char *resource, char *value));
  749. Xvoid get_xmstring P_((Widget w, char *resource, char **txtp));
  750. Xvoid set_xmstring P_((Widget w, char *resource, char *txt));
  751. Xvoid range P_((double *v, double r));
  752. Xvoid now_lst P_((Now *np, double *lst));
  753. Xvoid rnd_second P_((double *t));
  754. Xdouble mjd_day P_((double jd));
  755. Xdouble mjd_hr P_((double jd));
  756. Xvoid zero_mem P_((char *loc, unsigned len));
  757. Xvoid watch_cursor P_((int want));
  758. Xvoid all_update P_((Now *np, int how_much));
  759. Xvoid all_newobj P_((int dbidx));
  760. Xvoid all_newdb P_((int appended));
  761. Xvoid all_selection_mode P_((int whether));
  762. Xvoid register_selection P_((char *name));
  763. Xvoid field_log P_((Widget w, double value, int logv, char *str));
  764. Xvoid prompt_map_cb P_((Widget w, XtPointer client, XtPointer call));
  765. Xstatic void get_color_resource P_((Widget w, char *cname, Pixel *p));
  766. Xstatic get_views_font P_((Display *dsp, Font *fp));
  767. Xvoid obj_pickgc P_((Obj *op, Widget w, GC *gcp));
  768. Xint tickmarks P_((double min, double max, int numdiv, double ticks[]));
  769. Xchar *obj_description P_((Obj *op));
  770. Xvoid timestamp P_((Now *np, Widget w));
  771. Xint any_ison P_((void));
  772. Xint lc P_((int cx, int cy, int cw, int x1, int y1, int x2, int y2, int *sx1, int *sy1, int *sx2, int *sy2));
  773. Xvoid hg_mag P_((double h, double g, double rp, double rho, double rsn, double *mp));
  774. Xvoid gk_mag P_((double g, double k, double rp, double rho, double *mp));
  775. X
  776. X#undef P_
  777. X
  778. Xextern Widget toplevel_w;
  779. Xextern char *myclass;
  780. X#define    XtD    XtDisplay(toplevel_w)
  781. X
  782. X/* handy way to set one resource for a widget.
  783. X * shouldn't use this if you have several things to set for the same widget.
  784. X */
  785. Xvoid
  786. Xset_something (w, resource, value)
  787. XWidget w;
  788. Xchar *resource;
  789. Xchar *value;
  790. X{
  791. X    Arg a[1];
  792. X
  793. X    if (!w) {
  794. X        printf ("set_something (%s) called with w==0\n", resource);
  795. X        exit(1);
  796. X    }
  797. X
  798. X    XtSetArg (a[0], resource, value);
  799. X    XtSetValues (w, a, 1);
  800. X}
  801. X
  802. X/* handy way to get one resource for a widget.
  803. X * shouldn't use this if you have several things to get for the same widget.
  804. X */
  805. Xvoid
  806. Xget_something (w, resource, value)
  807. XWidget w;
  808. Xchar *resource;
  809. Xchar *value;
  810. X{
  811. X    Arg a[1];
  812. X
  813. X    if (!w) {
  814. X        printf ("get_something (%s) called with w==0\n", resource);
  815. X        exit(1);
  816. X    }
  817. X
  818. X    XtSetArg (a[0], resource, value);
  819. X    XtGetValues (w, a, 1);
  820. X}
  821. X
  822. X/* return the given XmString resource from the given widget as a char *.
  823. X * N.B. based on a sample in Heller, pg 178, the string back from
  824. X *   XmStringGetLtoR should be XtFree'd. Therefore, OUR caller should always
  825. X *   XtFree (*txtp).
  826. X */
  827. Xvoid
  828. Xget_xmstring (w, resource, txtp)
  829. XWidget w;
  830. Xchar *resource;
  831. Xchar **txtp;
  832. X{
  833. X    static char me[] = "get_xmstring()";
  834. X    static char hah[] = "??";
  835. X
  836. X    if (!w) {
  837. X        printf ("%s: called for %s with w==0\n", me, resource);
  838. X        exit(1);
  839. X    } else {
  840. X        XmString str;
  841. X        get_something(w, resource, (char *)&str); 
  842. X        if (!XmStringGetLtoR (str, XmSTRING_DEFAULT_CHARSET, txtp)) {
  843. X        /*
  844. X        fprintf (stderr, "%s: can't get string resource %s\n", me,
  845. X                                resource);
  846. X        exit (1);
  847. X        */
  848. X        (void) strcpy (*txtp = XtMalloc(sizeof(hah)), hah);
  849. X        }
  850. X        XmStringFree (str);
  851. X    }
  852. X}
  853. X
  854. Xvoid
  855. Xset_xmstring (w, resource, txt)
  856. XWidget w;
  857. Xchar *resource;
  858. Xchar *txt;
  859. X{
  860. X    XmString str;
  861. X
  862. X    if (!w) {
  863. X        printf ("set_xmstring called for %s with w==0\n", resource);
  864. X        return;
  865. X    }
  866. X
  867. X    str = XmStringCreateLtoR (txt, XmSTRING_DEFAULT_CHARSET);
  868. X    set_something (w, resource, (char *)str);
  869. X    XmStringFree (str);
  870. X}
  871. X
  872. X/* insure 0 <= *v < r.
  873. X */
  874. Xvoid
  875. Xrange (v, r)
  876. Xdouble *v, r;
  877. X{
  878. X    *v -= r*floor(*v/r);
  879. X}
  880. X
  881. Xvoid
  882. Xnow_lst (np, lst)
  883. XNow *np;
  884. Xdouble *lst;
  885. X{
  886. X    utc_gst (mjd_day(mjd), mjd_hr(mjd), lst);
  887. X    *lst += radhr(lng);
  888. X    range (lst, 24.0);
  889. X}
  890. X
  891. X/* round a time in days, *t, to the nearest second, IN PLACE. */
  892. Xvoid
  893. Xrnd_second (t)
  894. Xdouble *t;
  895. X{
  896. X    *t = floor(*t*SPD+0.5)/SPD;
  897. X}
  898. X    
  899. Xdouble
  900. Xmjd_day(jd)
  901. Xdouble jd;
  902. X{
  903. X    return (floor(jd-0.5)+0.5);
  904. X}
  905. X
  906. Xdouble
  907. Xmjd_hr(jd)
  908. Xdouble jd;
  909. X{
  910. X    return ((jd-mjd_day(jd))*24.0);
  911. X}
  912. X
  913. X/* zero from loc for len bytes */
  914. Xvoid
  915. Xzero_mem (loc, len)
  916. Xchar *loc;
  917. Xunsigned len;
  918. X{
  919. X    (void) memset (loc, 0, len);
  920. X}
  921. X
  922. X/* called to set or unset the watch cursor on all menus.
  923. X * allow for nested requests.
  924. X */
  925. Xvoid
  926. Xwatch_cursor(want)
  927. Xint want;
  928. X{
  929. X    extern void dm_cursor();
  930. X    extern void db_cursor();
  931. X    extern void jm_cursor();
  932. X    extern void lst_cursor();
  933. X    extern void main_cursor();
  934. X    extern void m_cursor();
  935. X    extern void msg_cursor();
  936. X    extern void obj_cursor();
  937. X    extern void plt_cursor();
  938. X    extern void sm_cursor();
  939. X    extern void sv_cursor();
  940. X    extern void svf_cursor();
  941. X    extern void ss_cursor();
  942. X    extern void srch_cursor();
  943. X    extern void v_cursor();
  944. X    static Cursor wc;
  945. X    static nreqs;
  946. X    Cursor c;
  947. X
  948. X    if (!wc)
  949. X        wc = XCreateFontCursor (XtD, XC_watch);
  950. X
  951. X    if (want) {
  952. X        if (nreqs++ > 0)
  953. X        return;
  954. X        c = wc;
  955. X    } else {
  956. X        if (--nreqs > 0)
  957. X        return;
  958. X        c = (Cursor)0;
  959. X    }
  960. X
  961. X    dm_cursor(c);
  962. X    db_cursor(c);
  963. X    jm_cursor(c);
  964. X    mars_cursor(c);
  965. X    e_cursor(c);
  966. X    lst_cursor(c);
  967. X    main_cursor(c);
  968. X    m_cursor(c);
  969. X    msg_cursor(c);
  970. X    obj_cursor(c);
  971. X    plt_cursor(c);
  972. X    sm_cursor(c);
  973. X    sv_cursor(c);
  974. X    svf_cursor(c);
  975. X    ss_cursor(c);
  976. X    srch_cursor(c);
  977. X    v_cursor(c);
  978. X
  979. X    XSync (XtD, 0);
  980. X}
  981. X
  982. X/* print stuff on other menus */
  983. Xvoid
  984. Xall_update(np, how_much)
  985. XNow *np;
  986. Xint how_much;
  987. X{
  988. X    dm_update (np, how_much);
  989. X    mars_update (np, how_much);
  990. X    e_update (np, how_much);
  991. X    jm_update (np, how_much);
  992. X    sm_update (np, how_much);
  993. X    ss_update (np, how_much);
  994. X    sv_update (np, how_much);
  995. X    m_update  (np, how_much);
  996. X    obj_update (np, how_much);
  997. X}
  998. X
  999. X/* tell everyone who might care that a user-defined object has changed
  1000. X * then recompute and redisplay new values.
  1001. X */
  1002. Xvoid
  1003. Xall_newobj(dbidx)
  1004. Xint dbidx;
  1005. X{
  1006. X    watch_cursor (1);
  1007. X
  1008. X    dm_newobj(dbidx);
  1009. X    ss_newobj(dbidx);
  1010. X    sv_newobj(dbidx);
  1011. X    all_update (mm_get_now(), 1);
  1012. X
  1013. X    watch_cursor (0);
  1014. X}
  1015. X
  1016. X/* tell everyone who might care that the db (beyond NOBJ) has changed.
  1017. X * appended is true if it grew; else it was replaced.
  1018. X */
  1019. Xvoid
  1020. Xall_newdb(appended)
  1021. Xint appended;
  1022. X{
  1023. X    watch_cursor (1);
  1024. X
  1025. X    obj_newdb(appended);
  1026. X    sv_newdb(appended);
  1027. X
  1028. X    watch_cursor (0);
  1029. X}
  1030. X
  1031. X/* inform all menus that have something selectable for plotting/listing/srching
  1032. X * wether we are now in a mode that they should report when those fields are
  1033. X * selected.
  1034. X */
  1035. Xvoid
  1036. Xall_selection_mode(whether)
  1037. Xint whether;
  1038. X{
  1039. X    dm_selection_mode(whether);
  1040. X    mm_selection_mode(whether);
  1041. X    jm_selection_mode(whether);
  1042. X    mars_selection_mode(whether);
  1043. X    e_selection_mode(whether);
  1044. X    sm_selection_mode(whether);
  1045. X    srch_selection_mode(whether);
  1046. X}
  1047. X
  1048. X/* inform all potentially interested parties of the name of a field that
  1049. X * it might want to use for latter.
  1050. X * this is just to collect in one place all the modules that gather care.
  1051. X */
  1052. Xvoid
  1053. Xregister_selection (name)
  1054. Xchar *name;
  1055. X{
  1056. X    plt_selection (name);
  1057. X    lst_selection (name);
  1058. X    srch_selection (name);
  1059. X}
  1060. X
  1061. X/* if we are plotting/listing/searching, send the current field info to them.
  1062. X * N.B. only send `value' to plot and search if logv is not 0.
  1063. X */
  1064. Xvoid
  1065. Xfield_log (w, value, logv, str)
  1066. XWidget w;
  1067. Xdouble value;
  1068. Xint logv;
  1069. Xchar *str;
  1070. X{
  1071. X    char *name;
  1072. X
  1073. X    if (!any_ison())
  1074. X        return;
  1075. X
  1076. X    get_something (w, XmNuserData, (char *)&name);
  1077. X    if (name) {
  1078. X        if (logv) {
  1079. X        plt_log (name, value);
  1080. X        srch_log (name, value);
  1081. X        }
  1082. X        lst_log (name, str);
  1083. X    }
  1084. X}
  1085. X
  1086. X/* may be connected as the mapCallback to any convenience Dialog to
  1087. X * position it centered the cursor (allowing for the screen edges).
  1088. X */
  1089. X/* ARGSUSED */
  1090. Xvoid
  1091. Xprompt_map_cb (w, client, call)
  1092. XWidget w;
  1093. XXtPointer client;
  1094. XXtPointer call;
  1095. X{
  1096. X    Window root, child;
  1097. X    int rx, ry, wx, wy;    /* rx/y: cursor loc on root window */
  1098. X    unsigned sw, sh;    /* screen width/height */
  1099. X    Dimension ww, wh;    /* this widget's width/height */
  1100. X    Position x, y;        /* final location */
  1101. X    unsigned mask;
  1102. X    Arg args[20];
  1103. X    int n;
  1104. X
  1105. X    XQueryPointer (XtDisplay(w), XtWindow(w),
  1106. X                &root, &child, &rx, &ry, &wx, &wy, &mask);
  1107. X    sw = WidthOfScreen (XtScreen(w));
  1108. X    sh = HeightOfScreen(XtScreen(w));
  1109. X    n = 0;
  1110. X    XtSetArg (args[n], XmNwidth, &ww); n++;
  1111. X    XtSetArg (args[n], XmNheight, &wh); n++;
  1112. X    XtGetValues (w, args, n);
  1113. X
  1114. X    x = rx - ww/2;
  1115. X    if (x < 0)
  1116. X        x = 0;
  1117. X    else if (x + ww >= sw)
  1118. X        x = sw - ww;
  1119. X    y = ry - wh/2;
  1120. X    if (y < 0)
  1121. X        y = 0;
  1122. X    else if (y + wh >= sh)
  1123. X        y = sh - wh;
  1124. X
  1125. X    n = 0;
  1126. X    XtSetArg (args[n], XmNx, x); n++;
  1127. X    XtSetArg (args[n], XmNy, y); n++;
  1128. X    XtSetValues (w, args, n);
  1129. X}
  1130. X
  1131. X/* get the named color in *p, else set to w's XmNforeground.
  1132. X */
  1133. Xstatic void
  1134. Xget_color_resource (w, cname, p)
  1135. XWidget w;
  1136. Xchar *cname;
  1137. XPixel *p;
  1138. X{
  1139. X    Display *dsp = XtDisplay(w);
  1140. X    Colormap def_cm = DefaultColormap (dsp, 0);
  1141. X    XColor defxc, dbxc;
  1142. X    char *cval;
  1143. X
  1144. X    cval = XGetDefault (dsp, myclass, cname);
  1145. X
  1146. X    if (!cval || !XAllocNamedColor (dsp, def_cm, cval, &defxc, &dbxc)) {
  1147. X        char msg[128];
  1148. X        if (!cval)
  1149. X        (void) sprintf (msg, "Can't find resource `%.80s'", cname);
  1150. X        else
  1151. X        (void) sprintf (msg, "Can't Alloc color `%.80s'", cval);
  1152. X        (void) strcat (msg, "... so using *foreground.\n");
  1153. X        xe_msg(msg, 0);
  1154. X        get_something (w, XmNforeground, (char *)p);
  1155. X    } else
  1156. X        *p = defxc.pixel;
  1157. X}
  1158. X
  1159. X/* get the Font we want to use when drawing text for the display views.
  1160. X * return 0 if ok, else -1.
  1161. X */
  1162. Xstatic
  1163. Xget_views_font (dsp, fp)
  1164. XDisplay *dsp;
  1165. XFont *fp;
  1166. X{
  1167. X    static char resname[] = "viewsFont";
  1168. X    char *fname;
  1169. X    XFontStruct *fsp;
  1170. X
  1171. X    fname = XGetDefault (dsp, myclass, resname);
  1172. X
  1173. X    /* use XLoadQueryFont because it returns gracefully if font is not
  1174. X     * found; XloadFont calls the default X error handler.
  1175. X     */
  1176. X    if (!fname || !(fsp = XLoadQueryFont (dsp, fname))) {
  1177. X        char msg[256];
  1178. X
  1179. X        if (!fname)
  1180. X        (void) sprintf (msg, "Can't find resource `%.180s'", resname);
  1181. X        else
  1182. X        (void) sprintf (msg, "Can't load font `%.180s'", fname);
  1183. X        (void) strcat (msg, "... using default server font");
  1184. X        xe_msg(msg, 0);
  1185. X        return (-1);
  1186. X    }
  1187. X    
  1188. X    *fp = fsp->fid;
  1189. X    return (0);
  1190. X}
  1191. X
  1192. X/* given an object, return a GC for it.
  1193. X * Use the colors defined in the X resoucres, else use the foreground of the
  1194. X * given widget.
  1195. X */
  1196. Xvoid
  1197. Xobj_pickgc(op, w, gcp)
  1198. XObj *op;
  1199. XWidget w;
  1200. XGC *gcp;
  1201. X{
  1202. X    /* names of resource colors for the planets.
  1203. X     * N.B. should be in the same order as the defines in astro.h
  1204. X     */
  1205. X    static char *objcolnames[NOBJ-2] = {
  1206. X        "mercuryColor", "venusColor", "marsColor", "jupiterColor",
  1207. X        "saturnColor", "uranusColor", "neptuneColor", "plutoColor",
  1208. X        "sunColor", "moonColor"
  1209. X    };
  1210. X    /* names of resource colors for stellar types.
  1211. X     */
  1212. X    static char *starcolnames[] = {
  1213. X        "hotStarColor", "mediumStarColor", "coolStarColor"
  1214. X    };
  1215. X    static GC objgcs[XtNumber(objcolnames)];
  1216. X    static GC stargcs[XtNumber(starcolnames)];
  1217. X    static GC other_gc;
  1218. X
  1219. X    /* make all the gcs the first time through */
  1220. X    if (!other_gc) {
  1221. X        Display *dsp = XtDisplay(w);
  1222. X        Window win = XtWindow(w);
  1223. X        unsigned gcm = GCForeground;
  1224. X        Font f;
  1225. X        XGCValues gcv;
  1226. X        Pixel p;
  1227. X        int i;
  1228. X
  1229. X        if (get_views_font (dsp, &f) == 0) {
  1230. X        gcm |= GCFont;
  1231. X        gcv.font = f;
  1232. X        }
  1233. X
  1234. X        /* make the planet gcs */
  1235. X        for (i = 0; i < XtNumber(objgcs); i++) {
  1236. X        get_color_resource (w, objcolnames[i], &p);
  1237. X        gcv.foreground = p;
  1238. X        objgcs[i] = XCreateGC (dsp, win, gcm, &gcv);
  1239. X        }
  1240. X
  1241. X        /* make the star color gcs */
  1242. X        for (i = 0; i < XtNumber(stargcs); i++) {
  1243. X        get_color_resource (w, starcolnames[i], &p);
  1244. X        gcv.foreground = p;
  1245. X        stargcs[i] = XCreateGC (dsp, win, gcm, &gcv);
  1246. X        }
  1247. X
  1248. X        /* make the gc for everything else */
  1249. X        get_something (w, XmNforeground, (char *)&p);
  1250. X        gcv.foreground = p;
  1251. X        other_gc = XCreateGC (dsp, win, gcm, &gcv);
  1252. X    }
  1253. X
  1254. X    if (op->type == PLANET && op->pl.code < XtNumber(objgcs))
  1255. X        *gcp = objgcs[op->pl.code];
  1256. X    else if (op->type == FIXED && op->f_spect[0])
  1257. X        switch (op->f_spect[0]) {
  1258. X        case 'O': case 'B': case 'A': case 'W':
  1259. X        *gcp = stargcs[0];
  1260. X        break;
  1261. X        case 'F': case 'G':
  1262. X        *gcp = stargcs[1];
  1263. X        break;
  1264. X        case 'K': case 'M': case 'N': case 'R': case 'S':
  1265. X        *gcp = stargcs[2];
  1266. X        break;
  1267. X        default:
  1268. X        *gcp = other_gc;
  1269. X        break;
  1270. X        }
  1271. X    else
  1272. X        *gcp = other_gc;
  1273. X}
  1274. X
  1275. X/* given min and max and an approximate number of divisions desired,
  1276. X * fill in ticks[] with nicely spaced values and return how many.
  1277. X * N.B. return value, and hence number of entries to ticks[], might be as
  1278. X *   much as 2 more than numdiv.
  1279. X */
  1280. Xint
  1281. Xtickmarks (min, max, numdiv, ticks)
  1282. Xdouble min, max;
  1283. Xint numdiv;
  1284. Xdouble ticks[];
  1285. X{
  1286. X        static int factor[] = { 1, 2, 5 };
  1287. X        double minscale;
  1288. X        double delta;
  1289. X    double lo;
  1290. X        double v;
  1291. X        int n;
  1292. X
  1293. X        minscale = fabs(max - min);
  1294. X        delta = minscale/numdiv;
  1295. X        for (n=0; n < sizeof(factor)/sizeof(factor[0]); n++) {
  1296. X        double scale;
  1297. X        double x = delta/factor[n];
  1298. X            if ((scale = (pow(10.0, ceil(log10(x)))*factor[n])) < minscale)
  1299. X        minscale = scale;
  1300. X    }
  1301. X        delta = minscale;
  1302. X
  1303. X        lo = floor(min/delta);
  1304. X        for (n = 0; (v = delta*(lo+n)) < max+delta; )
  1305. X        ticks[n++] = v;
  1306. X
  1307. X    return (n);
  1308. X}
  1309. X
  1310. X/* given an Obj *, return its type as a descriptive string.
  1311. X * if it's of type fixed then return its class description.
  1312. X * N.B. we return the address of static storage -- do not free or change.
  1313. X */
  1314. Xchar *
  1315. Xobj_description (op)
  1316. XObj *op;
  1317. X{
  1318. X    static struct {
  1319. X        char class;
  1320. X        char *desc;
  1321. X    } fixed_class_map[] = {
  1322. X        {'C', "Globular Cluster"},
  1323. X        {'U', "Cluster, with nebulosity"},
  1324. X        {'O', "Open Cluster"},
  1325. X        {'G', "Spiral Galaxy"},
  1326. X        {'H', "Spherical Galaxy"},
  1327. X        {'A', "Cluster of Galaxies"},
  1328. X        {'N', "Bright Nebula"},
  1329. X        {'F', "Diffuse Nebula"},
  1330. X        {'K', "Dark Nebula"},
  1331. X        {'P', "Planetary Nebula"},
  1332. X        {'Q', "Quasar"},
  1333. X        {'T', "Stellar Object"},
  1334. X        {'B', "Binary Star"},
  1335. X        {'D', "Double Star"},
  1336. X        {'M', "Multiple Star"},
  1337. X        {'S', "Star"},
  1338. X        {'V', "Variable Star"},
  1339. X    };
  1340. X
  1341. X    switch (op->type) {
  1342. X    case FIXED:
  1343. X        if (op->f_class) {
  1344. X        int i;
  1345. X        for (i = 0; i < XtNumber(fixed_class_map); i++)
  1346. X            if (fixed_class_map[i].class == op->f_class)
  1347. X            return (fixed_class_map[i].desc);
  1348. X        }
  1349. X        return ("Fixed");
  1350. X    case PARABOLIC:
  1351. X        return ("Solar - Parabolic");
  1352. X    case HYPERBOLIC:
  1353. X        return ("Solar - Hyperbolic");
  1354. X    case ELLIPTICAL:
  1355. X        return ("Solar - Elliptical");
  1356. X    case PLANET:
  1357. X        return ("Planet");
  1358. X    default:
  1359. X        printf ("obj_description: unknown type: 0x%x\n", op->type);
  1360. X        exit (1);
  1361. X        return (NULL);    /* for lint */
  1362. X    }
  1363. X}
  1364. X
  1365. X/* set the XmNlabelString resource of the given widget to the date and time 
  1366. X * as given in the Now struct at *np.
  1367. X * avoid unnecessary blinking by using f_showit().
  1368. X */
  1369. Xvoid
  1370. Xtimestamp (np, w)
  1371. XNow *np;
  1372. XWidget w;
  1373. X{
  1374. X    char d[32], t[32], out[64];
  1375. X    double lmjd = mjd - tz/24.0;
  1376. X    char timezonename[32];
  1377. X
  1378. X    fs_date (d, mjd_day(lmjd));
  1379. X    fs_time (t, mjd_hr(lmjd));
  1380. X    if (tznm[0] == '\0') {
  1381. X        if (tz == 0)
  1382. X        (void) strcpy(timezonename, "UTC");
  1383. X        else
  1384. X        (void) sprintf(timezonename, "UTC%c%g", tz<0?'+':'-', fabs(tz));
  1385. X    } else
  1386. X        (void) strcpy (timezonename, tznm);
  1387. X    (void) sprintf (out, "%s %s %s", d, t, timezonename);
  1388. X    f_showit (w, out);
  1389. X}
  1390. X
  1391. X/* return !0 if any of the button/data capture tools are active, else 0.
  1392. X */
  1393. Xany_ison()
  1394. X{
  1395. X    return (srch_ison() || plot_ison() || listing_ison());
  1396. X}
  1397. X
  1398. X/* given a circle and a line segment, find a segment of the line inside the 
  1399. X *   circle.
  1400. X * return 0 and the segment end points if one exists, else 0.
  1401. X * We use a parametric representation of the line:
  1402. X *   x = x1 + (x2-x1)*t and y = y1 + (y2-y1)*t, 0 < t < 1
  1403. X * and a centered representation of the circle:
  1404. X *   (x - xc)**2 + (y - yc)**2 = r**2
  1405. X * and solve for the t's that work, checking for usual conditions.
  1406. X */
  1407. Xlc (cx, cy, cw, x1, y1, x2, y2, sx1, sy1, sx2, sy2)
  1408. Xint cx, cy, cw;            /* circle bounding box corner and width */
  1409. Xint x1, y1, x2, y2;        /* line segment endpoints */
  1410. Xint *sx1, *sy1, *sx2, *sy2;    /* segment inside the circle */
  1411. X{
  1412. X    int dx = x2 - x1;
  1413. X    int dy = y2 - y1;
  1414. X    int r = cw/2;
  1415. X    int xc = cx + r;
  1416. X    int yc = cy + r;
  1417. X    int A = x1 - xc;
  1418. X    int B = y1 - yc;
  1419. X    double a = dx*dx + dy*dy;    /* O(2 * 2**16 * 2**16) */
  1420. X    double b = 2*(dx*A + dy*B);    /* O(4 * 2**16 * 2**16) */
  1421. X    double c = A*A + B*B - r*r;    /* O(2 * 2**16 * 2**16) */
  1422. X    double d = b*b - 4*a*c;        /* O(2**32 * 2**32) */
  1423. X    double sqrtd;
  1424. X    double t1, t2;
  1425. X
  1426. X    if (d <= 0)
  1427. X        return (-1);    /* containing line is purely outside circle */
  1428. X
  1429. X    sqrtd = sqrt(d);
  1430. X    t1 = (-b - sqrtd)/(2.0*a);
  1431. X    t2 = (-b + sqrtd)/(2.0*a);
  1432. X
  1433. X    if (t1 >= 1.0 || t2 <= 0.0)
  1434. X        return (-1);    /* segment is purely outside circle */
  1435. X
  1436. X    /* we know now that some part of the segment is inside,
  1437. X     * ie, t1 < 1 && t2 > 0
  1438. X     */
  1439. X
  1440. X    if (t1 <= 0.0) {
  1441. X        /* (x1,y1) is inside circle */
  1442. X        *sx1 = x1;
  1443. X        *sy1 = y1;
  1444. X    } else {
  1445. X        *sx1 = x1 + dx*t1;
  1446. X        *sy1 = y1 + dy*t1;
  1447. X    }
  1448. X
  1449. X    if (t2 >= 1.0) {
  1450. X        /* (x2,y2) is inside circle */
  1451. X        *sx2 = x2;
  1452. X        *sy2 = y2;
  1453. X    } else {
  1454. X        *sx2 = x1 + dx*t2;
  1455. X        *sy2 = y1 + dy*t2;
  1456. X    }
  1457. X
  1458. X    return (0);
  1459. X}
  1460. X
  1461. X/* compute visual magnitude using the H/G parameters used in the Astro Almanac.
  1462. X * these are commonly used for asteroids.
  1463. X */
  1464. Xvoid
  1465. Xhg_mag (h, g, rp, rho, rsn, mp)
  1466. Xdouble h, g;
  1467. Xdouble rp;    /* sun-obj dist, AU */
  1468. Xdouble rho;    /* earth-obj dist, AU */
  1469. Xdouble rsn;    /* sun-earth dist, AU */
  1470. Xdouble *mp;
  1471. X{
  1472. X    double psi_t, Psi_1, Psi_2, beta;
  1473. X    double tb2;
  1474. X
  1475. X    beta = acos((rp*rp + rho*rho - rsn*rsn)/ (2*rp*rho));
  1476. X    tb2 = tan(beta/2.0);
  1477. X    /* psi_t = exp(log(tan(beta/2.0))*0.63); */
  1478. X    psi_t = pow (tb2, 0.63);
  1479. X    Psi_1 = exp(-3.33*psi_t);
  1480. X    /* psi_t = exp(log(tan(beta/2.0))*1.22); */
  1481. X    psi_t = pow (tb2, 1.22);
  1482. X    Psi_2 = exp(-1.87*psi_t);
  1483. X    *mp = h + 5.0*log10(rp*rho) - 2.5*log10((1-g)*Psi_1 + g*Psi_2);
  1484. X}
  1485. X
  1486. X/* computer visual magnitude using the g/k parameters commonly used for comets.
  1487. X */
  1488. Xvoid
  1489. Xgk_mag (g, k, rp, rho, mp)
  1490. Xdouble g, k;
  1491. Xdouble rp;    /* sun-obj dist, AU */
  1492. Xdouble rho;    /* earth-obj dist, AU */
  1493. Xdouble *mp;
  1494. X{
  1495. X    *mp = g + 5.0*log10(rho) + 2.5*k*log10(rp);
  1496. X}
  1497. END_OF_FILE
  1498.   if test 19567 -ne `wc -c <'misc.c'`; then
  1499.     echo shar: \"'misc.c'\" unpacked with wrong size!
  1500.   fi
  1501.   # end of 'misc.c'
  1502. fi
  1503. if test -f 'precess.c' -a "${1}" != "-c" ; then 
  1504.   echo shar: Will not clobber existing file \"'precess.c'\"
  1505. else
  1506.   echo shar: Extracting \"'precess.c'\" \(4390 characters\)
  1507.   sed "s/^X//" >'precess.c' <<'END_OF_FILE'
  1508. X#include <stdio.h>
  1509. X#include <math.h>
  1510. X#include "astro.h"
  1511. X#include "preferences.h"
  1512. X
  1513. X
  1514. X#if defined(__STDC__) || defined(__cplusplus)
  1515. X#define P_(s) s
  1516. X#else
  1517. X#define P_(s) ()
  1518. X#endif
  1519. X
  1520. Xextern void mjd_year P_((double Mjd, double *yr));
  1521. Xextern void range P_((double *v, double r));
  1522. X
  1523. Xvoid precess P_((double mjd1, double mjd2, double *ra, double *dec));
  1524. Xstatic void precess_hiprec P_((double mjd1, double mjd2, double *ra, double *dec));
  1525. Xstatic void precess_fast P_((double mjd1, double mjd2, double *ra, double *dec));
  1526. X
  1527. X#undef P_
  1528. X
  1529. X#define    DCOS(x)        cos(degrad(x))
  1530. X#define    DSIN(x)        sin(degrad(x))
  1531. X#define    DASIN(x)    raddeg(asin(x))
  1532. X#define    DATAN2(y,x)    raddeg(atan2((y),(x)))
  1533. X
  1534. X/* corrects ra and dec, both in radians, for precession from epoch 1 to epoch 2.
  1535. X * the epochs are given by their modified JDs, mjd1 and mjd2, respectively.
  1536. X * N.B. ra and dec are modifed IN PLACE.
  1537. X */
  1538. Xvoid
  1539. Xprecess (mjd1, mjd2, ra, dec)
  1540. Xdouble mjd1, mjd2;    /* initial and final epoch modified JDs */
  1541. Xdouble *ra, *dec;    /* ra/dec for mjd1 in, for mjd2 out */
  1542. X{
  1543. X    if (pref_get(PREF_ALGO) == PREF_ACCURATE)
  1544. X        precess_hiprec (mjd1, mjd2, ra, dec);
  1545. X    else
  1546. X        precess_fast (mjd1, mjd2, ra, dec);
  1547. X}
  1548. X
  1549. X/*
  1550. X * Copyright (c) 1990 by Craig Counterman. All rights reserved.
  1551. X *
  1552. X * This software may be redistributed freely, not sold.
  1553. X * This copyright notice and disclaimer of warranty must remain
  1554. X *    unchanged. 
  1555. X *
  1556. X * No representation is made about the suitability of this
  1557. X * software for any purpose.  It is provided "as is" without express or
  1558. X * implied warranty, to the extent permitted by applicable law.
  1559. X *
  1560. X * Rigorous precession. From Astronomical Ephemeris 1989, p. B18
  1561. X */
  1562. Xstatic void
  1563. Xprecess_hiprec (mjd1, mjd2, ra, dec)
  1564. Xdouble mjd1, mjd2;    /* initial and final epoch modified JDs */
  1565. Xdouble *ra, *dec;    /* ra/dec for mjd1 in, for mjd2 out */
  1566. X{
  1567. X    double zeta_A, z_A, theta_A;
  1568. X    double T;
  1569. X    double A, B, C;
  1570. X    double alpha, delta;
  1571. X    double alpha_in, delta_in;
  1572. X    double from_equinox, to_equinox;
  1573. X    double alpha2000, delta2000;
  1574. X
  1575. X    mjd_year (mjd1, &from_equinox);
  1576. X    mjd_year (mjd2, &to_equinox);
  1577. X    alpha_in = raddeg(*ra);
  1578. X    delta_in = raddeg(*dec);
  1579. X
  1580. X    /* From from_equinox to 2000.0 */
  1581. X    if (from_equinox != 2000.0) {
  1582. X        T = (from_equinox - 2000.0)/100.0;
  1583. X        zeta_A  = 0.6406161* T + 0.0000839* T*T + 0.0000050* T*T*T;
  1584. X        z_A     = 0.6406161* T + 0.0003041* T*T + 0.0000051* T*T*T;
  1585. X        theta_A = 0.5567530* T - 0.0001185* T*T + 0.0000116* T*T*T;
  1586. X
  1587. X        A = DSIN(alpha_in - z_A) * DCOS(delta_in);
  1588. X        B = DCOS(alpha_in - z_A) * DCOS(theta_A) * DCOS(delta_in)
  1589. X          + DSIN(theta_A) * DSIN(delta_in);
  1590. X        C = -DCOS(alpha_in - z_A) * DSIN(theta_A) * DCOS(delta_in)
  1591. X          + DCOS(theta_A) * DSIN(delta_in);
  1592. X
  1593. X        alpha2000 = DATAN2(A,B) - zeta_A;
  1594. X        range (&alpha2000, 360.0);
  1595. X        delta2000 = DASIN(C);
  1596. X    } else {
  1597. X        /* should get the same answer, but this could improve accruacy */
  1598. X        alpha2000 = alpha_in;
  1599. X        delta2000 = delta_in;
  1600. X    };
  1601. X
  1602. X
  1603. X    /* From 2000.0 to to_equinox */
  1604. X    if (to_equinox != 2000.0) {
  1605. X        T = (to_equinox - 2000.0)/100.0;
  1606. X        zeta_A  = 0.6406161* T + 0.0000839* T*T + 0.0000050* T*T*T;
  1607. X        z_A     = 0.6406161* T + 0.0003041* T*T + 0.0000051* T*T*T;
  1608. X        theta_A = 0.5567530* T - 0.0001185* T*T + 0.0000116* T*T*T;
  1609. X
  1610. X        A = DSIN(alpha2000 + zeta_A) * DCOS(delta2000);
  1611. X        B = DCOS(alpha2000 + zeta_A) * DCOS(theta_A) * DCOS(delta2000)
  1612. X          - DSIN(theta_A) * DSIN(delta2000);
  1613. X        C = DCOS(alpha2000 + zeta_A) * DSIN(theta_A) * DCOS(delta2000)
  1614. X          + DCOS(theta_A) * DSIN(delta2000);
  1615. X
  1616. X        alpha = DATAN2(A,B) + z_A;
  1617. X        range(&alpha, 360.0);
  1618. X        delta = DASIN(C);
  1619. X    } else {
  1620. X        /* should get the same answer, but this could improve accruacy */
  1621. X        alpha = alpha2000;
  1622. X        delta = delta2000;
  1623. X    };
  1624. X
  1625. X    *ra = degrad(alpha);
  1626. X    *dec = degrad(delta);
  1627. X}
  1628. X
  1629. Xstatic void
  1630. Xprecess_fast (mjd1, mjd2, ra, dec)
  1631. Xdouble mjd1, mjd2;    /* initial and final epoch modified JDs */
  1632. Xdouble *ra, *dec;    /* ra/dec for mjd1 in, for mjd2 out */
  1633. X{
  1634. X    double nyrs;
  1635. X    double t1, t2;
  1636. X    double na, nb;
  1637. X    double ma, mb;
  1638. X    double n, m;
  1639. X    double ddec, dra;
  1640. X
  1641. X    nyrs = (mjd2 - mjd1)/365.2425;
  1642. X    t2 = mjd2/36525.0;
  1643. X    t1 = mjd1/36525.0;
  1644. X    nb = 20.0468 - (8.5e-3 * t2);
  1645. X    na = 20.0468 - (8.5e-3 * t1);
  1646. X    mb = 3.07234 + (1.86e-3 * t2);
  1647. X    ma = 3.07234 + (1.86e-3 * t1);
  1648. X    n = (na + nb)/2.0;
  1649. X    m = (ma + mb)/2.0;
  1650. X
  1651. X    ddec = n*cos(*ra) * 4.848137e-6 * nyrs;
  1652. X    dra  = (m + (n * sin(*ra) * tan(*dec)/15.0)) * 7.272205e-5 * nyrs;
  1653. X
  1654. X    *dec += ddec;
  1655. X    *ra += dra;
  1656. X    range (ra, 2.0*PI);
  1657. X}
  1658. END_OF_FILE
  1659.   if test 4390 -ne `wc -c <'precess.c'`; then
  1660.     echo shar: \"'precess.c'\" unpacked with wrong size!
  1661.   fi
  1662.   # end of 'precess.c'
  1663. fi
  1664. if test -f 'preferences.c' -a "${1}" != "-c" ; then 
  1665.   echo shar: Will not clobber existing file \"'preferences.c'\"
  1666. else
  1667.   echo shar: Extracting \"'preferences.c'\" \(7270 characters\)
  1668.   sed "s/^X//" >'preferences.c' <<'END_OF_FILE'
  1669. X/* code to support the preferences facility.
  1670. X * not much now, but expected to grow.
  1671. X * not all of these are necessarily settable in the Preferences mainmenu
  1672. X *   pulldown yet.
  1673. X */
  1674. X
  1675. X#include <Xm/Xm.h>
  1676. X#include <Xm/RowColumn.h>
  1677. X#include <Xm/ToggleB.h>
  1678. X#include <Xm/CascadeB.h>
  1679. X#include "astro.h"
  1680. X#include "circum.h"
  1681. X#include "preferences.h"
  1682. X
  1683. X#if defined(__STDC__) || defined(__cplusplus)
  1684. X#define P_(s) s
  1685. X#else
  1686. X#define P_(s) ()
  1687. X#endif
  1688. X
  1689. Xextern void redraw_screen P_((int how_much));
  1690. Xextern void set_xmstring P_((Widget w, char *resource, char *txt));
  1691. Xextern void xe_msg P_((char *msg, int app_modal));
  1692. X
  1693. Xvoid pref_create_pulldown P_((Widget menu_bar));
  1694. Xint pref_get P_((int pref));
  1695. Xstatic void pref_algo_cb P_((Widget w, XtPointer client, XtPointer call));
  1696. Xstatic void pref_date_cb P_((Widget w, XtPointer client, XtPointer call));
  1697. Xstatic void pref_units_cb P_((Widget w, XtPointer client, XtPointer call));
  1698. X
  1699. X#undef P_
  1700. X
  1701. Xextern char *myclass;
  1702. Xextern Widget toplevel_w;
  1703. X#define    XtD    XtDisplay(toplevel_w)
  1704. X
  1705. X/* record of preferences values */
  1706. Xstatic int prefs[NPREFS];
  1707. X
  1708. X/* Create "Preferences" PulldownMenu.
  1709. X * use the given menu_bar widget as a base.
  1710. X * this is called early when the main menu bar is being built..
  1711. X * initialize the prefs[] array from the initial state of the toggle buttons.
  1712. X */
  1713. Xvoid
  1714. Xpref_create_pulldown (menu_bar)
  1715. XWidget menu_bar;
  1716. X{
  1717. X    Widget tb1, tb2, tb3;
  1718. X    Widget cascade, menu_pane, pull_right;
  1719. X    Arg args[20];
  1720. X    int n;
  1721. X
  1722. X    n = 0;
  1723. X    menu_pane = XmCreatePulldownMenu (menu_bar, "Preferences", args, n);
  1724. X
  1725. X        /* create the algorithms pullright menu */
  1726. X
  1727. X        n = 0;
  1728. X        XtSetArg (args[n], XmNradioBehavior, True); n++;
  1729. X        pull_right = XmCreatePulldownMenu (menu_pane, "Algorithms", args,n);
  1730. X
  1731. X        n = 0;
  1732. X        XtSetArg (args[n], XmNmnemonic, 'A'); n++;
  1733. X        tb1 = XmCreateToggleButton (pull_right, "Accurate", args, n);
  1734. X        XtAddCallback (tb1, XmNvalueChangedCallback, pref_algo_cb,
  1735. X                            (XtPointer)PREF_ACCURATE);
  1736. X        XtManageChild (tb1);
  1737. X
  1738. X        n = 0;
  1739. X        XtSetArg (args[n], XmNmnemonic, 'F'); n++;
  1740. X        tb2 = XmCreateToggleButton (pull_right, "Fast", args, n);
  1741. X        XtAddCallback (tb2, XmNvalueChangedCallback, pref_algo_cb,
  1742. X                            (XtPointer)PREF_FAST);
  1743. X        XtManageChild (tb2);
  1744. X
  1745. X        if (XmToggleButtonGetState(tb1))
  1746. X        prefs[PREF_ALGO] = PREF_ACCURATE;
  1747. X        else if (XmToggleButtonGetState(tb2))
  1748. X        prefs[PREF_ALGO] = PREF_FAST;
  1749. X        else {
  1750. X        xe_msg ("Neither Alogirthms preference is set -- defaulting to Accurate\n", 0);
  1751. X        XmToggleButtonSetState (tb1, True, False);
  1752. X        prefs[PREF_ALGO] = PREF_ACCURATE;
  1753. X        }
  1754. X
  1755. X        n = 0;
  1756. X        XtSetArg (args[n], XmNsubMenuId, pull_right);  n++;
  1757. X        XtSetArg (args[n], XmNmnemonic, 'A'); n++;
  1758. X        cascade = XmCreateCascadeButton (menu_pane, "AlgorithmsCB",args,n);
  1759. X        XtManageChild (cascade);
  1760. X        set_xmstring (cascade, XmNlabelString, "Algorithms");
  1761. X
  1762. X        /* create the date formats pullright menu */
  1763. X
  1764. X        n = 0;
  1765. X        XtSetArg (args[n], XmNradioBehavior, True); n++;
  1766. X        pull_right = XmCreatePulldownMenu (menu_pane, "DateFormat",args,n);
  1767. X
  1768. X        n = 0;
  1769. X        XtSetArg (args[n], XmNmnemonic, 'm'); n++;
  1770. X        tb1 = XmCreateToggleButton (pull_right, "MDY", args, n);
  1771. X        XtManageChild (tb1);
  1772. X        XtAddCallback (tb1, XmNvalueChangedCallback, pref_date_cb,
  1773. X                            (XtPointer)PREF_MDY);
  1774. X        set_xmstring (tb1, XmNlabelString, "M/D/Y");
  1775. X        n = 0;
  1776. X        XtSetArg (args[n], XmNmnemonic, 'y'); n++;
  1777. X        tb2 = XmCreateToggleButton (pull_right, "YMD", args, n);
  1778. X        XtAddCallback (tb2, XmNvalueChangedCallback, pref_date_cb,
  1779. X                            (XtPointer)PREF_YMD);
  1780. X        XtManageChild (tb2);
  1781. X        set_xmstring (tb2, XmNlabelString, "Y/M/D");
  1782. X        n = 0;
  1783. X        XtSetArg (args[n], XmNmnemonic, 'd'); n++;
  1784. X        tb3 = XmCreateToggleButton (pull_right, "DMY", args, n);
  1785. X        XtAddCallback (tb3, XmNvalueChangedCallback, pref_date_cb,
  1786. X                            (XtPointer)PREF_DMY);
  1787. X        XtManageChild (tb3);
  1788. X        set_xmstring (tb3, XmNlabelString, "D/M/Y");
  1789. X
  1790. X        if (XmToggleButtonGetState(tb1))
  1791. X        prefs[PREF_DATE_FORMAT] = PREF_MDY;
  1792. X        else if (XmToggleButtonGetState(tb2))
  1793. X        prefs[PREF_DATE_FORMAT] = PREF_YMD;
  1794. X        else if (XmToggleButtonGetState(tb3))
  1795. X        prefs[PREF_DATE_FORMAT] = PREF_DMY;
  1796. X        else {
  1797. X        xe_msg ("No DateFormat preference is set -- defaulting to MDY\n", 0);
  1798. X        XmToggleButtonSetState (tb1, True, False);
  1799. X        prefs[PREF_DATE_FORMAT] = PREF_MDY;
  1800. X        }
  1801. X
  1802. X        n = 0;
  1803. X        XtSetArg (args[n], XmNsubMenuId, pull_right);  n++;
  1804. X        XtSetArg (args[n], XmNmnemonic, 'D'); n++;
  1805. X        cascade = XmCreateCascadeButton (menu_pane, "DateFormatCB",args, n);
  1806. X        XtManageChild (cascade);
  1807. X        set_xmstring (cascade, XmNlabelString, "Date formats");
  1808. X
  1809. X        /* create the units pullright menu */
  1810. X
  1811. X        n = 0;
  1812. X        XtSetArg (args[n], XmNradioBehavior, True); n++;
  1813. X        pull_right = XmCreatePulldownMenu (menu_pane, "Units", args,n);
  1814. X
  1815. X        n = 0;
  1816. X        XtSetArg (args[n], XmNmnemonic, 'E'); n++;
  1817. X        tb1 = XmCreateToggleButton (pull_right, "English", args, n);
  1818. X        XtAddCallback (tb1, XmNvalueChangedCallback, pref_units_cb,
  1819. X                            (XtPointer)PREF_ENGLISH);
  1820. X        XtManageChild (tb1);
  1821. X
  1822. X        n = 0;
  1823. X        XtSetArg (args[n], XmNmnemonic, 'M'); n++;
  1824. X        tb2 = XmCreateToggleButton (pull_right, "Metric", args, n);
  1825. X        XtAddCallback (tb2, XmNvalueChangedCallback, pref_units_cb,
  1826. X                            (XtPointer)PREF_METRIC);
  1827. X        XtManageChild (tb2);
  1828. X
  1829. X        if (XmToggleButtonGetState(tb1))
  1830. X        prefs[PREF_UNITS] = PREF_ENGLISH;
  1831. X        else if (XmToggleButtonGetState(tb2))
  1832. X        prefs[PREF_UNITS] = PREF_METRIC;
  1833. X        else {
  1834. X        xe_msg ("Neither Units preference is set -- defaulting to English\n", 0);
  1835. X        XmToggleButtonSetState (tb1, True, False);
  1836. X        prefs[PREF_UNITS] = PREF_ENGLISH;
  1837. X        }
  1838. X
  1839. X        n = 0;
  1840. X        XtSetArg (args[n], XmNsubMenuId, pull_right);  n++;
  1841. X        XtSetArg (args[n], XmNmnemonic, 'U'); n++;
  1842. X        cascade = XmCreateCascadeButton (menu_pane, "UnitsCB", args, n);
  1843. X        XtManageChild (cascade);
  1844. X        set_xmstring (cascade, XmNlabelString, "Units");
  1845. X
  1846. X    n = 0;
  1847. X    XtSetArg (args[n], XmNsubMenuId, menu_pane);  n++;
  1848. X    XtSetArg (args[n], XmNmnemonic, 'P'); n++;
  1849. X    cascade = XmCreateCascadeButton (menu_bar, "PreferencesCB", args, n);
  1850. X    set_xmstring (cascade, XmNlabelString, "Preferences");
  1851. X    XtManageChild (cascade);
  1852. X}
  1853. X
  1854. X/* called anytime we want to know a preference.
  1855. X */
  1856. Xint
  1857. Xpref_get(pref)
  1858. Xint pref;
  1859. X{
  1860. X    return (prefs[pref]);
  1861. X}
  1862. X
  1863. X/* called when a PREF_ALGO preference changes.
  1864. X * the new value is in client.
  1865. X */
  1866. X/* ARGSUSED */
  1867. Xstatic void
  1868. Xpref_algo_cb (w, client, call)
  1869. XWidget w;
  1870. XXtPointer client;
  1871. XXtPointer call;
  1872. X{
  1873. X    XmToggleButtonCallbackStruct *s = (XmToggleButtonCallbackStruct *)call;
  1874. X
  1875. X    if (s->set) {
  1876. X        prefs[PREF_ALGO] = (int)client;
  1877. X        redraw_screen (1);
  1878. X    }
  1879. X}
  1880. X
  1881. X/* called when a PREF_DATE_FORMAT preference changes.
  1882. X * the new value is in client.
  1883. X */
  1884. X/* ARGSUSED */
  1885. Xstatic void
  1886. Xpref_date_cb (w, client, call)
  1887. XWidget w;
  1888. XXtPointer client;
  1889. XXtPointer call;
  1890. X{
  1891. X    XmToggleButtonCallbackStruct *s = (XmToggleButtonCallbackStruct *)call;
  1892. X
  1893. X    if (s->set) {
  1894. X        prefs[PREF_DATE_FORMAT] = (int)client;
  1895. X        redraw_screen (1);
  1896. X    }
  1897. X}
  1898. X
  1899. X/* called when a PREF_UNITS preference changes.
  1900. X * the new value is in client.
  1901. X */
  1902. X/* ARGSUSED */
  1903. Xstatic void
  1904. Xpref_units_cb (w, client, call)
  1905. XWidget w;
  1906. XXtPointer client;
  1907. XXtPointer call;
  1908. X{
  1909. X    XmToggleButtonCallbackStruct *s = (XmToggleButtonCallbackStruct *)call;
  1910. X
  1911. X    if (s->set) {
  1912. X        prefs[PREF_UNITS] = (int)client;
  1913. X        redraw_screen (1);
  1914. X    }
  1915. X}
  1916. END_OF_FILE
  1917.   if test 7270 -ne `wc -c <'preferences.c'`; then
  1918.     echo shar: \"'preferences.c'\" unpacked with wrong size!
  1919.   fi
  1920.   # end of 'preferences.c'
  1921. fi
  1922. if test -f 'skyviewmenu.c.3' -a "${1}" != "-c" ; then 
  1923.   echo shar: Will not clobber existing file \"'skyviewmenu.c.3'\"
  1924. else
  1925.   echo shar: Extracting \"'skyviewmenu.c.3'\" \(21068 characters\)
  1926.   sed "s/^X//" >'skyviewmenu.c.3' <<'END_OF_FILE'
  1927. X    } else {
  1928. X        label = (pu.op->o_flags ^= OBJF_LABEL) & OBJF_LABEL;
  1929. X        if (label) {
  1930. X        sv_getcircle (&w, &h, &r, &xb, &yb);
  1931. X        (void) sv_dbobjloc (pu.op, r, &x, &y);
  1932. X        name = pu.op->o_name;
  1933. X        }
  1934. X    }
  1935. X
  1936. X    if (label) {
  1937. X        /* label is being turned on so draw it */
  1938. X        Display *dsp = XtDisplay(svda_w);
  1939. X        Window win = sv_pm;
  1940. X        GC gc;
  1941. X        x += xb;
  1942. X        y += yb;
  1943. X        obj_pickgc (pu.op, svda_w, &gc);
  1944. X        draw_label (dsp, win, gc, name, x, y);
  1945. X        sv_copy_sky();
  1946. X    } else {
  1947. X        /* label is being turned off so redraw */
  1948. X        sv_all (mm_get_now(), 1);
  1949. X    }
  1950. X}
  1951. X
  1952. X/* remove trails no longer wanted. */
  1953. Xstatic void
  1954. Xtobj_rmoff()
  1955. X{
  1956. X    TrailObj **topp;    /* address to be changed if we decide to 
  1957. X                 * remove *topp
  1958. X                 */
  1959. X    TrailObj *top;        /* handy *topp */
  1960. X
  1961. X    for (topp = &trailobj; (top = *topp) != NULL; ) {
  1962. X        if (top->on) {
  1963. X        topp = &top->ntop;
  1964. X        } else {
  1965. X        *topp = top->ntop;
  1966. X        XtFree ((char *)top);
  1967. X        }
  1968. X    }
  1969. X}
  1970. X
  1971. X/* remove the trailobj list that contains the given pointer.
  1972. X * we have to search each trail list to find the one with this pointer.
  1973. X * it might be the one on TrailObj itself or one of the older ones on
  1974. X *    the TSky list.
  1975. X */
  1976. Xstatic void
  1977. Xtobj_rmobj (op)
  1978. XObj *op;
  1979. X{
  1980. X    TrailObj **topp;    /* address to be changed if we decide to 
  1981. X                 * remove *topp
  1982. X                 */
  1983. X    TrailObj *top;        /* handy *topp */
  1984. X
  1985. X    for (topp = &trailobj; (top = *topp) != NULL; ) {
  1986. X        int i;
  1987. X        if (top->op == op)
  1988. X        goto out;
  1989. X        for (i = 0; i < top->nsky; i++)
  1990. X        if (&top->sky[i].o == op)
  1991. X            goto out;
  1992. X        topp = &top->ntop;
  1993. X    }
  1994. X
  1995. X    out:
  1996. X
  1997. X    if (!top)
  1998. X        return;    /* oh well */
  1999. X
  2000. X    *topp = top->ntop;
  2001. X    XtFree ((char *)top);
  2002. X}
  2003. X
  2004. X/* add a new empty entry to the trailobj list for db object op.
  2005. X * return a pointer to the new TrailObj.
  2006. X */
  2007. Xstatic TrailObj *
  2008. Xtobj_addobj (op)
  2009. XObj *op;
  2010. X{
  2011. X    TrailObj *top;
  2012. X
  2013. X    /* don't forget there is inherently room for one TSky in a TrailObj */
  2014. X    top = (TrailObj *)
  2015. X        XtMalloc (sizeof(TrailObj) + (TRAILCHUNKS-1)*sizeof(TSky));
  2016. X    top->nskymem = TRAILCHUNKS; /* there is room for TRAILCHUNKS TSkys .. */
  2017. X    top->nsky = 0;      /* though none are in use in our new one */
  2018. X    top->op = op;
  2019. X    top->on = 1;
  2020. X
  2021. X    /* link directly off trailobj -- order is unimportant */
  2022. X    top->ntop = trailobj;
  2023. X    trailobj = top;
  2024. X
  2025. X    return (top);
  2026. X}
  2027. X
  2028. X/* increase the number of Sky's top can hold.
  2029. X * since we may have to move top to do it, return the new pointer.
  2030. X */
  2031. Xstatic TrailObj *
  2032. Xtobj_growsky (top)
  2033. XTrailObj *top;
  2034. X{
  2035. X    TrailObj *ltop;
  2036. X    TrailObj *newtop;
  2037. X    int newn;
  2038. X
  2039. X    /* set ltop to the TrailObj in the list just before top */
  2040. X    if (trailobj == top)
  2041. X        ltop = NULL;
  2042. X    else {
  2043. X        for (ltop=trailobj; ltop; ltop=ltop->ntop)
  2044. X        if (ltop->ntop == top)
  2045. X            break;
  2046. X        if (!ltop) {
  2047. X        printf ("tobj_growsky(): top not found!\n");
  2048. X        exit (1);
  2049. X        }
  2050. X    }
  2051. X
  2052. X    /* don't forget there is already one TSky within a TrailObj. */
  2053. X    newn = top->nskymem + TRAILCHUNKS;
  2054. X    newtop = (TrailObj *) XtRealloc ((char *)top,
  2055. X                sizeof(TrailObj) + (newn-1)*sizeof(TSky));
  2056. X    if (ltop)
  2057. X        ltop->ntop = newtop;
  2058. X    else
  2059. X        trailobj = newtop;
  2060. X    newtop->nskymem = newn;
  2061. X    return (newtop);
  2062. X}
  2063. X
  2064. X/* empty the trailobj list and reclaim all space.
  2065. X */
  2066. Xstatic void
  2067. Xtobj_reset()
  2068. X{
  2069. X    TrailObj *top, *ntop;
  2070. X
  2071. X    for (top = trailobj; top; top = ntop) {
  2072. X        ntop = top->ntop;
  2073. X        XtFree ((char *)top);
  2074. X    }
  2075. X
  2076. X    trailobj = NULL;
  2077. X}
  2078. X
  2079. X/* find the TrailObj that contains op */
  2080. Xstatic TrailObj *
  2081. Xtobj_find (op)
  2082. XObj *op;
  2083. X{
  2084. X    TrailObj *top;
  2085. X
  2086. X    for (top = trailobj; top; top = top->ntop) {
  2087. X        int i;
  2088. X        if (top->op == op)
  2089. X        return (top);
  2090. X        for (i = 0; i < top->nsky; i++)
  2091. X        if (&top->sky[i].o == op)
  2092. X            return (top);
  2093. X    }
  2094. X
  2095. X    return (NULL);
  2096. X}
  2097. X
  2098. X/* add an Obj to the given trailobj, top.
  2099. X * mark it as being valid as of jd (which is really an mjd).
  2100. X * these are maintained in increasing order of time, ie, the first is the
  2101. X * earliest. we take care not to add one for an identical time already in
  2102. X * the list. since we might have to move top to grow it, we return a (possibly
  2103. X * different) pointer.
  2104. X */
  2105. Xstatic TrailObj *
  2106. Xtobj_addsky (top, jd, op)
  2107. XTrailObj *top;
  2108. Xdouble jd;
  2109. XObj *op;
  2110. X{
  2111. X    int i;
  2112. X
  2113. X    /* make sure there is room for one more */
  2114. X    if (top->nsky == top->nskymem)
  2115. X        top = tobj_growsky (top);
  2116. X
  2117. X    /* add op to top->sky in ascending time order.
  2118. X     * exit loop with i as the index of the cell to use.
  2119. X     */
  2120. X    for (i = top->nsky; i > 0; --i)
  2121. X        if (top->sky[i-1].ts_mjd < jd)
  2122. X        break;
  2123. X        else if (top->sky[i-1].ts_mjd == jd)
  2124. X        return (top);    /* don't add a dup */
  2125. X        else
  2126. X        top->sky[i] = top->sky[i-1];
  2127. X
  2128. X    top->sky[i].flags = 0;
  2129. X    top->sky[i].ts_mjd = jd;
  2130. X    top->sky[i].o = *op;
  2131. X    top->nsky++;
  2132. X
  2133. X    return (top);
  2134. X}
  2135. X
  2136. X/* display everything in the trailobj list that is marked on onto sv_pm
  2137. X * clipped to a circle of radius r, offset by xb and yb borders.
  2138. X */
  2139. Xstatic void
  2140. Xtobj_display_all(r, xb, yb)
  2141. Xunsigned r, xb, yb;
  2142. X{
  2143. X    Display *dsp = XtDisplay(svda_w);
  2144. X    Window win = sv_pm;
  2145. X    TrailObj *top;
  2146. X
  2147. X    for (top = trailobj; top; top = top->ntop) {
  2148. X        int x1, y1, x2, y2;
  2149. X        int before;
  2150. X        Obj *op;
  2151. X        GC gc;
  2152. X        int i;
  2153. X
  2154. X        if (!top->on)
  2155. X        continue;
  2156. X
  2157. X        obj_pickgc(top->op, svda_w, &gc);
  2158. X        before = 0;
  2159. X
  2160. X        for (i = 0; i < top->nsky; i++) {
  2161. X        op = &top->sky[i].o;
  2162. X        if (sv_trailobjloc (&top->sky[i], r, &x2, &y2)) {
  2163. X            sv_draw_obj (dsp, win, gc, op, x2+xb, y2+yb,
  2164. X                magdiam(op->s_mag/MAGSCALE), justdots);
  2165. X            if (all_labels || (top->sky[i].flags & OBJF_LABEL))
  2166. X            draw_label (dsp, win, gc, op->o_name, x2+xb, y2+yb);
  2167. X        }
  2168. X        if (before++) {
  2169. X            int sx1, sy1, sx2, sy2;
  2170. X            if (lc(0,0,r*2,x1,y1,x2,y2,&sx1,&sy1,&sx2,&sy2) == 0)
  2171. X            XDrawLine (dsp, win, gc, sx1+xb, sy1+yb, sx2+xb,sy2+yb);
  2172. X        }
  2173. X        x1 = x2;
  2174. X        y1 = y2;
  2175. X        }
  2176. X
  2177. X    }
  2178. X
  2179. X    sv_draw_obj (dsp, win, (GC)0, NULL, 0, 0, 0, 0);    /* flush */
  2180. X}
  2181. X
  2182. X/* determine if the given object is visible and within a circle of radius r
  2183. X * pixels. if so, return 1 and compute the location in *xp/*yp, else return 0.
  2184. X * N.B. only call this for bona fide db objects -- *not* for objects in the
  2185. X *   TrailObj lists -- it will destroy their history.
  2186. X */
  2187. Xstatic
  2188. Xsv_dbobjloc (op, r, xp, yp)
  2189. XObj *op;
  2190. Xint r;
  2191. Xint *xp, *yp;
  2192. X{
  2193. X    double altdec, azra;
  2194. X
  2195. X    if (!sv_precheck(op))
  2196. X        return (0);
  2197. X
  2198. X    /* remaining things need accurate s_* fields */
  2199. X    db_update(op);
  2200. X
  2201. X    if (aa_mode && op->s_alt < 0.0)
  2202. X        return(0);    /* it's below horizon and we're in alt-az mode */
  2203. X
  2204. X    if (op->s_mag/MAGSCALE > fmag || op->s_mag/MAGSCALE < bmag)
  2205. X        return(0);    /* it's not within mag range after all */
  2206. X
  2207. X    altdec = aa_mode ? op->s_alt : op->s_dec;
  2208. X    azra   = aa_mode ? op->s_az  : op->s_ra;
  2209. X    if (!sv_loc (r, altdec, azra, xp, yp))
  2210. X        return(0);     /* it's outside the fov after all */
  2211. X
  2212. X    return (1);    /* yup, really within r */
  2213. X}
  2214. X
  2215. X/* given a TSky find its location in a circle of radius r, all in pixels.
  2216. X * return 1 if the resulting x/y is in fact within the circle, else 0 if it is
  2217. X *   outside or otherwise should not be shown now (but return the x/y anyway).
  2218. X * N.B. we take care to not change the tsp->o in any way.
  2219. X */
  2220. Xstatic
  2221. Xsv_trailobjloc (tsp, r, xp, yp)
  2222. XTSky *tsp;
  2223. Xint r;
  2224. Xint *xp, *yp;
  2225. X{
  2226. X    Obj *op = &tsp->o;
  2227. X    double altdec, azra;
  2228. X    int infov;
  2229. X
  2230. X    altdec = aa_mode ? op->s_alt : op->s_dec;
  2231. X    azra   = aa_mode ? op->s_az  : op->s_ra;
  2232. X    infov = sv_loc (r, altdec, azra, xp, yp);
  2233. X    return (infov && (!aa_mode || op->s_alt >= 0.0) && sv_precheck(op)?1:0);
  2234. X}
  2235. X
  2236. X/* do as much as possible to pre-check whether op is on screen now
  2237. X * WITHOUT computing it's actual coordinates. put another way, we are not to
  2238. X * use and s_* fields in these tests.
  2239. X * return 0 if we know it's definitely not on screen, or 1 if it might be.
  2240. X */
  2241. Xstatic
  2242. Xsv_precheck (op)
  2243. XObj *op;
  2244. X{
  2245. X    if (op->type == UNDEFOBJ)
  2246. X        return(0);
  2247. X
  2248. X    if (!svf_filter_ok(op) || !sv_bright_ok(op) || !sv_infov(op))
  2249. X        return(0);    /* wrong type, wrong brightness or outside for sure */
  2250. X    
  2251. X    return (1);
  2252. X}
  2253. X
  2254. X/* return 1 if db object is ever possibly within the fmag/bmag range; else 0.
  2255. X */
  2256. Xstatic
  2257. Xsv_bright_ok(op)
  2258. XObj *op;
  2259. X{
  2260. X    switch (op->type) {
  2261. X    case PLANET:
  2262. X        /* always go for the planets for now but ..
  2263. X         * TODO: work up a table of extreme planet magnitudes.
  2264. X         */
  2265. X        return (1);
  2266. X        /* break; */
  2267. X    case HYPERBOLIC: return (1);    /* and interlopers */
  2268. X    case PARABOLIC: return (1);
  2269. X    case ELLIPTICAL: {
  2270. X        double mag;        /* magnitude */
  2271. X        double per, aph;    /* perihelion and aphelion distance */
  2272. X
  2273. X        per = op->e_a*(1.0 - op->e_e);
  2274. X        aph = op->e_a*(1.0 + op->e_e);
  2275. X        if (per <= 1.1 && aph >= 0.9)
  2276. X        return (1); /* might be blazing in the back yard some day */
  2277. X        if (op->e_mag.whichm == MAG_HG)
  2278. X         mag = op->e_mag.m1 + 5*log10(per*fabs(per-1.0));
  2279. X        else
  2280. X         gk_mag(op->e_mag.m1, op->e_mag.m2,
  2281. X                        per, fabs(per-1.0), &mag);
  2282. X        return (mag <= fmag && mag >= bmag);
  2283. X        /* break; */
  2284. X        }
  2285. X    case FIXED:
  2286. X        return (op->f_mag/MAGSCALE <= fmag && op->f_mag/MAGSCALE >= bmag);
  2287. X        /* break; */
  2288. X    default: 
  2289. X        printf ("sv_bright_ok(): bad type: %d\n", op->type);
  2290. X        exit (1);
  2291. X        return (0);    /* for lint */
  2292. X    }
  2293. X}
  2294. X
  2295. X/* return 1 if the object can potentially be within the current sv_fov, else 0.
  2296. X * N.B. this is meant to be cheap - we only do fixed objects and we don't
  2297. X *      precess. most importantly, we don't use any s_* fields.
  2298. X */
  2299. Xstatic
  2300. Xsv_infov (op)
  2301. XObj *op;
  2302. X{
  2303. X#define    DELEP    100        /* maximum epoch difference we dare go without
  2304. X                 * precessing, years
  2305. X                 */
  2306. X#define    MARGIN    degrad(3.0)    /* border around fov still considered "in"
  2307. X                 * in spite of having not precessed.
  2308. X                 */
  2309. X    double ra0, dec0;    /* ra/dec of our center of view */
  2310. X    double a, sa, ca;    /* angle from viewpoint to pole */
  2311. X    double b, sb, cb;    /* angle from object to pole */
  2312. X    double c, cc;        /* diff of polar angles of obj and viewpoint */
  2313. X    double d;        /* angular separation of object and viewpoint */
  2314. X    Now *np = mm_get_now();
  2315. X
  2316. X    if (op->type != FIXED)
  2317. X        return (1);
  2318. X    if (fabs (mjd - op->f_epoch) > DELEP)
  2319. X        return (1);
  2320. X
  2321. X    if (aa_mode) {
  2322. X        /* TODO: cache this -- it's the same for each obj! */
  2323. X        double ha, lst;
  2324. X        aa_hadec (lat, sv_altdec, sv_azra, &ha, &dec0);
  2325. X        now_lst (np, &lst);
  2326. X        ra0 = hrrad(lst) - ha;
  2327. X        range (&ra0, 2*PI);
  2328. X    } else {
  2329. X        ra0 = sv_azra;
  2330. X        dec0 = sv_altdec;
  2331. X    }
  2332. X
  2333. X    a = PI/2 - dec0;
  2334. X    sa = sin(a);
  2335. X    ca = cos(a);
  2336. X    b = PI/2 - op->f_dec;
  2337. X    sb = sin(b);
  2338. X    cb = cos(b);
  2339. X    c = ra0 - op->f_RA;
  2340. X    cc = cos(c);
  2341. X    d = acos(ca*cb + sa*sb*cc);
  2342. X    return (d < sv_fov/2 + MARGIN);
  2343. X}
  2344. X
  2345. X/* compute x/y loc of a point at azra/altdec on a circle of radius rad pixels
  2346. X *   as viewed from sv_azra/sv_altdec with sv_fov.
  2347. X * return 1 if fits on screen, else 0 (but still return x/y).
  2348. X */
  2349. Xstatic
  2350. Xsv_loc (rad, altdec, azra, xp, yp)
  2351. Xint rad;    /* radius of target display, pixels */
  2352. Xdouble altdec;    /* angle up from spherical equator, such as alt or dec; rad */
  2353. Xdouble azra;    /* angle around spherical pole, such as az or ra; rad */
  2354. Xint *xp, *yp;    /* return X coords within circle */
  2355. X{
  2356. X#define    LOCEPS    (1e-5)    /* an angle too small to see on screen, rads */
  2357. X    double a,sa,ca;    /* angle from viewpoint to pole */
  2358. X    double b,sb,cb;    /* angle from object to pole */
  2359. X    double c,sc,cc;    /* difference in polar angles of obj and viewpoint */
  2360. X    double d,sd,cd;    /* angular separation of object and viewpoint */
  2361. X    double r;    /* proportion of d to desired field of view */
  2362. X    double se, ce;    /* angle between (viewpoint,pole) and (viewpoint,obj) */
  2363. X
  2364. X    a = PI/2 - sv_altdec;
  2365. X    sa = sin(a);
  2366. X    ca = cos(a);
  2367. X    b = PI/2 - altdec;
  2368. X    sb = sin(b);
  2369. X    cb = cos(b);
  2370. X    if (aa_mode)
  2371. X        c = azra - sv_azra;
  2372. X    else
  2373. X        c = sv_azra - azra;
  2374. X    cc = cos(c);
  2375. X    d = acos(ca*cb + sa*sb*cc);
  2376. X    if (d < LOCEPS) {
  2377. X        *xp = *yp = rad;
  2378. X        return (1);
  2379. X    }
  2380. X
  2381. X    r = d/(sv_fov/2.0);
  2382. X
  2383. X    sc = sin(c);
  2384. X    sd = sin(d);
  2385. X    se = sc*sb/sd;
  2386. X    *xp = rad*(1 + r*se) + 0.5;
  2387. X    if (a < LOCEPS) {
  2388. X        /* as viewpoint approaches N pole, e approaches PI - c */
  2389. X        ce = -cc;
  2390. X    } else if (a > PI - LOCEPS) {
  2391. X        /* as viewpoint approaches S pole, e approaches c */
  2392. X        ce = cc;
  2393. X    } else {
  2394. X        cd = cos(d);
  2395. X        ce = (cb - cd*ca)/(sd*sa);
  2396. X    }
  2397. X    *yp = rad*(1 - r*ce) + 0.5;
  2398. X
  2399. X    return (r >= 1.0 ? 0 : 1);
  2400. X}
  2401. X
  2402. X/* compute azra/altdec loc of a point at x/y on a circle of radius rad pixels
  2403. X *   as viewed from sv_azra/sv_altdec with sv_fov.
  2404. X * return 1 if x/y are within the circle, else 0.
  2405. X */
  2406. Xstatic
  2407. Xsv_unloc (rad, x, y, altdecp, azrap)
  2408. Xint rad;    /* radius of target display, pixels */
  2409. Xint x, y;    /* X coords within circle */
  2410. Xdouble *altdecp;/* angle up from spherical equator, such as alt or dec; rad */
  2411. Xdouble *azrap;    /* angle around spherical pole, such as az or ra; rad */
  2412. X{
  2413. X#define    UNLOCEPS (1e-4)    /* sufficiently close to pole to not know az/ra; rads */
  2414. X    double a,sa,ca;    /* angle from viewpoint to pole */
  2415. X    double r;    /* distance from center to object, pixels */
  2416. X    double d,sd,cd;    /* angular separation of object and viewpoint */
  2417. X    double e,se,ce;    /* angle between (viewpoint,pole) and (viewpoint,obj) */
  2418. X    double b,sb,cb;    /* angle from object to pole */
  2419. X    double c,sc,cc;    /* difference in polar angles of obj and viewpoint */
  2420. X
  2421. X    if (x == rad && y == rad) {
  2422. X        /* at the center -- avoids cases where r == 0 */
  2423. X        *altdecp = sv_altdec;
  2424. X        *azrap = sv_azra;
  2425. X        return (1);
  2426. X    }
  2427. X
  2428. X    a = PI/2 - sv_altdec;
  2429. X    sa = sin(a);
  2430. X    ca = cos(a);
  2431. X
  2432. X    r = sqrt ((double)((x-rad)*(x-rad) + (y-rad)*(y-rad)));
  2433. X    if (r > rad)
  2434. X        return(0); /* outside the circle */
  2435. X
  2436. X    d = r/rad*(sv_fov/2.0);
  2437. X    sd = sin(d);
  2438. X    cd = cos(d);
  2439. X    ce = (rad - y)/r;
  2440. X    se = (x - rad)/r;
  2441. X    cb = ca*cd + sa*sd*ce;
  2442. X    b = acos(cb);
  2443. X    *altdecp = PI/2 - b;
  2444. X
  2445. X    /* find c, the polar angle between viewpoint and object */
  2446. X    if (a < UNLOCEPS) {
  2447. X        /* as viewpoint approaches N pole, c approaches PI - e */
  2448. X        c = acos(-ce);
  2449. X    } else if (a > PI - UNLOCEPS) {
  2450. X        /* as viewpoint approaches S pole, c approaches e */
  2451. X        c = acos(ce);
  2452. X    } else if (b < UNLOCEPS || b > PI - UNLOCEPS) {
  2453. X        /* as object approaches either pole, c becomes arbitary */
  2454. X        c = 0.0;
  2455. X    } else {
  2456. X        sb = sin(b);
  2457. X        cc = (cd - ca*cb)/(sa*sb);
  2458. X        if (cc < -1.0) cc = -1.0;    /* heh, it happens ... */
  2459. X        if (cc >  1.0) cc =  1.0;    /* heh, it happens ... */
  2460. X        c = acos (cc);        /* 0 .. PI; next step checks if c
  2461. X                     * should be > PI
  2462. X                     */
  2463. X    }
  2464. X    if (se < 0.0)         /* if e > PI */
  2465. X        c = PI + (PI - c);    /*     so is c */
  2466. X
  2467. X    if (aa_mode)
  2468. X        *azrap = sv_azra + c;
  2469. X    else
  2470. X        *azrap = sv_azra - c;
  2471. X    range (azrap, 2*PI);
  2472. X
  2473. X    return (1);
  2474. X}
  2475. X
  2476. X/* draw a nice grid on a circle of radius r, x and y borders xb and yb.
  2477. X */
  2478. Xstatic void
  2479. Xdraw_grid(dsp, win, gc, r, xb, yb)
  2480. XDisplay *dsp;
  2481. XWindow win;
  2482. XGC gc;
  2483. Xunsigned int r;
  2484. Xunsigned int xb, yb;
  2485. X{
  2486. X    double vticks[NGRID], hticks[NGRID];
  2487. X    double vmin, vmax, hmin, hmax;
  2488. X    XSegment xsegments[NGRID*NSEGS], *xs;
  2489. X    char msg[64];
  2490. X    int nvt, nht;
  2491. X    int i, j;
  2492. X    int pole;
  2493. X
  2494. X    /* set vertical min and max, and detect whether pole is within fov.
  2495. X     * since display is in degrees, use that unit for finding ticks.
  2496. X     */
  2497. X    pole = 0;
  2498. X    vmin = sv_altdec-sv_fov/2;
  2499. X    if (vmin < 0 && aa_mode)
  2500. X        vmin = 0.0;
  2501. X    if (vmin <= -PI/2) {
  2502. X        /* clamp at pole */
  2503. X        vmin = -PI/2;
  2504. X        pole = 1;
  2505. X    }
  2506. X    vmax = sv_altdec+sv_fov/2;
  2507. X    if (vmax >= PI/2) {
  2508. X        /* clamp at pole */
  2509. X        vmax = PI/2;
  2510. X        pole = 1;
  2511. X    }
  2512. X    vmin = raddeg(vmin);
  2513. X    vmax = raddeg(vmax);
  2514. X
  2515. X    /* set horizontal min and max.
  2516. X     * if pole is visible, we go all the way around.
  2517. X     * else compute spherical angle spanned by fov "del" from pole.
  2518. X     * again, compute ticks in the units we display in.
  2519. X     */
  2520. X    if (pole) {
  2521. X        /* pole is visible */
  2522. X        hmin = 0.0;
  2523. X        hmax = 2*PI;
  2524. X    } else {
  2525. X        double del = PI/2 - fabs(sv_altdec);
  2526. X        double a= acos((cos(sv_fov) - cos(del)*cos(del))/sin(del)/sin(del));
  2527. X        hmin = sv_azra-a/2;
  2528. X        hmax = sv_azra+a/2;
  2529. X    }
  2530. X    hmin = aa_mode ? raddeg(hmin) : radhr(hmin);
  2531. X    hmax = aa_mode ? raddeg(hmax) : radhr(hmax);
  2532. X
  2533. X    /* find tick marks.
  2534. X     * generally get less than half the max, so insure it to be consistent.
  2535. X     * N.B. remember that tickmarks() can return up to 2 more than asked.
  2536. X     */
  2537. X    nvt = tickmarks(vmin, vmax, NGRID-2, vticks);
  2538. X    nht = tickmarks(hmin, hmax, NGRID-2, hticks);
  2539. X
  2540. X    /* report the spacing */
  2541. X    (void) sprintf (msg, "%s: %g Degs", aa_mode ? "Alt" : "Dec",
  2542. X                        (vticks[nvt-1]-vticks[0])/(nvt-1));
  2543. X    f_showit (vgrid_w, msg);
  2544. X    (void) sprintf (msg, " %s: %g %s", aa_mode ? "Az" : "RA",
  2545. X        (hticks[nht-1]-hticks[0])/(nht-1), aa_mode ? "Degs" : "Hrs");
  2546. X    f_showit (hgrid_w, msg);
  2547. X
  2548. X    /* convert back to rads */
  2549. X    for (i = 0; i < nvt; i++)
  2550. X        vticks[i] = degrad(vticks[i]);
  2551. X    for (i = 0; i < nht; i++)
  2552. X        hticks[i] = aa_mode ? degrad(hticks[i]) : hrrad(hticks[i]);
  2553. X
  2554. X    /* for each horizontal tick mark
  2555. X     *   for each vertical tick mark
  2556. X     *     compute coord on screen
  2557. X     *     if we've at least 2 pts now
  2558. X     *       connect the points with what is visible within the circle.
  2559. X     */
  2560. X    for (i = 0; i < nht; i += 1) {
  2561. X        double h = hticks[i];
  2562. X        int before = 0;
  2563. X        int vis1, vis2;
  2564. X        int x1, y1, x2, y2;
  2565. X        xs = xsegments;
  2566. X        for (j = 0; j < nvt; j++) {
  2567. X        double v = vticks[j];
  2568. X        vis2 = sv_loc(r, v, h, &x2, &y2);
  2569. X        if (before++ && (vis1 || vis2)) {
  2570. X            int sx1, sy1, sx2, sy2;
  2571. X            if (lc(0,0,r*2,x1,y1,x2,y2,&sx1,&sy1,&sx2,&sy2) == 0) {
  2572. X            xs->x1 = sx1+xb; xs->y1 = sy1+yb;
  2573. X            xs->x2 = sx2+xb; xs->y2 = sy2+yb;
  2574. X            xs++;
  2575. X            }
  2576. X        }
  2577. X        x1 = x2;
  2578. X        y1 = y2;
  2579. X        vis1 = vis2;
  2580. X        }
  2581. X        XDrawSegments (dsp, win, gc, xsegments, xs - xsegments);
  2582. X    }
  2583. X
  2584. X    /* for each vertical tick mark
  2585. X     *   for each horizontal tick mark
  2586. X     *     compute coord on screen
  2587. X     *     if we've at least 2 pts now
  2588. X     *       connect the points with what is visible within the circle.
  2589. X     *     (break into smaller pieces because these lines tend to curve)
  2590. X     */
  2591. X    for (i = 0; i < nvt; i+=1) {
  2592. X        double v = vticks[i];
  2593. X        double h1;
  2594. X        int before = 0;
  2595. X        int vis1, vis2;
  2596. X        int x1, y1, x2, y2;
  2597. X        xs = xsegments;
  2598. X        for (j = 0; j < nht; j++) {
  2599. X        double h = hticks[j];
  2600. X        vis2 = sv_loc(r, v, h, &x2, &y2);
  2601. X        if (before++ && (vis1 || vis2)) {
  2602. X            /* last point is at (x1,y1) == (h1,v);
  2603. X             * this point is at (x2,y2) == (h, v);
  2604. X             * connect with NSEGS segments.
  2605. X             */
  2606. X            int sx1, sy1, sx2, sy2;
  2607. X            int xt, yt;
  2608. X            int vist, k;
  2609. X            for (k = 1; k <= NSEGS; k++) {
  2610. X            if (k == NSEGS) {
  2611. X                xt = x2;
  2612. X                yt = y2;
  2613. X                vist = vis2;
  2614. X            } else
  2615. X                vist = sv_loc(r, v, h1+k*(h-h1)/NSEGS, &xt, &yt);
  2616. X            if ((vis1 || vist) &&
  2617. X                lc(0,0,r*2,x1,y1,xt,yt,&sx1,&sy1,&sx2,&sy2)==0){
  2618. X                xs->x1 = sx1+xb; xs->y1 = sy1+yb;
  2619. X                xs->x2 = sx2+xb; xs->y2 = sy2+yb;
  2620. X                xs++;
  2621. X            }
  2622. X            x1 = xt;
  2623. X            y1 = yt;
  2624. X            vis1 = vist;
  2625. X            }
  2626. X        }
  2627. X        x1 = x2;
  2628. X        y1 = y2;
  2629. X        h1 = h;
  2630. X        vis1 = vis2;
  2631. X        }
  2632. X        XDrawSegments (dsp, win, gc, xsegments, xs - xsegments);
  2633. X    }
  2634. X}
  2635. X
  2636. X
  2637. X/* draw the ecliptic on a circle of radius r, x and y borders xb and yb.
  2638. X * special thanks to Uwe Bonnes <bon@LTE.E-TECHNIK.uni-erlangen.de>
  2639. X */
  2640. Xstatic void
  2641. Xdraw_ecliptic(dsp, win, gc, r, xb, yb)
  2642. XDisplay *dsp;
  2643. XWindow win;
  2644. XGC gc;
  2645. Xunsigned int r;
  2646. Xunsigned int xb, yb;
  2647. X{
  2648. X#define    ECL_CACHE_SZ    100
  2649. X    XPoint point_cache[ECL_CACHE_SZ];
  2650. X    double elat0, elng0;    /* ecliptic lat and long at center of fov */
  2651. X    double elngmin, elngmax;/* ecliptic long limits */
  2652. X    double ra, dec;
  2653. X    double elng;
  2654. X    double lst;
  2655. X    int ncache;
  2656. X    Now *np;
  2657. X
  2658. X    np = mm_get_now();
  2659. X    now_lst (np, &lst);
  2660. X
  2661. X    /* find ecliptic coords of center of view */
  2662. X    if (aa_mode) {
  2663. X        double ha0;        /* local hour angle */
  2664. X        aa_hadec (lat, sv_altdec, sv_azra, &ha0, &dec);
  2665. X        ra = hrrad(lst) - ha0;
  2666. X    } else {
  2667. X        ra = sv_azra;
  2668. X        dec = sv_altdec;
  2669. X    }
  2670. X    eq_ecl (mjd, ra, dec, &elat0, &elng0);
  2671. X
  2672. X    /* no ecliptic visible if ecliptic latitude at center of view 
  2673. X     * is not less than fov/2
  2674. X     */
  2675. X    if (fabs(elat0) >= sv_fov/2.0)
  2676. X        return;
  2677. X
  2678. X    /* worst-case elong limits is center elong += half fov */
  2679. X    elngmin = elng0 - sv_fov/2.0;
  2680. X    elngmax = elng0 + sv_fov/2.0;
  2681. X
  2682. X    /* put a mark at every ECL_TICS pixels */
  2683. X    ncache = 0;
  2684. X    for (elng = elngmin; elng <= elngmax; elng += sv_fov/(2.0*r/ECL_TICS)) {
  2685. X        int x, y;
  2686. X        double altdec, azra;
  2687. X
  2688. X        /* convert longitude along the ecliptic to ra/dec */
  2689. X        ecl_eq (mjd, 0.0, elng, &azra, &altdec);
  2690. X
  2691. X        /* if in aa mode, we need it in alt/az */
  2692. X        if (aa_mode) {
  2693. X        hadec_aa (lat, hrrad(lst) - azra, altdec, &altdec, &azra);
  2694. X        refract (pressure, temp, altdec, &altdec);
  2695. X        }
  2696. X
  2697. X        /* if visible, display point */
  2698. X        if ((!aa_mode || altdec >= 0) && sv_loc (r, altdec, azra, &x, &y)) {
  2699. X        XPoint *xp = &point_cache[ncache++];
  2700. X        xp->x = x + xb;
  2701. X        xp->y = y + yb;
  2702. X        if (ncache == XtNumber(point_cache)) {
  2703. X            XDrawPoints (dsp,win,gc,point_cache,ncache,CoordModeOrigin);
  2704. X            ncache = 0;
  2705. X        }
  2706. X        }
  2707. X    }
  2708. X
  2709. X    if (ncache > 0)
  2710. X        XDrawPoints (dsp, win, gc, point_cache, ncache, CoordModeOrigin);
  2711. X}
  2712. X
  2713. X/* given the magnitude of an object, return its desired diameter, in pixels.
  2714. X * N.B. we assume it is at least as bright as fmag.
  2715. X */
  2716. Xstatic
  2717. Xmagdiam(m)
  2718. Xdouble m;
  2719. X{
  2720. X    return (((int)(fmag-m)+3)/2);
  2721. X}
  2722. X
  2723. X/* make the general purpose sv_gc and learn the three colors.
  2724. X */
  2725. Xstatic void
  2726. Xsv_mk_gcs(dsp, win)
  2727. XDisplay *dsp;
  2728. XWindow win;
  2729. X{
  2730. X    XGCValues gcv;
  2731. X    unsigned gcm = 0;
  2732. X
  2733. X    get_something (svda_w, XmNforeground, (char *)&fg_p);
  2734. X    get_something (svda_w, XmNbackground, (char *)&sky_p);
  2735. X    get_something (svform_w, XmNbackground, (char *)&bg_p);
  2736. X    set_something (svda_w, XmNbackground, (char *)bg_p);
  2737. X
  2738. X    sv_gc = XCreateGC (dsp, win, gcm, &gcv);
  2739. X}
  2740. X
  2741. X/* draw a label for an object that is located at [x,y]
  2742. X */
  2743. Xstatic void
  2744. Xdraw_label (dsp, win, gc, label, x, y)
  2745. XDisplay *dsp;
  2746. XWindow win;
  2747. XGC gc;
  2748. Xchar label[];
  2749. Xint x, y;
  2750. X{
  2751. X    XDrawString (dsp, win, gc, x+4, y-4, label, strlen(label));
  2752. X}
  2753. END_OF_FILE
  2754.   if test 21068 -ne `wc -c <'skyviewmenu.c.3'`; then
  2755.     echo shar: \"'skyviewmenu.c.3'\" unpacked with wrong size!
  2756.   fi
  2757.   # end of 'skyviewmenu.c.3'
  2758. fi
  2759. echo shar: End of archive 18 \(of 21\).
  2760. cp /dev/null ark18isdone
  2761. MISSING=""
  2762. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ; do
  2763.     if test ! -f ark${I}isdone ; then
  2764.     MISSING="${MISSING} ${I}"
  2765.     fi
  2766. done
  2767. if test "${MISSING}" = "" ; then
  2768.     echo You have unpacked all 21 archives.
  2769.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2770.     echo Building ephem.db
  2771.     cat > ephem.db.Z.uu ephem.db.Z.uu.?
  2772.     uudecode ephem.db.Z.uu
  2773.     rm ephem.db.Z.uu ephem.db.Z.uu.?
  2774.     uncompress ephem.db.Z
  2775.     echo Building skyviewmenu.c
  2776.     cat > skyviewmenu.c skyviewmenu.c.?
  2777.     rm skyviewmenu.c.?
  2778.     echo Building smallfm.xbm
  2779.     cat > smallfm.xbm smallfm.xbm.?
  2780.     rm smallfm.xbm.?
  2781. else
  2782.     echo You still must unpack the following archives:
  2783.     echo "        " ${MISSING}
  2784. fi
  2785. exit 0
  2786. exit 0 # Just in case...
  2787. -- 
  2788.   // chris@IMD.Sterling.COM            | Send comp.sources.x submissions to:
  2789. \X/  Amiga - The only way to fly!      |
  2790.  "It's intuitively obvious to the most |    sources-x@imd.sterling.com
  2791.   casual observer..."                  |
  2792.