| [1457] | 1 | /* misc handy functions. | 
|---|
|  | 2 | * every system has such, no? | 
|---|
|  | 3 | *  4/20/98 now_lst() always just returns apparent time | 
|---|
|  | 4 | */ | 
|---|
|  | 5 |  | 
|---|
|  | 6 | #include <stdio.h> | 
|---|
|  | 7 | #include <math.h> | 
|---|
|  | 8 | #include <stdlib.h> | 
|---|
|  | 9 | #include <string.h> | 
|---|
|  | 10 |  | 
|---|
|  | 11 | #include "astro.h" | 
|---|
|  | 12 |  | 
|---|
|  | 13 | /* zero from loc for len bytes */ | 
|---|
|  | 14 | void | 
|---|
| [2551] | 15 | zero_mem (void *loc, unsigned len) | 
|---|
| [1457] | 16 | { | 
|---|
|  | 17 | (void) memset (loc, 0, len); | 
|---|
|  | 18 | } | 
|---|
|  | 19 |  | 
|---|
|  | 20 | /* given min and max and an approximate number of divisions desired, | 
|---|
|  | 21 | * fill in ticks[] with nicely spaced values and return how many. | 
|---|
|  | 22 | * N.B. return value, and hence number of entries to ticks[], might be as | 
|---|
|  | 23 | *   much as 2 more than numdiv. | 
|---|
|  | 24 | */ | 
|---|
|  | 25 | int | 
|---|
| [2551] | 26 | tickmarks (double min, double max, int numdiv, double ticks[]) | 
|---|
| [1457] | 27 | { | 
|---|
|  | 28 | static int factor[] = { 1, 2, 5 }; | 
|---|
|  | 29 | double minscale; | 
|---|
|  | 30 | double delta; | 
|---|
|  | 31 | double lo; | 
|---|
|  | 32 | double v; | 
|---|
|  | 33 | int n; | 
|---|
|  | 34 |  | 
|---|
|  | 35 | minscale = fabs(max - min); | 
|---|
|  | 36 | delta = minscale/numdiv; | 
|---|
| [2551] | 37 | for (n=0; n < (int)(sizeof(factor)/sizeof(factor[0])); n++) { | 
|---|
| [1457] | 38 | double scale; | 
|---|
|  | 39 | double x = delta/factor[n]; | 
|---|
|  | 40 | if ((scale = (pow(10.0, ceil(log10(x)))*factor[n])) < minscale) | 
|---|
|  | 41 | minscale = scale; | 
|---|
|  | 42 | } | 
|---|
|  | 43 | delta = minscale; | 
|---|
|  | 44 |  | 
|---|
|  | 45 | lo = floor(min/delta); | 
|---|
|  | 46 | for (n = 0; (v = delta*(lo+n)) < max+delta; ) | 
|---|
|  | 47 | ticks[n++] = v; | 
|---|
|  | 48 |  | 
|---|
|  | 49 | return (n); | 
|---|
|  | 50 | } | 
|---|
|  | 51 |  | 
|---|
|  | 52 | /* given an Obj *, return its type as a descriptive string. | 
|---|
|  | 53 | * if it's of type fixed then return its class description. | 
|---|
|  | 54 | * N.B. we return the address of static storage -- do not free or change. | 
|---|
|  | 55 | */ | 
|---|
|  | 56 | char * | 
|---|
| [2551] | 57 | obj_description (Obj *op) | 
|---|
| [1457] | 58 | { | 
|---|
| [2551] | 59 | typedef struct { | 
|---|
|  | 60 | char classcode; | 
|---|
| [1457] | 61 | char *desc; | 
|---|
| [2551] | 62 | } CC; | 
|---|
|  | 63 |  | 
|---|
|  | 64 | #define NFCM    ((int)(sizeof(fixed_class_map)/sizeof(fixed_class_map[0]))) | 
|---|
|  | 65 | static CC fixed_class_map[] = { | 
|---|
| [1457] | 66 | {'A', "Cluster of Galaxies"}, | 
|---|
| [2551] | 67 | {'B', "Binary System"}, | 
|---|
| [1457] | 68 | {'C', "Globular Cluster"}, | 
|---|
|  | 69 | {'D', "Double Star"}, | 
|---|
|  | 70 | {'F', "Diffuse Nebula"}, | 
|---|
|  | 71 | {'G', "Spiral Galaxy"}, | 
|---|
|  | 72 | {'H', "Spherical Galaxy"}, | 
|---|
|  | 73 | {'J', "Radio"}, | 
|---|
|  | 74 | {'K', "Dark Nebula"}, | 
|---|
|  | 75 | {'L', "Pulsar"}, | 
|---|
|  | 76 | {'M', "Multiple Star"}, | 
|---|
|  | 77 | {'N', "Bright Nebula"}, | 
|---|
|  | 78 | {'O', "Open Cluster"}, | 
|---|
|  | 79 | {'P', "Planetary Nebula"}, | 
|---|
|  | 80 | {'Q', "Quasar"}, | 
|---|
|  | 81 | {'R', "Supernova Remnant"}, | 
|---|
|  | 82 | {'S', "Star"}, | 
|---|
|  | 83 | {'T', "Star-like Object"}, | 
|---|
|  | 84 | {'U', "Cluster, with nebulosity"}, | 
|---|
|  | 85 | {'V', "Variable Star"}, | 
|---|
| [2551] | 86 | {'Y', "Supernova"}, | 
|---|
| [1457] | 87 | }; | 
|---|
|  | 88 |  | 
|---|
| [2551] | 89 | #define NBCM    ((int)(sizeof(binary_class_map)/sizeof(binary_class_map[0]))) | 
|---|
|  | 90 | static CC binary_class_map[] = { | 
|---|
|  | 91 | {'a', "Astrometric binary"}, | 
|---|
|  | 92 | {'c', "Cataclysmic variable"}, | 
|---|
|  | 93 | {'e', "Eclipsing binary"}, | 
|---|
|  | 94 | {'x', "High-mass X-ray binary"}, | 
|---|
|  | 95 | {'y', "Low-mass X-ray binary"}, | 
|---|
|  | 96 | {'o', "Occultation binary"}, | 
|---|
|  | 97 | {'s', "Spectroscopic binary"}, | 
|---|
|  | 98 | {'t', "1-line spectral binary"}, | 
|---|
|  | 99 | {'u', "2-line spectral binary"}, | 
|---|
|  | 100 | {'v', "Spectrum binary"}, | 
|---|
|  | 101 | {'b', "Visual binary"}, | 
|---|
|  | 102 | {'d', "Visual binary, apparent"}, | 
|---|
|  | 103 | {'q', "Visual binary, optical"}, | 
|---|
|  | 104 | {'r', "Visual binary, physical"}, | 
|---|
|  | 105 | {'p', "Exoplanet"}, | 
|---|
|  | 106 | }; | 
|---|
|  | 107 |  | 
|---|
| [1457] | 108 | switch (op->o_type) { | 
|---|
|  | 109 | case FIXED: | 
|---|
|  | 110 | if (op->f_class) { | 
|---|
|  | 111 | int i; | 
|---|
|  | 112 | for (i = 0; i < NFCM; i++) | 
|---|
| [2551] | 113 | if (fixed_class_map[i].classcode == op->f_class) | 
|---|
| [1457] | 114 | return (fixed_class_map[i].desc); | 
|---|
|  | 115 | } | 
|---|
| [2551] | 116 | return ("Fixed"); | 
|---|
| [1457] | 117 | case PARABOLIC: | 
|---|
|  | 118 | return ("Solar - Parabolic"); | 
|---|
|  | 119 | case HYPERBOLIC: | 
|---|
|  | 120 | return ("Solar - Hyperbolic"); | 
|---|
|  | 121 | case ELLIPTICAL: | 
|---|
|  | 122 | return ("Solar - Elliptical"); | 
|---|
| [2551] | 123 | case BINARYSTAR: | 
|---|
|  | 124 | if (op->f_class) { | 
|---|
|  | 125 | int i; | 
|---|
|  | 126 | for (i = 0; i < NFCM; i++) | 
|---|
|  | 127 | if (binary_class_map[i].classcode == op->f_class) | 
|---|
|  | 128 | return (binary_class_map[i].desc); | 
|---|
|  | 129 | } | 
|---|
|  | 130 | return ("Binary system"); | 
|---|
|  | 131 | case PLANET: { | 
|---|
|  | 132 | static char nsstr[16]; | 
|---|
|  | 133 | static Obj *biop; | 
|---|
|  | 134 |  | 
|---|
|  | 135 | if (op->pl_code == SUN) | 
|---|
|  | 136 | return ("Star"); | 
|---|
|  | 137 | if (op->pl_code == MOON) | 
|---|
|  | 138 | return ("Moon of Earth"); | 
|---|
|  | 139 | if (op->pl_moon == X_PLANET) | 
|---|
|  | 140 | return ("Planet"); | 
|---|
|  | 141 | if (!biop) | 
|---|
|  | 142 | getBuiltInObjs (&biop); | 
|---|
|  | 143 | sprintf (nsstr, "Moon of %s", biop[op->pl_code].o_name); | 
|---|
|  | 144 | return (nsstr); | 
|---|
|  | 145 | } | 
|---|
| [1457] | 146 | case EARTHSAT: | 
|---|
|  | 147 | return ("Earth Sat"); | 
|---|
|  | 148 | default: | 
|---|
|  | 149 | printf ("obj_description: unknown type: 0x%x\n", op->o_type); | 
|---|
| [2551] | 150 | abort(); | 
|---|
| [1457] | 151 | return (NULL);      /* for lint */ | 
|---|
|  | 152 | } | 
|---|
|  | 153 | } | 
|---|
|  | 154 |  | 
|---|
|  | 155 | /* given a Now *, find the local apparent sidereal time, in hours. | 
|---|
|  | 156 | */ | 
|---|
|  | 157 | void | 
|---|
| [2551] | 158 | now_lst (Now *np, double *lstp) | 
|---|
| [1457] | 159 | { | 
|---|
|  | 160 | static double last_mjd = -23243, last_lng = 121212, last_lst; | 
|---|
|  | 161 | double eps, lst, deps, dpsi; | 
|---|
|  | 162 |  | 
|---|
|  | 163 | if (last_mjd == mjd && last_lng == lng) { | 
|---|
|  | 164 | *lstp = last_lst; | 
|---|
|  | 165 | return; | 
|---|
|  | 166 | } | 
|---|
|  | 167 |  | 
|---|
|  | 168 | utc_gst (mjd_day(mjd), mjd_hr(mjd), &lst); | 
|---|
|  | 169 | lst += radhr(lng); | 
|---|
|  | 170 |  | 
|---|
|  | 171 | obliquity(mjd, &eps); | 
|---|
|  | 172 | nutation(mjd, &deps, &dpsi); | 
|---|
|  | 173 | lst += radhr(dpsi*cos(eps+deps)); | 
|---|
|  | 174 |  | 
|---|
|  | 175 | range (&lst, 24.0); | 
|---|
|  | 176 |  | 
|---|
|  | 177 | last_mjd = mjd; | 
|---|
|  | 178 | last_lng = lng; | 
|---|
|  | 179 | *lstp = last_lst = lst; | 
|---|
|  | 180 | } | 
|---|
|  | 181 |  | 
|---|
| [2818] | 182 | /* convert ra to ha, in range 0..2*PI | 
|---|
| [1457] | 183 | * need dec too if not already apparent. | 
|---|
|  | 184 | */ | 
|---|
|  | 185 | void | 
|---|
| [2551] | 186 | radec2ha (Now *np, double ra, double dec, double *hap) | 
|---|
| [1457] | 187 | { | 
|---|
|  | 188 | double ha, lst; | 
|---|
|  | 189 |  | 
|---|
|  | 190 | if (epoch != EOD) | 
|---|
|  | 191 | as_ap (np, epoch, &ra, &dec); | 
|---|
|  | 192 | now_lst (np, &lst); | 
|---|
|  | 193 | ha = hrrad(lst) - ra; | 
|---|
| [2818] | 194 | if (ha < 0) | 
|---|
|  | 195 | ha += 2*PI; | 
|---|
| [1457] | 196 | *hap = ha; | 
|---|
|  | 197 | } | 
|---|
|  | 198 |  | 
|---|
| [2818] | 199 | /* find Greenwich Hour Angle of the given object at the given time, 0..2*PI. | 
|---|
|  | 200 | */ | 
|---|
|  | 201 | void | 
|---|
|  | 202 | gha (Now *np, Obj *op, double *ghap) | 
|---|
|  | 203 | { | 
|---|
|  | 204 | Now n = *np; | 
|---|
|  | 205 | Obj o = *op; | 
|---|
|  | 206 | double tmp; | 
|---|
|  | 207 |  | 
|---|
|  | 208 | n.n_epoch = EOD; | 
|---|
|  | 209 | n.n_lng = 0.0; | 
|---|
|  | 210 | n.n_lat = 0.0; | 
|---|
|  | 211 | obj_cir (&n, &o); | 
|---|
|  | 212 | now_lst (&n, &tmp); | 
|---|
|  | 213 | tmp = hrrad(tmp) - o.s_ra; | 
|---|
|  | 214 | if (tmp < 0) | 
|---|
|  | 215 | tmp += 2*PI; | 
|---|
|  | 216 | *ghap = tmp; | 
|---|
|  | 217 | } | 
|---|
|  | 218 |  | 
|---|
| [1457] | 219 | /* given a circle and a line segment, find a segment of the line inside the | 
|---|
|  | 220 | *   circle. | 
|---|
|  | 221 | * return 0 and the segment end points if one exists, else -1. | 
|---|
|  | 222 | * We use a parametric representation of the line: | 
|---|
|  | 223 | *   x = x1 + (x2-x1)*t and y = y1 + (y2-y1)*t, 0 < t < 1 | 
|---|
|  | 224 | * and a centered representation of the circle: | 
|---|
|  | 225 | *   (x - xc)**2 + (y - yc)**2 = r**2 | 
|---|
|  | 226 | * and solve for the t's that work, checking for usual conditions. | 
|---|
|  | 227 | */ | 
|---|
|  | 228 | int | 
|---|
| [2551] | 229 | lc ( | 
|---|
|  | 230 | int cx, int cy, int cw,                 /* circle bbox corner and width */ | 
|---|
|  | 231 | int x1, int y1, int x2, int y2,         /* line segment endpoints */ | 
|---|
|  | 232 | int *sx1, int *sy1, int *sx2, int *sy2) /* segment inside the circle */ | 
|---|
| [1457] | 233 | { | 
|---|
|  | 234 | int dx = x2 - x1; | 
|---|
|  | 235 | int dy = y2 - y1; | 
|---|
|  | 236 | int r = cw/2; | 
|---|
|  | 237 | int xc = cx + r; | 
|---|
|  | 238 | int yc = cy + r; | 
|---|
|  | 239 | int A = x1 - xc; | 
|---|
|  | 240 | int B = y1 - yc; | 
|---|
|  | 241 | double a = dx*dx + dy*dy;       /* O(2 * 2**16 * 2**16) */ | 
|---|
|  | 242 | double b = 2*(dx*A + dy*B);     /* O(4 * 2**16 * 2**16) */ | 
|---|
|  | 243 | double c = A*A + B*B - r*r;     /* O(2 * 2**16 * 2**16) */ | 
|---|
|  | 244 | double d = b*b - 4*a*c;         /* O(2**32 * 2**32) */ | 
|---|
|  | 245 | double sqrtd; | 
|---|
|  | 246 | double t1, t2; | 
|---|
|  | 247 |  | 
|---|
|  | 248 | if (d <= 0) | 
|---|
|  | 249 | return (-1);        /* containing line is purely outside circle */ | 
|---|
|  | 250 |  | 
|---|
|  | 251 | sqrtd = sqrt(d); | 
|---|
|  | 252 | t1 = (-b - sqrtd)/(2.0*a); | 
|---|
|  | 253 | t2 = (-b + sqrtd)/(2.0*a); | 
|---|
|  | 254 |  | 
|---|
|  | 255 | if (t1 >= 1.0 || t2 <= 0.0) | 
|---|
|  | 256 | return (-1);        /* segment is purely outside circle */ | 
|---|
|  | 257 |  | 
|---|
|  | 258 | /* we know now that some part of the segment is inside, | 
|---|
|  | 259 | * ie, t1 < 1 && t2 > 0 | 
|---|
|  | 260 | */ | 
|---|
|  | 261 |  | 
|---|
|  | 262 | if (t1 <= 0.0) { | 
|---|
|  | 263 | /* (x1,y1) is inside circle */ | 
|---|
|  | 264 | *sx1 = x1; | 
|---|
|  | 265 | *sy1 = y1; | 
|---|
|  | 266 | } else { | 
|---|
|  | 267 | *sx1 = (int)(x1 + dx*t1); | 
|---|
|  | 268 | *sy1 = (int)(y1 + dy*t1); | 
|---|
|  | 269 | } | 
|---|
|  | 270 |  | 
|---|
|  | 271 | if (t2 >= 1.0) { | 
|---|
|  | 272 | /* (x2,y2) is inside circle */ | 
|---|
|  | 273 | *sx2 = x2; | 
|---|
|  | 274 | *sy2 = y2; | 
|---|
|  | 275 | } else { | 
|---|
|  | 276 | *sx2 = (int)(x1 + dx*t2); | 
|---|
|  | 277 | *sy2 = (int)(y1 + dy*t2); | 
|---|
|  | 278 | } | 
|---|
|  | 279 |  | 
|---|
|  | 280 | return (0); | 
|---|
|  | 281 | } | 
|---|
|  | 282 |  | 
|---|
|  | 283 | /* compute visual magnitude using the H/G parameters used in the Astro Almanac. | 
|---|
|  | 284 | * these are commonly used for asteroids. | 
|---|
|  | 285 | */ | 
|---|
|  | 286 | void | 
|---|
| [2551] | 287 | hg_mag ( | 
|---|
|  | 288 | double h, double g, | 
|---|
|  | 289 | double rp,      /* sun-obj dist, AU */ | 
|---|
|  | 290 | double rho,     /* earth-obj dist, AU */ | 
|---|
|  | 291 | double rsn,     /* sun-earth dist, AU */ | 
|---|
|  | 292 | double *mp) | 
|---|
| [1457] | 293 | { | 
|---|
|  | 294 | double psi_t, Psi_1, Psi_2, beta; | 
|---|
|  | 295 | double c; | 
|---|
|  | 296 | double tb2; | 
|---|
|  | 297 |  | 
|---|
|  | 298 | c = (rp*rp + rho*rho - rsn*rsn)/(2*rp*rho); | 
|---|
|  | 299 | if (c <= -1) | 
|---|
|  | 300 | beta = PI; | 
|---|
|  | 301 | else if (c >= 1) | 
|---|
|  | 302 | beta = 0; | 
|---|
|  | 303 | else | 
|---|
|  | 304 | beta = acos(c);; | 
|---|
|  | 305 | tb2 = tan(beta/2.0); | 
|---|
|  | 306 | /* psi_t = exp(log(tan(beta/2.0))*0.63); */ | 
|---|
|  | 307 | psi_t = pow (tb2, 0.63); | 
|---|
|  | 308 | Psi_1 = exp(-3.33*psi_t); | 
|---|
|  | 309 | /* psi_t = exp(log(tan(beta/2.0))*1.22); */ | 
|---|
|  | 310 | psi_t = pow (tb2, 1.22); | 
|---|
|  | 311 | Psi_2 = exp(-1.87*psi_t); | 
|---|
| [2551] | 312 | *mp = h + 5.0*log10(rp*rho); | 
|---|
|  | 313 | if (Psi_1 || Psi_2) *mp -= 2.5*log10((1-g)*Psi_1 + g*Psi_2); | 
|---|
| [1457] | 314 | } | 
|---|
|  | 315 |  | 
|---|
|  | 316 | /* given faintest desired mag, mag step magstp, image scale and object | 
|---|
|  | 317 | * magnitude and size, return diameter to draw object, in pixels, or 0 if | 
|---|
|  | 318 | * dimmer than fmag. | 
|---|
|  | 319 | */ | 
|---|
|  | 320 | int | 
|---|
| [2551] | 321 | magdiam ( | 
|---|
|  | 322 | int fmag,       /* faintest mag */ | 
|---|
|  | 323 | int magstp,     /* mag range per dot size */ | 
|---|
|  | 324 | double scale,   /* rads per pixel */ | 
|---|
|  | 325 | double mag,     /* magnitude */ | 
|---|
|  | 326 | double size)    /* rads, or 0 */ | 
|---|
| [1457] | 327 | { | 
|---|
|  | 328 | int diam, sized; | 
|---|
|  | 329 |  | 
|---|
|  | 330 | if (mag > fmag) | 
|---|
|  | 331 | return (0); | 
|---|
|  | 332 | diam = (int)((fmag - mag)/magstp + 1); | 
|---|
|  | 333 | sized = (int)(size/scale + 0.5); | 
|---|
|  | 334 | if (sized > diam) | 
|---|
|  | 335 | diam = sized; | 
|---|
|  | 336 |  | 
|---|
|  | 337 | return (diam); | 
|---|
|  | 338 | } | 
|---|
|  | 339 |  | 
|---|
|  | 340 | /* computer visual magnitude using the g/k parameters commonly used for comets. | 
|---|
|  | 341 | */ | 
|---|
|  | 342 | void | 
|---|
| [2551] | 343 | gk_mag ( | 
|---|
|  | 344 | double g, double k, | 
|---|
|  | 345 | double rp,      /* sun-obj dist, AU */ | 
|---|
|  | 346 | double rho,     /* earth-obj dist, AU */ | 
|---|
|  | 347 | double *mp) | 
|---|
| [1457] | 348 | { | 
|---|
|  | 349 | *mp = g + 5.0*log10(rho) + 2.5*k*log10(rp); | 
|---|
|  | 350 | } | 
|---|
|  | 351 |  | 
|---|
|  | 352 | /* given a string convert to floating point and return it as a double. | 
|---|
|  | 353 | * this is to isolate possible unportabilities associated with declaring atof(). | 
|---|
|  | 354 | * it's worth it because atof() is often some 50% faster than sscanf ("%lf"); | 
|---|
|  | 355 | */ | 
|---|
|  | 356 | double | 
|---|
| [2551] | 357 | atod (char *buf) | 
|---|
| [1457] | 358 | { | 
|---|
| [2551] | 359 | return (strtod (buf, NULL)); | 
|---|
| [1457] | 360 | } | 
|---|
|  | 361 |  | 
|---|
|  | 362 | /* solve a spherical triangle: | 
|---|
|  | 363 | *           A | 
|---|
|  | 364 | *          /  \ | 
|---|
|  | 365 | *         /    \ | 
|---|
|  | 366 | *      c /      \ b | 
|---|
|  | 367 | *       /        \ | 
|---|
|  | 368 | *      /          \ | 
|---|
|  | 369 | *    B ____________ C | 
|---|
|  | 370 | *           a | 
|---|
|  | 371 | * | 
|---|
|  | 372 | * given A, b, c find B and a in range 0..B..2PI and 0..a..PI, respectively.. | 
|---|
|  | 373 | * cap and Bp may be NULL if not interested in either one. | 
|---|
|  | 374 | * N.B. we pass in cos(c) and sin(c) because in many problems one of the sides | 
|---|
|  | 375 | *   remains constant for many values of A and b. | 
|---|
|  | 376 | */ | 
|---|
|  | 377 | void | 
|---|
| [2551] | 378 | solve_sphere (double A, double b, double cc, double sc, double *cap, double *Bp) | 
|---|
| [1457] | 379 | { | 
|---|
|  | 380 | double cb = cos(b), sb = sin(b); | 
|---|
| [2551] | 381 | double sA, cA = cos(A); | 
|---|
|  | 382 | double x, y; | 
|---|
| [1457] | 383 | double ca; | 
|---|
|  | 384 | double B; | 
|---|
|  | 385 |  | 
|---|
|  | 386 | ca = cb*cc + sb*sc*cA; | 
|---|
|  | 387 | if (ca >  1.0) ca =  1.0; | 
|---|
|  | 388 | if (ca < -1.0) ca = -1.0; | 
|---|
|  | 389 | if (cap) | 
|---|
|  | 390 | *cap = ca; | 
|---|
|  | 391 |  | 
|---|
|  | 392 | if (!Bp) | 
|---|
|  | 393 | return; | 
|---|
|  | 394 |  | 
|---|
| [2653] | 395 | if (sc < 1e-7) | 
|---|
|  | 396 | B = cc < 0 ? A : PI-A; | 
|---|
|  | 397 | else { | 
|---|
|  | 398 | sA = sin(A); | 
|---|
|  | 399 | y = sA*sb*sc; | 
|---|
|  | 400 | x = cb - ca*cc; | 
|---|
|  | 401 | B = y ? (x ? atan2(y,x) : (y>0 ? PI/2 : -PI/2)) : (x>=0 ? 0 : PI); | 
|---|
|  | 402 | } | 
|---|
| [1457] | 403 |  | 
|---|
|  | 404 | *Bp = B; | 
|---|
|  | 405 | range (Bp, 2*PI); | 
|---|
|  | 406 | } | 
|---|
|  | 407 |  | 
|---|
|  | 408 | /* #define WANT_MATHERR if your system supports it. it gives SGI fits. | 
|---|
|  | 409 | */ | 
|---|
|  | 410 | #undef WANT_MATHERR | 
|---|
|  | 411 | #if defined(WANT_MATHERR) | 
|---|
|  | 412 | /* attempt to do *something* reasonable when a math function blows. | 
|---|
|  | 413 | */ | 
|---|
|  | 414 | matherr (xp) | 
|---|
|  | 415 | struct exception *xp; | 
|---|
|  | 416 | { | 
|---|
|  | 417 | static char *names[8] = { | 
|---|
|  | 418 | "acos", "asin", "atan2", "pow", | 
|---|
|  | 419 | "exp", "log", "log10", "sqrt" | 
|---|
|  | 420 | }; | 
|---|
|  | 421 | int i; | 
|---|
|  | 422 |  | 
|---|
|  | 423 | /* catch-all */ | 
|---|
|  | 424 | xp->retval = 0.0; | 
|---|
|  | 425 |  | 
|---|
|  | 426 | for (i = 0; i < sizeof(names)/sizeof(names[0]); i++) | 
|---|
|  | 427 | if (strcmp (xp->name, names[i]) == 0) | 
|---|
|  | 428 | switch (i) { | 
|---|
|  | 429 | case 0: /* acos */ | 
|---|
|  | 430 | xp->retval = xp->arg1 >= 1.0 ? 0.0 : -PI; | 
|---|
|  | 431 | break; | 
|---|
|  | 432 | case 1: /* asin */ | 
|---|
|  | 433 | xp->retval = xp->arg1 >= 1.0 ? PI/2 : -PI/2; | 
|---|
|  | 434 | break; | 
|---|
|  | 435 | case 2: /* atan2 */ | 
|---|
|  | 436 | if (xp->arg1 == 0.0) | 
|---|
|  | 437 | xp->retval = xp->arg2 < 0.0 ? PI : 0.0; | 
|---|
|  | 438 | else if (xp->arg2 == 0.0) | 
|---|
|  | 439 | xp->retval = xp->arg1 < 0.0 ? -PI/2 : PI/2; | 
|---|
|  | 440 | else | 
|---|
|  | 441 | xp->retval = 0.0; | 
|---|
|  | 442 | break; | 
|---|
|  | 443 | case 3: /* pow */ | 
|---|
|  | 444 | /* FALLTHRU */ | 
|---|
|  | 445 | case 4: /* exp */ | 
|---|
|  | 446 | xp->retval = xp->o_type == OVERFLOW ? 1e308 : 0.0; | 
|---|
|  | 447 | break; | 
|---|
|  | 448 | case 5: /* log */ | 
|---|
|  | 449 | /* FALLTHRU */ | 
|---|
|  | 450 | case 6: /* log10 */ | 
|---|
|  | 451 | xp->retval = xp->arg1 <= 0.0 ? -1e308 : 0; | 
|---|
|  | 452 | break; | 
|---|
|  | 453 | case 7: /* sqrt */ | 
|---|
|  | 454 | xp->retval = 0.0; | 
|---|
|  | 455 | break; | 
|---|
|  | 456 | } | 
|---|
|  | 457 |  | 
|---|
|  | 458 | return (1);     /* suppress default error handling */ | 
|---|
|  | 459 | } | 
|---|
|  | 460 | #endif | 
|---|
|  | 461 |  | 
|---|
|  | 462 | /* given the difference in two RA's, in rads, return their difference, | 
|---|
|  | 463 | *   accounting for wrap at 2*PI. caller need *not* first force it into the | 
|---|
|  | 464 | *   range 0..2*PI. | 
|---|
|  | 465 | */ | 
|---|
|  | 466 | double | 
|---|
| [2551] | 467 | delra (double dra) | 
|---|
| [1457] | 468 | { | 
|---|
|  | 469 | double fdra = fmod(fabs(dra), 2*PI); | 
|---|
|  | 470 |  | 
|---|
|  | 471 | if (fdra > PI) | 
|---|
|  | 472 | fdra = 2*PI - fdra; | 
|---|
|  | 473 | return (fdra); | 
|---|
|  | 474 | } | 
|---|
|  | 475 |  | 
|---|
|  | 476 | /* return 1 if object is considered to be "deep sky", else 0. | 
|---|
|  | 477 | * The only things deep-sky are fixed objects other than stars. | 
|---|
|  | 478 | */ | 
|---|
|  | 479 | int | 
|---|
| [2551] | 480 | is_deepsky (Obj *op) | 
|---|
| [1457] | 481 | { | 
|---|
|  | 482 | int deepsky = 0; | 
|---|
|  | 483 |  | 
|---|
|  | 484 | if (is_type(op, FIXEDM)) { | 
|---|
|  | 485 | switch (op->f_class) { | 
|---|
|  | 486 | case 'T': | 
|---|
|  | 487 | case 'B': | 
|---|
|  | 488 | case 'D': | 
|---|
|  | 489 | case 'M': | 
|---|
|  | 490 | case 'S': | 
|---|
|  | 491 | case 'V': | 
|---|
|  | 492 | break; | 
|---|
|  | 493 | default: | 
|---|
|  | 494 | deepsky = 1; | 
|---|
|  | 495 | break; | 
|---|
|  | 496 | } | 
|---|
|  | 497 | } | 
|---|
|  | 498 |  | 
|---|
|  | 499 | return (deepsky); | 
|---|
|  | 500 | } | 
|---|
|  | 501 |  | 
|---|
|  | 502 | /* For RCS Only -- Do Not Edit */ | 
|---|
| [3477] | 503 | static char *rcsid[2] = {(char *)rcsid, "@(#) $RCSfile: misc.c,v $ $Date: 2008-03-25 17:45:15 $ $Revision: 1.8 $ $Name: not supported by cvs2svn $"}; | 
|---|