]> git.mxchange.org Git - simgear.git/blob - Lib/Math/fg_geodesy.cxx
Fixed an IRIX warning message where an inline function is referenced
[simgear.git] / Lib / Math / fg_geodesy.cxx
1 // fg_geodesy.cxx -- routines to convert between geodetic and geocentric 
2 //                   coordinate systems.
3 //
4 // Copied and adapted directly from LaRCsim/ls_geodesy.c
5 //
6 // See below for the complete original LaRCsim comments.
7 //
8 // $Id$
9
10 #include "Include/compiler.h"
11 #ifdef FG_HAVE_STD_INCLUDES
12 # include <cmath>
13 # include <cerrno>
14 #else
15 # include <math.h>
16 # include <errno.h>
17 #endif
18
19 #include <Include/fg_constants.h>
20 #include <Math/fg_geodesy.hxx>
21 #include <Math/point3d.hxx>
22
23 #ifndef FG_HAVE_NATIVE_SGI_COMPILERS
24 FG_USING_STD(cout);
25 #endif
26
27 // ONE_SECOND is pi/180/60/60, or about 100 feet at earths' equator
28 #define ONE_SECOND 4.848136811E-6
29
30
31 // fgGeocToGeod(lat_geoc, radius, *lat_geod, *alt, *sea_level_r)
32 //     INPUTS:  
33 //         lat_geoc     Geocentric latitude, radians, + = North
34 //         radius       C.G. radius to earth center (meters)
35 //
36 //     OUTPUTS:
37 //         lat_geod     Geodetic latitude, radians, + = North
38 //         alt          C.G. altitude above mean sea level (meters)
39 //         sea_level_r  radius from earth center to sea level at
40 //                      local vertical (surface normal) of C.G. (meters)
41
42
43 void fgGeocToGeod( double lat_geoc, double radius, double
44                    *lat_geod, double *alt, double *sea_level_r )
45 {
46     double t_lat, x_alpha, mu_alpha, delt_mu, r_alpha, l_point, rho_alpha;
47     double sin_mu_a, denom,delt_lambda, lambda_sl, sin_lambda_sl;
48
49     if( ( (FG_PI_2 - lat_geoc) < ONE_SECOND )        // near North pole
50         || ( (FG_PI_2 + lat_geoc) < ONE_SECOND ) )   // near South pole
51     {
52         *lat_geod = lat_geoc;
53         *sea_level_r = EQUATORIAL_RADIUS_M*E;
54         *alt = radius - *sea_level_r;
55     } else {
56         t_lat = tan(lat_geoc);
57         x_alpha = E*EQUATORIAL_RADIUS_M/sqrt(t_lat*t_lat + E*E);
58         double tmp = RESQ_M - x_alpha * x_alpha;
59         if ( tmp < 0.0 ) { tmp = 0.0; }
60         mu_alpha = atan2(sqrt(tmp),E*x_alpha);
61         if (lat_geoc < 0) mu_alpha = - mu_alpha;
62         sin_mu_a = sin(mu_alpha);
63         delt_lambda = mu_alpha - lat_geoc;
64         r_alpha = x_alpha/cos(lat_geoc);
65         l_point = radius - r_alpha;
66         *alt = l_point*cos(delt_lambda);
67
68         // check for domain error
69         if ( errno == EDOM ) {
70             cout << "Domain ERROR in fgGeocToGeod!!!!\n";
71             *alt = 0.0;
72         }
73
74         denom = sqrt(1-EPS*EPS*sin_mu_a*sin_mu_a);
75         rho_alpha = EQUATORIAL_RADIUS_M*(1-EPS)/
76             (denom*denom*denom);
77         delt_mu = atan2(l_point*sin(delt_lambda),rho_alpha + *alt);
78         *lat_geod = mu_alpha - delt_mu;
79         lambda_sl = atan( E*E * tan(*lat_geod) ); // SL geoc. latitude
80         sin_lambda_sl = sin( lambda_sl );
81         *sea_level_r = 
82             sqrt(RESQ_M / (1 + ((1/(E*E))-1)*sin_lambda_sl*sin_lambda_sl));
83
84         // check for domain error
85         if ( errno == EDOM ) {
86             cout << "Domain ERROR in fgGeocToGeod!!!!\n";
87             *sea_level_r = 0.0;
88         }
89     }
90
91 }
92
93
94 // fgGeodToGeoc( lat_geod, alt, *sl_radius, *lat_geoc )
95 //     INPUTS:  
96 //         lat_geod     Geodetic latitude, radians, + = North
97 //         alt          C.G. altitude above mean sea level (meters)
98 //
99 //     OUTPUTS:
100 //         sl_radius    SEA LEVEL radius to earth center (meters)
101 //                      (add Altitude to get true distance from earth center.
102 //         lat_geoc     Geocentric latitude, radians, + = North
103 //
104
105
106 void fgGeodToGeoc( double lat_geod, double alt, double *sl_radius,
107                       double *lat_geoc )
108 {
109     double lambda_sl, sin_lambda_sl, cos_lambda_sl, sin_mu, cos_mu, px, py;
110     
111     lambda_sl = atan( E*E * tan(lat_geod) ); // sea level geocentric latitude
112     sin_lambda_sl = sin( lambda_sl );
113     cos_lambda_sl = cos( lambda_sl );
114     sin_mu = sin(lat_geod);                  // Geodetic (map makers') latitude
115     cos_mu = cos(lat_geod);
116     *sl_radius = 
117         sqrt(RESQ_M / (1 + ((1/(E*E))-1)*sin_lambda_sl*sin_lambda_sl));
118     py = *sl_radius*sin_lambda_sl + alt*sin_mu;
119     px = *sl_radius*cos_lambda_sl + alt*cos_mu;
120     *lat_geoc = atan2( py, px );
121 }
122
123
124 /***************************************************************************
125
126         TITLE:  ls_geodesy
127         
128 ----------------------------------------------------------------------------
129
130         FUNCTION:       Converts geocentric coordinates to geodetic positions
131
132 ----------------------------------------------------------------------------
133
134         MODULE STATUS:  developmental
135
136 ----------------------------------------------------------------------------
137
138         GENEALOGY:      Written as part of LaRCSim project by E. B. Jackson
139
140 ----------------------------------------------------------------------------
141
142         DESIGNED BY:    E. B. Jackson
143         
144         CODED BY:       E. B. Jackson
145         
146         MAINTAINED BY:  E. B. Jackson
147
148 ----------------------------------------------------------------------------
149
150         MODIFICATION HISTORY:
151         
152         DATE    PURPOSE                                         BY
153         
154         930208  Modified to avoid singularity near polar region.        EBJ
155         930602  Moved backwards calcs here from ls_step.                EBJ
156         931214  Changed erroneous Latitude and Altitude variables to 
157                 *lat_geod and *alt in routine ls_geoc_to_geod.          EBJ
158         940111  Changed header files from old ls_eom.h style to ls_types, 
159                 and ls_constants.  Also replaced old DATA type with new
160                 SCALAR type.                                            EBJ
161
162         CURRENT RCS HEADER:
163
164 $Header$
165  * Revision 1.5  1994/01/11  18:47:05  bjax
166  * Changed include files to use types and constants, not ls_eom.h
167  * Also changed DATA type to SCALAR type.
168  *
169  * Revision 1.4  1993/12/14  21:06:47  bjax
170  * Removed global variable references Altitude and Latitude.   EBJ
171  *
172  * Revision 1.3  1993/06/02  15:03:40  bjax
173  * Made new subroutine for calculating geodetic to geocentric; changed name
174  * of forward conversion routine from ls_geodesy to ls_geoc_to_geod.
175  *
176
177 ----------------------------------------------------------------------------
178
179         REFERENCES:
180
181                 [ 1]    Stevens, Brian L.; and Lewis, Frank L.: "Aircraft 
182                         Control and Simulation", Wiley and Sons, 1992.
183                         ISBN 0-471-61397-5                    
184
185
186 ----------------------------------------------------------------------------
187
188         CALLED BY:      ls_aux
189
190 ----------------------------------------------------------------------------
191
192         CALLS TO:
193
194 ----------------------------------------------------------------------------
195
196         INPUTS: 
197                 lat_geoc        Geocentric latitude, radians, + = North
198                 radius          C.G. radius to earth center, ft
199
200 ----------------------------------------------------------------------------
201
202         OUTPUTS:
203                 lat_geod        Geodetic latitude, radians, + = North
204                 alt             C.G. altitude above mean sea level, ft
205                 sea_level_r     radius from earth center to sea level at
206                                 local vertical (surface normal) of C.G.
207
208 --------------------------------------------------------------------------*/
209
210