| 1 | /* compute Obj fields for natural satellites. | 
|---|
| 2 | */ | 
|---|
| 3 |  | 
|---|
| 4 | #include <stdio.h> | 
|---|
| 5 | #include <string.h> | 
|---|
| 6 | #include <math.h> | 
|---|
| 7 |  | 
|---|
| 8 | #include "astro.h" | 
|---|
| 9 |  | 
|---|
| 10 | /* private cache of planet ephemerides and when they were computed | 
|---|
| 11 | * N.B. don't use ones in builtin[] -- they are the user's responsibility. | 
|---|
| 12 | */ | 
|---|
| 13 | static ObjPl plobj[NOBJ]; | 
|---|
| 14 | static Now plnow[NOBJ]; | 
|---|
| 15 |  | 
|---|
| 16 | /* public builtin storage | 
|---|
| 17 | */ | 
|---|
| 18 | static Obj builtin[NBUILTIN]; | 
|---|
| 19 |  | 
|---|
| 20 | static char *moondir; | 
|---|
| 21 |  | 
|---|
| 22 | static void setMoon (Now *np, Obj *moonop, Obj *planop, MoonData *mdp); | 
|---|
| 23 | static void init1BI (int idx, int pl, int moon, char *name); | 
|---|
| 24 | static void initPlobj(void); | 
|---|
| 25 | static void rotate (double a, double *x, double *y); | 
|---|
| 26 |  | 
|---|
| 27 | /* directory in which to look for auxil moon data files. | 
|---|
| 28 | * N.B. caller must supply persistent storage. | 
|---|
| 29 | */ | 
|---|
| 30 | void | 
|---|
| 31 | setMoonDir (char *dir) | 
|---|
| 32 | { | 
|---|
| 33 | moondir = dir; | 
|---|
| 34 | } | 
|---|
| 35 |  | 
|---|
| 36 | /* return set of builtin objects. | 
|---|
| 37 | * caller can use this storage but should never try to free anything. | 
|---|
| 38 | */ | 
|---|
| 39 | int | 
|---|
| 40 | getBuiltInObjs (Obj **opp) | 
|---|
| 41 | { | 
|---|
| 42 | if (!builtin[MERCURY].o_name[0]) { | 
|---|
| 43 | /* first time only */ | 
|---|
| 44 |  | 
|---|
| 45 | init1BI (MERCURY,   MERCURY, X_PLANET,    "Mercury"); | 
|---|
| 46 |  | 
|---|
| 47 | init1BI (VENUS,     VENUS,   X_PLANET,    "Venus"); | 
|---|
| 48 |  | 
|---|
| 49 | init1BI (MARS,      MARS,    X_PLANET,    "Mars"); | 
|---|
| 50 | init1BI (PHOBOS,    MARS,    M_PHOBOS,    "Phobos"); | 
|---|
| 51 | init1BI (DEIMOS,    MARS,    M_DEIMOS,    "Deimos"); | 
|---|
| 52 |  | 
|---|
| 53 | init1BI (JUPITER,   JUPITER, X_PLANET,    "Jupiter"); | 
|---|
| 54 | init1BI (IO,        JUPITER, J_IO,        "Io"); | 
|---|
| 55 | init1BI (EUROPA,    JUPITER, J_EUROPA,    "Europa"); | 
|---|
| 56 | init1BI (GANYMEDE,  JUPITER, J_GANYMEDE,  "Ganymede"); | 
|---|
| 57 | init1BI (CALLISTO,  JUPITER, J_CALLISTO,  "Callisto"); | 
|---|
| 58 |  | 
|---|
| 59 | init1BI (SATURN,    SATURN,  X_PLANET,    "Saturn"); | 
|---|
| 60 | init1BI (MIMAS,     SATURN,  S_MIMAS,     "Mimas"); | 
|---|
| 61 | init1BI (ENCELADUS, SATURN,  S_ENCELADUS, "Enceladus"); | 
|---|
| 62 | init1BI (TETHYS,    SATURN,  S_TETHYS,    "Tethys"); | 
|---|
| 63 | init1BI (DIONE,     SATURN,  S_DIONE,     "Dione"); | 
|---|
| 64 | init1BI (RHEA,      SATURN,  S_RHEA,      "Rhea"); | 
|---|
| 65 | init1BI (TITAN,     SATURN,  S_TITAN,     "Titan"); | 
|---|
| 66 | init1BI (HYPERION,  SATURN,  S_HYPERION,  "Hyperion"); | 
|---|
| 67 | init1BI (IAPETUS,   SATURN,  S_IAPETUS,   "Iapetus"); | 
|---|
| 68 |  | 
|---|
| 69 | init1BI (URANUS,    URANUS,  X_PLANET,    "Uranus"); | 
|---|
| 70 | init1BI (ARIEL,     URANUS,  U_ARIEL,     "Ariel"); | 
|---|
| 71 | init1BI (UMBRIEL,   URANUS,  U_UMBRIEL,   "Umbriel"); | 
|---|
| 72 | init1BI (TITANIA,   URANUS,  U_TITANIA,   "Titania"); | 
|---|
| 73 | init1BI (OBERON,    URANUS,  U_OBERON,    "Oberon"); | 
|---|
| 74 | init1BI (MIRANDA,   URANUS,  U_MIRANDA,   "Miranda"); | 
|---|
| 75 |  | 
|---|
| 76 | init1BI (NEPTUNE,   NEPTUNE, X_PLANET,    "Neptune"); | 
|---|
| 77 |  | 
|---|
| 78 | init1BI (PLUTO,     PLUTO,   X_PLANET,    "Pluto"); | 
|---|
| 79 |  | 
|---|
| 80 | init1BI (SUN,       SUN,     X_PLANET,    "Sun"); | 
|---|
| 81 |  | 
|---|
| 82 | init1BI (MOON,      MOON,    X_PLANET,    "Moon"); | 
|---|
| 83 | } | 
|---|
| 84 |  | 
|---|
| 85 | *opp = builtin; | 
|---|
| 86 | return (NBUILTIN); | 
|---|
| 87 | } | 
|---|
| 88 |  | 
|---|
| 89 | static void | 
|---|
| 90 | init1BI (int idx, int pl, int moon, char *name) | 
|---|
| 91 | { | 
|---|
| 92 | strcpy (builtin[idx].o_name, name); | 
|---|
| 93 | builtin[idx].o_type = PLANET; | 
|---|
| 94 | builtin[idx].pl_code = pl; | 
|---|
| 95 | builtin[idx].pl_moon = moon; | 
|---|
| 96 | } | 
|---|
| 97 |  | 
|---|
| 98 | /* find the circumstances for natural satellite object op at np. | 
|---|
| 99 | * TODO: distances and helio coords just copied from parent planet. | 
|---|
| 100 | */ | 
|---|
| 101 | int | 
|---|
| 102 | plmoon_cir (Now *np, Obj *moonop) | 
|---|
| 103 | { | 
|---|
| 104 | Obj *sunop = (Obj*)&plobj[SUN]; | 
|---|
| 105 | MoonData md[X_MAXNMOONS]; | 
|---|
| 106 | double sz, t1, t2; | 
|---|
| 107 | double pra, pdec; | 
|---|
| 108 | MoonData *mdp; | 
|---|
| 109 | Obj *planop; | 
|---|
| 110 |  | 
|---|
| 111 | /* init plobj[] */ | 
|---|
| 112 | if (!((Obj *)&plobj[0])->o_type) | 
|---|
| 113 | initPlobj(); | 
|---|
| 114 |  | 
|---|
| 115 | /* get sun @ np */ | 
|---|
| 116 | if (memcmp (&plnow[SUN], np, sizeof(Now))) { | 
|---|
| 117 | obj_cir (np, (Obj*)&plobj[SUN]); | 
|---|
| 118 | memcpy (&plnow[SUN], np, sizeof(Now)); | 
|---|
| 119 | } | 
|---|
| 120 |  | 
|---|
| 121 | /* get parent planet and moon info @ np */ | 
|---|
| 122 | switch (moonop->pl_code) { | 
|---|
| 123 |  | 
|---|
| 124 | case MARS: | 
|---|
| 125 | case PHOBOS: | 
|---|
| 126 | case DEIMOS: | 
|---|
| 127 |  | 
|---|
| 128 | planop = (Obj*)&plobj[MARS]; | 
|---|
| 129 |  | 
|---|
| 130 | if (memcmp (&plnow[MARS], np, sizeof(Now))) { | 
|---|
| 131 | obj_cir (np, planop); | 
|---|
| 132 | memcpy (&plnow[MARS], np, sizeof(Now)); | 
|---|
| 133 | } | 
|---|
| 134 |  | 
|---|
| 135 | /* don't worry, this already caches based on same mjd */ | 
|---|
| 136 | marsm_data (mjd, moondir, sunop, planop, &sz, &pra, &pdec, md); | 
|---|
| 137 | mdp = &md[moonop->pl_moon]; | 
|---|
| 138 | break; | 
|---|
| 139 |  | 
|---|
| 140 | case JUPITER: | 
|---|
| 141 | case IO: | 
|---|
| 142 | case EUROPA: | 
|---|
| 143 | case GANYMEDE: | 
|---|
| 144 | case CALLISTO: | 
|---|
| 145 |  | 
|---|
| 146 | planop = (Obj*)&plobj[JUPITER]; | 
|---|
| 147 |  | 
|---|
| 148 | if (memcmp (&plnow[JUPITER], np, sizeof(Now))) { | 
|---|
| 149 | obj_cir (np, planop); | 
|---|
| 150 | memcpy (&plnow[JUPITER], np, sizeof(Now)); | 
|---|
| 151 | } | 
|---|
| 152 |  | 
|---|
| 153 | /* don't worry, this already caches based on same mjd */ | 
|---|
| 154 | jupiter_data (mjd,moondir,sunop,planop,&sz,&t1,&t2,&pra,&pdec,md); | 
|---|
| 155 | mdp = &md[moonop->pl_moon]; | 
|---|
| 156 | moonop->pl_aux1 = t1; | 
|---|
| 157 | moonop->pl_aux2 = t2; | 
|---|
| 158 | break; | 
|---|
| 159 |  | 
|---|
| 160 | case SATURN: | 
|---|
| 161 | case MIMAS: | 
|---|
| 162 | case ENCELADUS: | 
|---|
| 163 | case TETHYS: | 
|---|
| 164 | case DIONE: | 
|---|
| 165 | case RHEA: | 
|---|
| 166 | case TITAN: | 
|---|
| 167 | case HYPERION: | 
|---|
| 168 | case IAPETUS: | 
|---|
| 169 |  | 
|---|
| 170 | planop = (Obj*)&plobj[SATURN]; | 
|---|
| 171 |  | 
|---|
| 172 | if (memcmp (&plnow[SATURN], np, sizeof(Now))) { | 
|---|
| 173 | obj_cir (np, planop); | 
|---|
| 174 | memcpy (&plnow[SATURN], np, sizeof(Now)); | 
|---|
| 175 | } | 
|---|
| 176 |  | 
|---|
| 177 | /* don't worry, this already caches based on same mjd */ | 
|---|
| 178 | saturn_data (mjd,moondir,sunop,planop,&sz,&t1,&t2,&pra,&pdec,md); | 
|---|
| 179 | mdp = &md[moonop->pl_moon]; | 
|---|
| 180 | moonop->pl_aux1 = t1; | 
|---|
| 181 | moonop->pl_aux2 = t2; | 
|---|
| 182 | break; | 
|---|
| 183 |  | 
|---|
| 184 | case URANUS: | 
|---|
| 185 | case ARIEL: | 
|---|
| 186 | case UMBRIEL: | 
|---|
| 187 | case TITANIA: | 
|---|
| 188 | case OBERON: | 
|---|
| 189 | case MIRANDA: | 
|---|
| 190 |  | 
|---|
| 191 | planop = (Obj*)&plobj[URANUS]; | 
|---|
| 192 |  | 
|---|
| 193 | if (memcmp (&plnow[URANUS], np, sizeof(Now))) { | 
|---|
| 194 | obj_cir (np, planop); | 
|---|
| 195 | memcpy (&plnow[URANUS], np, sizeof(Now)); | 
|---|
| 196 | } | 
|---|
| 197 |  | 
|---|
| 198 | /* don't worry, this already caches based on same mjd */ | 
|---|
| 199 | uranus_data (mjd, moondir, sunop, planop, &sz, &pra, &pdec, md); | 
|---|
| 200 | mdp = &md[moonop->pl_moon]; | 
|---|
| 201 | break; | 
|---|
| 202 |  | 
|---|
| 203 | default: | 
|---|
| 204 |  | 
|---|
| 205 | printf ("Called plmoon_cir with bad code: %d\n",moonop->pl_code); | 
|---|
| 206 | return (-1); | 
|---|
| 207 |  | 
|---|
| 208 | } | 
|---|
| 209 |  | 
|---|
| 210 | /* set moonop */ | 
|---|
| 211 | setMoon (np, moonop, planop, mdp); | 
|---|
| 212 |  | 
|---|
| 213 | return (0); | 
|---|
| 214 | } | 
|---|
| 215 |  | 
|---|
| 216 | static void | 
|---|
| 217 | initPlobj() | 
|---|
| 218 | { | 
|---|
| 219 | int i; | 
|---|
| 220 |  | 
|---|
| 221 | for (i = 0; i < NOBJ; i++) { | 
|---|
| 222 | ((Obj*)&plobj[i])->o_type = PLANET; | 
|---|
| 223 | ((Obj*)&plobj[i])->pl_code = i; | 
|---|
| 224 | } | 
|---|
| 225 | } | 
|---|
| 226 |  | 
|---|
| 227 | /* set moonop->s_* fields. | 
|---|
| 228 | * np is needed to get local parallactic angle. | 
|---|
| 229 | */ | 
|---|
| 230 | static void | 
|---|
| 231 | setMoon (Now *np, Obj *moonop, Obj *planop, MoonData *mdp) | 
|---|
| 232 | { | 
|---|
| 233 | double pa, dra, ddec; | 
|---|
| 234 |  | 
|---|
| 235 | /* just copy most fields from planet for now */ | 
|---|
| 236 | moonop->s_gaera = planop->s_gaera;      /* TODO */ | 
|---|
| 237 | moonop->s_gaedec = planop->s_gaedec;    /* TODO */ | 
|---|
| 238 | moonop->s_elong = planop->s_elong;      /* TODO */ | 
|---|
| 239 | moonop->s_size = 0;                     /* TODO */ | 
|---|
| 240 | moonop->s_sdist = planop->s_sdist;      /* TODO */ | 
|---|
| 241 | moonop->s_edist = planop->s_edist;      /* TODO */ | 
|---|
| 242 | moonop->s_hlat = planop->s_hlat;        /* TODO */ | 
|---|
| 243 | moonop->s_hlong = planop->s_hlong;      /* TODO */ | 
|---|
| 244 | moonop->s_phase = planop->s_phase;      /* TODO */ | 
|---|
| 245 |  | 
|---|
| 246 | /* new ra/dec directly from mdp */ | 
|---|
| 247 | moonop->s_ra = mdp->ra; | 
|---|
| 248 | moonop->s_dec = mdp->dec; | 
|---|
| 249 |  | 
|---|
| 250 | /* geoemtry info */ | 
|---|
| 251 | moonop->pl_x = mdp->x; | 
|---|
| 252 | moonop->pl_y = mdp->y; | 
|---|
| 253 | moonop->pl_z = mdp->z; | 
|---|
| 254 | moonop->pl_evis = mdp->evis; | 
|---|
| 255 | moonop->pl_svis = mdp->svis; | 
|---|
| 256 |  | 
|---|
| 257 | /* tweak alt/az by change in ra/dec rotated by pa */ | 
|---|
| 258 | pa = parallacticLDA (lat, planop->s_dec, planop->s_alt); | 
|---|
| 259 | if (planop->s_az < PI) | 
|---|
| 260 | pa = -pa;                   /* rotation radec to altaz */ | 
|---|
| 261 | dra = (moonop->s_ra - planop->s_ra)*cos(planop->s_dec); | 
|---|
| 262 | ddec = moonop->s_dec - planop->s_dec; | 
|---|
| 263 | rotate (pa, &dra, &ddec); | 
|---|
| 264 | moonop->s_alt = planop->s_alt + ddec; | 
|---|
| 265 | moonop->s_az = planop->s_az - dra/cos(planop->s_alt); | 
|---|
| 266 |  | 
|---|
| 267 | /* new mag directly from mdp */ | 
|---|
| 268 | set_smag (moonop, mdp->mag); | 
|---|
| 269 |  | 
|---|
| 270 | /* name */ | 
|---|
| 271 | strcpy (moonop->o_name, mdp->full); | 
|---|
| 272 | } | 
|---|
| 273 |  | 
|---|
| 274 | /* rotate ccw by a */ | 
|---|
| 275 | static void | 
|---|
| 276 | rotate (double a, double *x, double *y) | 
|---|
| 277 | { | 
|---|
| 278 | double sa = sin(a); | 
|---|
| 279 | double ca = cos(a); | 
|---|
| 280 | double xp = (*x)*ca - (*y)*sa; | 
|---|
| 281 | double yp = (*x)*sa + (*y)*ca; | 
|---|
| 282 | *x = xp; | 
|---|
| 283 | *y = yp; | 
|---|
| 284 | } | 
|---|