OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
ctotc.c
Go to the documentation of this file.
1 /*
2  *----------------------------------------------------------------------
3  * @(#) ctotc.c 1.0 20 Mar 93 <shc>
4  * Copyright (c) 1993, CSIRO Division of Oceanography.
5  *----------------------------------------------------------------------
6  *
7  * ctotc --
8  *
9  * Rectangular (Cartesian) to topocentric coordinate conversion.
10  *
11  * Results:
12  *
13  * Given the rectangular (Cartesian) earth-centred coordinates of an
14  * object, the latitude, longitude and height above the geoid of
15  * an observer and the Greenwich Hour angle, calculate the topocentric
16  * coordinates of the object (azimuth, elevation and range) and,
17  * optionally, derivatives of these wrt Cartesian.
18  * Units are radians, metres and seconds.
19  *
20  * Azimuth, elevation and range are returned in TOP. If "DAER"
21  * is non-NULL, the 3x3 Jacobian of topocentric coordinates wrt
22  * rectangular coordinates is returned in DAER.
23  *
24  * Side effects:
25  * None.
26  *
27  * History:
28  * 17 Dec 90 <shc>
29  * Initial version
30  *
31  * 23 Jan 91 <shc>
32  * Reduced number of trig routine calls
33  *
34  * 20 Mar 93 <shc>
35  * Converted from FORTRAN to C
36  *
37  *----------------------------------------------------------------------
38  */
39 
40 #include "orbit.h"
41 
42 void
43 ctotc(r, obs, gha, top, daer)
44 double r[3]; /* Rectangular coordinates of object (metres) */
45 struct GEODETIC *obs; /* Observer's lat, lon (radians) and height (m) */
46 double gha; /* Greenwich hour angle (radians) */
47 struct TOPOCENTRIC *top; /* Resulting az, el and range */
48 double daer[3][3]; /* Jacobian of (az,el,range) wrt (x,y,z) */
49 {
50  int i, j;
51  double olat, olon, ohgt, clat, clon, slat, slon;
52  double ens, xo, yo, zo, xos, yos, zos, xlt, ylt, zlt;
53  double rngsq, range;
54  double emlt[3][3], dlt[3][3];
55  /*
56  * Observer geodetic coordinates (latitude, longitude and height) in
57  * radians and metres.
58  */
59  olat = obs->lat;
60  olon = AN2PI(obs->lon + gha);
61  ohgt = obs->height;
62 
63  clat = cos(olat);
64  clon = cos(olon);
65  slat = sin(olat);
66  slon = sin(olon);
67  /*
68  * Rotation matrix to bring geocentric reference frame
69  * parallel to local tangent reference frame.
70  */
71  emlt[0][0] = -slon;
72  emlt[0][1] = clon;
73  emlt[0][2] = 0.0;
74  emlt[1][0] = -slat*clon;
75  emlt[1][1] = -slat*slon;
76  emlt[1][2] = clat;
77  emlt[2][0] = clat*clon;
78  emlt[2][1] = clat*slon;
79  emlt[2][2] = slat;
80  /*
81  * Geocentric vector to observer
82  */
83  ens = EQRAD / sqrt(1.0 - FLT * (2.0 - FLT) * slat * slat);
84  xo = (ens + ohgt) * clat * clon;
85  yo = (ens + ohgt) * clat * slon;
86  zo = (ens * (1.0 - FLT)*(1.0 - FLT) + ohgt) * slat;
87  /*
88  * Vector from observer to object
89  */
90  xos = r[0] - xo;
91  yos = r[1] - yo;
92  zos = r[2] - zo;
93  /*
94  * Position of object in local tangent reference frame
95  */
96  xlt = emlt[0][0] * xos + emlt[0][1] * yos + emlt[0][2] * zos;
97  ylt = emlt[1][0] * xos + emlt[1][1] * yos + emlt[1][2] * zos;
98  zlt = emlt[2][0] * xos + emlt[2][1] * yos + emlt[2][2] * zos;
99  /*
100  * Spacecraft azimuth, elevation and range
101  */
102  rngsq = xlt * xlt + ylt * ylt + zlt*zlt;
103  range = sqrt(rngsq);
104  top->az = AN2PI(atan2(xlt, ylt));
105  top->el = asin(zlt / range);
106  top->range = range;
107  /*
108  * Optionally calculate derivatives of azimuth, elevation and range
109  * with respect to the object rectangular coordinates.
110  */
111  if (daer != NULL) {
112  double a1, a2;
113  /*
114  * Derivatives of azimuth (DLT[0][*]), elevation (DLT[1][*]) and
115  * range (DLT[2][*]) wrt object position in local tangent frame.
116  */
117  a1 = xlt * xlt + ylt*ylt;
118  a2 = sqrt(a1);
119  dlt[0][0] = ylt / a1;
120  dlt[0][1] = -xlt / a1;
121  dlt[0][2] = 0.0;
122  dlt[1][0] = -zlt * xlt / (rngsq * a2);
123  dlt[1][1] = -zlt * ylt / (rngsq * a2);
124  dlt[1][2] = a2 / rngsq;
125  dlt[2][0] = xlt / range;
126  dlt[2][1] = ylt / range;
127  dlt[2][2] = zlt / range;
128  /*
129  * Convert derivatives wrt local tangent frame to derivatives wrt
130  * geocentric reference frame: Product[dlt, emlt].
131  */
132  for (i = 0; i < 3; i++) {
133  for (j = 0; j < 3; j++) {
134  daer[i][j] = dlt[i][0] * emlt[0][j] +
135  dlt[i][1] * emlt[1][j] +
136  dlt[i][2] * emlt[2][j];
137  }
138  }
139  }
140 
141  return;
142 }
int r
Definition: decode_rs.h:73
int j
Definition: decode_rs.h:73
#define EQRAD
Definition: earth.h:33
double height
Definition: orbit.h:119
#define NULL
Definition: decode_rs.h:63
void ctotc(r, struct GEODETIC *obs, double gha, struct TOPOCENTRIC *top, daer)
Definition: ctotc.c:43
double lon
Definition: orbit.h:118
#define AN2PI(X)
Definition: orbit.h:57
float dlt
Definition: atrem_cor.h:94
int i
Definition: decode_rs.h:71
#define FLT
Definition: earth.h:31
double lat
Definition: orbit.h:117