[2551] | 1 | /* jupiter moon info */
|
---|
| 2 |
|
---|
| 3 | #include <stdio.h>
|
---|
| 4 | #include <stdlib.h>
|
---|
| 5 | #include <string.h>
|
---|
[3111] | 6 | #include <errno.h>
|
---|
[2551] | 7 | #include <math.h>
|
---|
| 8 |
|
---|
| 9 | #include "astro.h"
|
---|
| 10 | #include "bdl.h"
|
---|
| 11 |
|
---|
| 12 | static int use_bdl (double jd, char *dir, MoonData md[J_NMOONS]);
|
---|
| 13 | static void meeus_jupiter (double d, double *cmlI, double *cmlII,
|
---|
| 14 | MoonData md[J_NMOONS]);
|
---|
| 15 | static void moonradec (double jupsize, MoonData md[J_NMOONS]);
|
---|
[2643] | 16 | static void moonSVis (Obj *sop, Obj *jop, MoonData md[J_NMOONS]);
|
---|
[2551] | 17 | static void moonEVis (MoonData md[J_NMOONS]);
|
---|
[2643] | 18 | static void moonPShad (Obj *sop, Obj *jop, MoonData md[J_NMOONS]);
|
---|
| 19 | static void moonTrans (MoonData md[J_NMOONS]);
|
---|
[2551] | 20 |
|
---|
| 21 | /* moon table and a few other goodies and when it was last computed */
|
---|
| 22 | static double mdmjd = -123456;
|
---|
| 23 | static MoonData jmd[J_NMOONS] = {
|
---|
| 24 | {"Jupiter", NULL},
|
---|
| 25 | {"Io", "I"},
|
---|
| 26 | {"Europa", "II"},
|
---|
| 27 | {"Ganymede", "III"},
|
---|
| 28 | {"Callisto", "IV"}
|
---|
| 29 | };
|
---|
| 30 | static double sizemjd; /* size at last mjd */
|
---|
| 31 | static double cmlImjd; /* central meridian long sys I, at last mjd */
|
---|
| 32 | static double cmlIImjd; /* " II " */
|
---|
| 33 |
|
---|
[2643] | 34 | /* These values are from the Explanatory Supplement.
|
---|
| 35 | * Precession degrades them gradually over time.
|
---|
| 36 | */
|
---|
| 37 | #define POLE_RA degrad(268.05) /* RA of Jupiter's north pole */
|
---|
| 38 | #define POLE_DEC degrad(64.50) /* Dec of Jupiter's north pole */
|
---|
| 39 |
|
---|
| 40 |
|
---|
[2551] | 41 | /* get jupiter info in md[0], moon info in md[1..J_NMOONS-1].
|
---|
| 42 | * if !dir always use meeus model.
|
---|
| 43 | * if !jop caller just wants md[] for names
|
---|
[2643] | 44 | * N.B. we assume sop and jop are updated.
|
---|
[2551] | 45 | */
|
---|
| 46 | void
|
---|
| 47 | jupiter_data (
|
---|
| 48 | double Mjd, /* mjd */
|
---|
| 49 | char dir[], /* dir in which to look for helper files */
|
---|
[2643] | 50 | Obj *sop, /* Sun */
|
---|
[2551] | 51 | Obj *jop, /* jupiter */
|
---|
| 52 | double *sizep, /* jup angular diam, rads */
|
---|
[2643] | 53 | double *cmlI, double *cmlII, /* central meridian longitude, rads */
|
---|
| 54 | double *polera, double *poledec, /* pole location */
|
---|
[2551] | 55 | MoonData md[J_NMOONS]) /* return info */
|
---|
| 56 | {
|
---|
| 57 | double JD;
|
---|
| 58 |
|
---|
| 59 | /* always copy back at least for name */
|
---|
| 60 | memcpy (md, jmd, sizeof(jmd));
|
---|
| 61 |
|
---|
[2643] | 62 | /* pole */
|
---|
| 63 | if (polera) *polera = POLE_RA;
|
---|
| 64 | if (poledec) *poledec = POLE_DEC;
|
---|
| 65 |
|
---|
[2551] | 66 | /* nothing else if repeat call or just want names */
|
---|
| 67 | if (Mjd == mdmjd || !jop) {
|
---|
| 68 | if (jop) {
|
---|
| 69 | *sizep = sizemjd;
|
---|
| 70 | *cmlI = cmlImjd;
|
---|
| 71 | *cmlII = cmlIImjd;
|
---|
| 72 | }
|
---|
| 73 | return;
|
---|
| 74 | }
|
---|
| 75 | JD = Mjd + MJD0;
|
---|
| 76 |
|
---|
| 77 | /* planet in [0] */
|
---|
| 78 | md[0].ra = jop->s_ra;
|
---|
| 79 | md[0].dec = jop->s_dec;
|
---|
| 80 | md[0].mag = get_mag(jop);
|
---|
| 81 | md[0].x = 0;
|
---|
| 82 | md[0].y = 0;
|
---|
| 83 | md[0].z = 0;
|
---|
| 84 | md[0].evis = 1;
|
---|
| 85 | md[0].svis = 1;
|
---|
| 86 |
|
---|
| 87 | /* size is straight from jop */
|
---|
| 88 | *sizep = degrad(jop->s_size/3600.0);
|
---|
| 89 |
|
---|
| 90 | /* mags from JPL ephemeris */
|
---|
| 91 | md[1].mag = 5.7;
|
---|
| 92 | md[2].mag = 5.8;
|
---|
| 93 | md[3].mag = 5.3;
|
---|
| 94 | md[4].mag = 6.7;
|
---|
| 95 |
|
---|
| 96 | /* get moon data from BDL if possible, else Meeus' model.
|
---|
| 97 | * always use Meeus for cml
|
---|
| 98 | */
|
---|
| 99 | if (dir && use_bdl (JD, dir, md) == 0)
|
---|
| 100 | meeus_jupiter (Mjd, cmlI, cmlII, NULL);
|
---|
| 101 | else
|
---|
| 102 | meeus_jupiter (Mjd, cmlI, cmlII, md);
|
---|
| 103 |
|
---|
| 104 | /* set visibilities */
|
---|
[2643] | 105 | moonSVis (sop, jop, md);
|
---|
| 106 | moonPShad (sop, jop, md);
|
---|
[2551] | 107 | moonEVis (md);
|
---|
[2643] | 108 | moonTrans (md);
|
---|
[2551] | 109 |
|
---|
| 110 | /* fill in moon ra and dec */
|
---|
| 111 | moonradec (*sizep, md);
|
---|
| 112 |
|
---|
| 113 | /* save */
|
---|
| 114 | mdmjd = Mjd;
|
---|
| 115 | sizemjd = *sizep;
|
---|
| 116 | cmlImjd = *cmlI;
|
---|
| 117 | cmlIImjd = *cmlII;
|
---|
| 118 | memcpy (jmd, md, sizeof(jmd));
|
---|
| 119 | }
|
---|
| 120 |
|
---|
| 121 | /* hunt for BDL file in dir[] and use if possible
|
---|
| 122 | * return 0 if ok, else -1
|
---|
| 123 | */
|
---|
| 124 | static int
|
---|
| 125 | use_bdl (
|
---|
| 126 | double JD, /* julian date */
|
---|
| 127 | char dir[], /* directory */
|
---|
| 128 | MoonData md[J_NMOONS]) /* fill md[1..NM-1].x/y/z for each moon */
|
---|
| 129 | {
|
---|
| 130 | #define JUPRAU .0004769108 /* jupiter radius, AU */
|
---|
| 131 | double x[J_NMOONS], y[J_NMOONS], z[J_NMOONS];
|
---|
| 132 | char buf[1024];
|
---|
| 133 | FILE *fp;
|
---|
[3111] | 134 | char *fn;
|
---|
[2551] | 135 | int i;
|
---|
| 136 |
|
---|
[3111] | 137 | /* check ranges and appropriate data file */
|
---|
| 138 | if (JD < 2451179.50000) /* Jan 1 1999 UTC */
|
---|
[2551] | 139 | return (-1);
|
---|
[3111] | 140 | if (JD < 2455562.5) /* Jan 1 2011 UTC */
|
---|
| 141 | fn = "jupiter.9910";
|
---|
| 142 | else if (JD < 2459215.5) /* Jan 1 2021 UTC */
|
---|
| 143 | fn = "jupiter.1020";
|
---|
| 144 | else
|
---|
| 145 | return (-1);
|
---|
[2551] | 146 |
|
---|
| 147 | /* open */
|
---|
[3111] | 148 | (void) sprintf (buf, "%s/%s", dir, fn);
|
---|
[2551] | 149 | fp = fopen (buf, "r");
|
---|
[3111] | 150 | if (!fp) {
|
---|
| 151 | fprintf (stderr, "%s: %s\n", fn, strerror(errno));
|
---|
[2551] | 152 | return (-1);
|
---|
[3111] | 153 | }
|
---|
[2551] | 154 |
|
---|
| 155 | /* use it */
|
---|
| 156 | if ((i = read_bdl (fp, JD, x, y, z, buf)) < 0) {
|
---|
[3111] | 157 | fprintf (stderr, "%s: %s\n", fn, buf);
|
---|
[2551] | 158 | fclose (fp);
|
---|
| 159 | return (-1);
|
---|
| 160 | }
|
---|
| 161 | if (i != J_NMOONS-1) {
|
---|
[3111] | 162 | fprintf (stderr, "%s: BDL says %d moons, code expects %d", fn,
|
---|
[2551] | 163 | i, J_NMOONS-1);
|
---|
| 164 | fclose (fp);
|
---|
| 165 | return (-1);
|
---|
| 166 | }
|
---|
| 167 |
|
---|
| 168 | /* copy into md[1..NM-1] with our scale and sign conventions */
|
---|
| 169 | for (i = 1; i < J_NMOONS; i++) {
|
---|
| 170 | md[i].x = x[i-1]/JUPRAU; /* we want jup radii +E */
|
---|
| 171 | md[i].y = -y[i-1]/JUPRAU; /* we want jup radii +S */
|
---|
| 172 | md[i].z = -z[i-1]/JUPRAU; /* we want jup radii +front */
|
---|
| 173 | }
|
---|
| 174 |
|
---|
| 175 | /* ok */
|
---|
| 176 | fclose (fp);
|
---|
| 177 | return (0);
|
---|
| 178 | }
|
---|
| 179 |
|
---|
| 180 | /* compute location of GRS and Galilean moons.
|
---|
| 181 | * if md == NULL, just to cml.
|
---|
| 182 | * from "Astronomical Formulae for Calculators", 2nd ed, by Jean Meeus,
|
---|
| 183 | * Willmann-Bell, Richmond, Va., U.S.A. (c) 1982, chapters 35 and 36.
|
---|
| 184 | */
|
---|
| 185 | static void
|
---|
| 186 | meeus_jupiter(
|
---|
| 187 | double d,
|
---|
| 188 | double *cmlI, double *cmlII, /* central meridian longitude, rads */
|
---|
| 189 | MoonData md[J_NMOONS]) /* fill in md[1..NM-1].x/y/z for each moon.
|
---|
| 190 | * N.B. md[0].ra/dec must already be set
|
---|
| 191 | */
|
---|
| 192 | {
|
---|
| 193 | #define dsin(x) sin(degrad(x))
|
---|
| 194 | #define dcos(x) cos(degrad(x))
|
---|
| 195 | double A, B, Del, J, K, M, N, R, V;
|
---|
| 196 | double cor_u1, cor_u2, cor_u3, cor_u4;
|
---|
| 197 | double solc, tmp, G, H, psi, r, r1, r2, r3, r4;
|
---|
| 198 | double u1, u2, u3, u4;
|
---|
| 199 | double lam, Ds;
|
---|
| 200 | double z1, z2, z3, z4;
|
---|
| 201 | double De, dsinDe;
|
---|
| 202 | double theta, phi;
|
---|
| 203 | double tvc, pvc;
|
---|
| 204 | double salpha, calpha;
|
---|
| 205 | int i;
|
---|
| 206 |
|
---|
| 207 | V = 134.63 + 0.00111587 * d;
|
---|
| 208 |
|
---|
| 209 | M = (358.47583 + 0.98560003*d);
|
---|
| 210 | N = (225.32833 + 0.0830853*d) + 0.33 * dsin (V);
|
---|
| 211 |
|
---|
| 212 | J = 221.647 + 0.9025179*d - 0.33 * dsin(V);
|
---|
| 213 |
|
---|
| 214 | A = 1.916*dsin(M) + 0.02*dsin(2*M);
|
---|
| 215 | B = 5.552*dsin(N) + 0.167*dsin(2*N);
|
---|
| 216 | K = (J+A-B);
|
---|
| 217 | R = 1.00014 - 0.01672 * dcos(M) - 0.00014 * dcos(2*M);
|
---|
| 218 | r = 5.20867 - 0.25192 * dcos(N) - 0.00610 * dcos(2*N);
|
---|
| 219 | Del = sqrt (R*R + r*r - 2*R*r*dcos(K));
|
---|
| 220 | psi = raddeg (asin (R/Del*dsin(K)));
|
---|
| 221 |
|
---|
| 222 | *cmlI = degrad(268.28 + 877.8169088*(d - Del/173) + psi - B);
|
---|
| 223 | range (cmlI, 2*PI);
|
---|
| 224 | *cmlII = degrad(290.28 + 870.1869088*(d - Del/173) + psi - B);
|
---|
| 225 | range (cmlII, 2*PI);
|
---|
| 226 |
|
---|
| 227 | /* that's it if don't want moon info too */
|
---|
| 228 | if (!md)
|
---|
| 229 | return;
|
---|
| 230 |
|
---|
| 231 | solc = (d - Del/173.); /* speed of light correction */
|
---|
| 232 | tmp = psi - B;
|
---|
| 233 |
|
---|
| 234 | u1 = 84.5506 + 203.4058630 * solc + tmp;
|
---|
| 235 | u2 = 41.5015 + 101.2916323 * solc + tmp;
|
---|
| 236 | u3 = 109.9770 + 50.2345169 * solc + tmp;
|
---|
| 237 | u4 = 176.3586 + 21.4879802 * solc + tmp;
|
---|
| 238 |
|
---|
| 239 | G = 187.3 + 50.310674 * solc;
|
---|
| 240 | H = 311.1 + 21.569229 * solc;
|
---|
| 241 |
|
---|
| 242 | cor_u1 = 0.472 * dsin (2*(u1-u2));
|
---|
| 243 | cor_u2 = 1.073 * dsin (2*(u2-u3));
|
---|
| 244 | cor_u3 = 0.174 * dsin (G);
|
---|
| 245 | cor_u4 = 0.845 * dsin (H);
|
---|
| 246 |
|
---|
| 247 | r1 = 5.9061 - 0.0244 * dcos (2*(u1-u2));
|
---|
| 248 | r2 = 9.3972 - 0.0889 * dcos (2*(u2-u3));
|
---|
| 249 | r3 = 14.9894 - 0.0227 * dcos (G);
|
---|
| 250 | r4 = 26.3649 - 0.1944 * dcos (H);
|
---|
| 251 |
|
---|
| 252 | md[1].x = -r1 * dsin (u1+cor_u1);
|
---|
| 253 | md[2].x = -r2 * dsin (u2+cor_u2);
|
---|
| 254 | md[3].x = -r3 * dsin (u3+cor_u3);
|
---|
| 255 | md[4].x = -r4 * dsin (u4+cor_u4);
|
---|
| 256 |
|
---|
| 257 | lam = 238.05 + 0.083091*d + 0.33*dsin(V) + B;
|
---|
| 258 | Ds = 3.07*dsin(lam + 44.5);
|
---|
| 259 | De = Ds - 2.15*dsin(psi)*dcos(lam+24.)
|
---|
| 260 | - 1.31*(r-Del)/Del*dsin(lam-99.4);
|
---|
| 261 | dsinDe = dsin(De);
|
---|
| 262 |
|
---|
| 263 | z1 = r1 * dcos(u1+cor_u1);
|
---|
| 264 | z2 = r2 * dcos(u2+cor_u2);
|
---|
| 265 | z3 = r3 * dcos(u3+cor_u3);
|
---|
| 266 | z4 = r4 * dcos(u4+cor_u4);
|
---|
| 267 |
|
---|
| 268 | md[1].y = z1*dsinDe;
|
---|
| 269 | md[2].y = z2*dsinDe;
|
---|
| 270 | md[3].y = z3*dsinDe;
|
---|
| 271 | md[4].y = z4*dsinDe;
|
---|
| 272 |
|
---|
| 273 | /* compute sky transformation angle as triple vector product */
|
---|
| 274 | tvc = PI/2.0 - md[0].dec;
|
---|
| 275 | pvc = md[0].ra;
|
---|
| 276 | theta = PI/2.0 - POLE_DEC;
|
---|
| 277 | phi = POLE_RA;
|
---|
| 278 | salpha = -sin(tvc)*sin(theta)*(cos(pvc)*sin(phi) - sin(pvc)*cos(phi));
|
---|
| 279 | calpha = sqrt (1.0 - salpha*salpha);
|
---|
| 280 |
|
---|
| 281 | for (i = 0; i < J_NMOONS; i++) {
|
---|
| 282 | double tx = md[i].x*calpha + md[i].y*salpha;
|
---|
| 283 | double ty = -md[i].x*salpha + md[i].y*calpha;
|
---|
| 284 | md[i].x = tx;
|
---|
| 285 | md[i].y = ty;
|
---|
| 286 | }
|
---|
| 287 |
|
---|
| 288 | md[1].z = z1;
|
---|
| 289 | md[2].z = z2;
|
---|
| 290 | md[3].z = z3;
|
---|
| 291 | md[4].z = z4;
|
---|
| 292 | }
|
---|
| 293 |
|
---|
| 294 |
|
---|
| 295 | /* given jupiter loc in md[0].ra/dec and size, and location of each moon in
|
---|
| 296 | * md[1..NM-1].x/y in jup radii, find ra/dec of each moon in md[1..NM-1].ra/dec.
|
---|
| 297 | */
|
---|
| 298 | static void
|
---|
| 299 | moonradec (
|
---|
| 300 | double jupsize, /* jup diameter, rads */
|
---|
| 301 | MoonData md[J_NMOONS]) /* fill in RA and Dec */
|
---|
| 302 | {
|
---|
| 303 | double juprad = jupsize/2;
|
---|
| 304 | double jupra = md[0].ra;
|
---|
| 305 | double jupdec = md[0].dec;
|
---|
| 306 | int i;
|
---|
| 307 |
|
---|
| 308 | for (i = 1; i < J_NMOONS; i++) {
|
---|
| 309 | double dra = juprad * md[i].x;
|
---|
| 310 | double ddec = juprad * md[i].y;
|
---|
| 311 | md[i].ra = jupra + dra;
|
---|
| 312 | md[i].dec = jupdec - ddec;
|
---|
| 313 | }
|
---|
| 314 | }
|
---|
| 315 |
|
---|
| 316 | /* set svis according to whether moon is in sun light */
|
---|
| 317 | static void
|
---|
| 318 | moonSVis(
|
---|
[2643] | 319 | Obj *sop, /* SUN */
|
---|
[2551] | 320 | Obj *jop, /* jupiter */
|
---|
| 321 | MoonData md[J_NMOONS])
|
---|
| 322 | {
|
---|
[2643] | 323 | double esd = sop->s_edist;
|
---|
[2551] | 324 | double eod = jop->s_edist;
|
---|
| 325 | double sod = jop->s_sdist;
|
---|
| 326 | double soa = degrad(jop->s_elong);
|
---|
| 327 | double esa = asin(esd*sin(soa)/sod);
|
---|
| 328 | double h = sod*jop->s_hlat;
|
---|
| 329 | double nod = h*(1./eod - 1./sod);
|
---|
| 330 | double sca = cos(esa), ssa = sin(esa);
|
---|
| 331 | int i;
|
---|
| 332 |
|
---|
| 333 | for (i = 1; i < J_NMOONS; i++) {
|
---|
| 334 | MoonData *mdp = &md[i];
|
---|
| 335 | double xp = sca*mdp->x + ssa*mdp->z;
|
---|
| 336 | double yp = mdp->y;
|
---|
| 337 | double zp = -ssa*mdp->x + sca*mdp->z;
|
---|
| 338 | double ca = cos(nod), sa = sin(nod);
|
---|
| 339 | double xpp = xp;
|
---|
| 340 | double ypp = ca*yp - sa*zp;
|
---|
| 341 | double zpp = sa*yp + ca*zp;
|
---|
| 342 | int outside = xpp*xpp + ypp*ypp > 1.0;
|
---|
| 343 | int infront = zpp > 0.0;
|
---|
| 344 | mdp->svis = outside || infront;
|
---|
| 345 | }
|
---|
| 346 | }
|
---|
| 347 |
|
---|
| 348 | /* set evis according to whether moon is geometrically visible from earth */
|
---|
| 349 | static void
|
---|
| 350 | moonEVis (MoonData md[J_NMOONS])
|
---|
| 351 | {
|
---|
| 352 | int i;
|
---|
| 353 |
|
---|
| 354 | for (i = 1; i < J_NMOONS; i++) {
|
---|
| 355 | MoonData *mdp = &md[i];
|
---|
| 356 | int outside = mdp->x*mdp->x + mdp->y*mdp->y > 1.0;
|
---|
| 357 | int infront = mdp->z > 0.0;
|
---|
| 358 | mdp->evis = outside || infront;
|
---|
| 359 | }
|
---|
| 360 | }
|
---|
| 361 |
|
---|
[2643] | 362 | /* set pshad and sx,sy shadow info */
|
---|
| 363 | static void
|
---|
| 364 | moonPShad(
|
---|
| 365 | Obj *sop, /* SUN */
|
---|
| 366 | Obj *jop, /* jupiter */
|
---|
| 367 | MoonData md[J_NMOONS])
|
---|
| 368 | {
|
---|
| 369 | int i;
|
---|
| 370 |
|
---|
| 371 | for (i = 1; i < J_NMOONS; i++) {
|
---|
| 372 | MoonData *mdp = &md[i];
|
---|
| 373 | mdp->pshad = !plshadow (jop, sop, POLE_RA, POLE_DEC, mdp->x,
|
---|
| 374 | mdp->y, mdp->z, &mdp->sx, &mdp->sy);
|
---|
| 375 | }
|
---|
| 376 | }
|
---|
| 377 |
|
---|
| 378 | /* set whether moons are transiting */
|
---|
| 379 | static void
|
---|
| 380 | moonTrans (MoonData md[J_NMOONS])
|
---|
| 381 | {
|
---|
| 382 | int i;
|
---|
| 383 |
|
---|
| 384 | for (i = 1; i < J_NMOONS; i++) {
|
---|
| 385 | MoonData *mdp = &md[i];
|
---|
| 386 | mdp->trans = mdp->z > 0 && mdp->x*mdp->x + mdp->y*mdp->y < 1;
|
---|
| 387 | }
|
---|
| 388 | }
|
---|
| 389 |
|
---|
[2551] | 390 | /* For RCS Only -- Do Not Edit */
|
---|
[3477] | 391 | static char *rcsid[2] = {(char *)rcsid, "@(#) $RCSfile: jupmoon.c,v $ $Date: 2008-03-25 17:45:14 $ $Revision: 1.5 $ $Name: not supported by cvs2svn $"};
|
---|