1 | #include <stdio.h>
|
---|
2 | #include <math.h>
|
---|
3 | #include "aa_hadec.h"
|
---|
4 | #define GOODATAN2
|
---|
5 | #define PI M_PI
|
---|
6 |
|
---|
7 | static void aaha_aux (double lat, double x, double y, double* p, double* q);
|
---|
8 |
|
---|
9 |
|
---|
10 | /* given latitude (n+, radians), lat, altitude (up+, radians), alt, and
|
---|
11 | * azimuth (angle round to the east from north+, radians),
|
---|
12 | * return hour angle (radians), ha, and declination (radians), dec.
|
---|
13 | */
|
---|
14 | void aa_hadec (double lat, double alt, double az, double* ha, double* dec)
|
---|
15 | {
|
---|
16 | aaha_aux (lat, az, alt, ha, dec);
|
---|
17 | }
|
---|
18 |
|
---|
19 | /* given latitude (n+, radians), lat, hour angle (radians), ha, and declination
|
---|
20 | * (radians), dec,
|
---|
21 | * return altitude (up+, radians), alt, and
|
---|
22 | * azimuth (angle round to the east from north+, radians),
|
---|
23 | */
|
---|
24 | void hadec_aa (double lat, double ha, double dec, double* alt, double* az)
|
---|
25 | {
|
---|
26 | aaha_aux (lat, ha, dec, az, alt);
|
---|
27 | }
|
---|
28 |
|
---|
29 | /* the actual formula is the same for both transformation directions so
|
---|
30 | * do it here once for each way.
|
---|
31 | * N.B. all arguments are in radians.
|
---|
32 | */
|
---|
33 | static void
|
---|
34 | aaha_aux (double lat, double x, double y, double* p, double* q)
|
---|
35 | {
|
---|
36 | static double lastlat = -1000.;
|
---|
37 | static double sinlastlat, coslastlat;
|
---|
38 | double sy, cy;
|
---|
39 | double sx, cx;
|
---|
40 | #ifndef GOODATAN2
|
---|
41 | double sq, cq;
|
---|
42 | double a;
|
---|
43 | double cp;
|
---|
44 | #endif
|
---|
45 |
|
---|
46 | /* latitude doesn't change much, so try to reuse the sin and cos evals.
|
---|
47 | */
|
---|
48 | if (lat != lastlat) {
|
---|
49 | sinlastlat = sin (lat);
|
---|
50 | coslastlat = cos (lat);
|
---|
51 | lastlat = lat;
|
---|
52 | }
|
---|
53 |
|
---|
54 | sy = sin (y);
|
---|
55 | cy = cos (y);
|
---|
56 | sx = sin (x);
|
---|
57 | cx = cos (x);
|
---|
58 |
|
---|
59 | /* define GOODATAN2 if atan2 returns full range -PI through +PI.
|
---|
60 | */
|
---|
61 | #ifdef GOODATAN2
|
---|
62 | *q = asin ((sy*sinlastlat) + (cy*coslastlat*cx));
|
---|
63 | *p = atan2 (-cy*sx, -cy*cx*sinlastlat + sy*coslastlat);
|
---|
64 | #else
|
---|
65 | #define EPS (1e-20)
|
---|
66 | sq = (sy*sinlastlat) + (cy*coslastlat*cx);
|
---|
67 | *q = asin (sq);
|
---|
68 | cq = cos (*q);
|
---|
69 | a = coslastlat*cq;
|
---|
70 | if (a > -EPS && a < EPS)
|
---|
71 | a = a < 0 ? -EPS : EPS; /* avoid / 0 */
|
---|
72 | cp = (sy - (sinlastlat*sq))/a;
|
---|
73 | if (cp >= 1.0) /* the /a can be slightly > 1 */
|
---|
74 | *p = 0.0;
|
---|
75 | else if (cp <= -1.0)
|
---|
76 | *p = PI;
|
---|
77 | else
|
---|
78 | *p = acos ((sy - (sinlastlat*sq))/a);
|
---|
79 | if (sx>0) *p = 2.0*PI - *p;
|
---|
80 | #endif
|
---|
81 | }
|
---|