241
242
* Latitude : Calculated latitude value in radians. (output)
242
243
* Longitude : Calculated longitude value in radians. (output)
243
244
* Height : Calculated height value, in meters. (output)
247
#define USE_ITERATIVE_METHOD
249
void pj_Convert_Geocentric_To_Geodetic (double X,
255
{ /* BEGIN Convert_Geocentric_To_Geodetic */
256
#if !defined(USE_ITERATIVE_METHOD)
245
258
* The method used here is derived from 'An Improved Algorithm for
246
259
* Geocentric to Geodetic Coordinate Conversion', by Ralph Toms, Feb 1996
249
262
/* Note: Variable names follow the notation used in Toms, Feb 1996 */
251
double W; /* distance from Z axis */
252
double W2; /* square of distance from Z axis */
253
double T0; /* initial estimate of vertical component */
254
double T1; /* corrected estimate of vertical component */
255
double S0; /* initial estimate of horizontal component */
256
double S1; /* corrected estimate of horizontal component */
257
double Sin_B0; /* sin(B0), B0 is estimate of Bowring aux variable */
258
double Sin3_B0; /* cube of sin(B0) */
259
double Cos_B0; /* cos(B0) */
260
double Sin_p1; /* sin(phi1), phi1 is estimated latitude */
261
double Cos_p1; /* cos(phi1) */
262
double Rn; /* Earth radius at location */
263
double Sum; /* numerator of cos(phi1) */
264
int At_Pole; /* indicates location is in polar region */
269
*Longitude = atan2(Y,X);
275
*Longitude = PI_OVER_2;
279
*Longitude = -PI_OVER_2;
287
*Latitude = PI_OVER_2;
291
*Latitude = -PI_OVER_2;
294
{ /* center of earth */
295
*Latitude = PI_OVER_2;
296
*Height = -Geocent_b;
304
S0 = sqrt(T0 * T0 + W2);
307
Sin3_B0 = Sin_B0 * Sin_B0 * Sin_B0;
308
T1 = Z + Geocent_b * Geocent_ep2 * Sin3_B0;
309
Sum = W - Geocent_a * Geocent_e2 * Cos_B0 * Cos_B0 * Cos_B0;
310
S1 = sqrt(T1*T1 + Sum * Sum);
313
Rn = Geocent_a / sqrt(1.0 - Geocent_e2 * Sin_p1 * Sin_p1);
314
if (Cos_p1 >= COS_67P5)
316
*Height = W / Cos_p1 - Rn;
318
else if (Cos_p1 <= -COS_67P5)
320
*Height = W / -Cos_p1 - Rn;
324
*Height = Z / Sin_p1 + Rn * (Geocent_e2 - 1.0);
326
if (At_Pole == FALSE)
328
*Latitude = atan(Sin_p1 / Cos_p1);
264
double W; /* distance from Z axis */
265
double W2; /* square of distance from Z axis */
266
double T0; /* initial estimate of vertical component */
267
double T1; /* corrected estimate of vertical component */
268
double S0; /* initial estimate of horizontal component */
269
double S1; /* corrected estimate of horizontal component */
270
double Sin_B0; /* sin(B0), B0 is estimate of Bowring aux variable */
271
double Sin3_B0; /* cube of sin(B0) */
272
double Cos_B0; /* cos(B0) */
273
double Sin_p1; /* sin(phi1), phi1 is estimated latitude */
274
double Cos_p1; /* cos(phi1) */
275
double Rn; /* Earth radius at location */
276
double Sum; /* numerator of cos(phi1) */
277
int At_Pole; /* indicates location is in polar region */
282
*Longitude = atan2(Y,X);
288
*Longitude = PI_OVER_2;
292
*Longitude = -PI_OVER_2;
300
*Latitude = PI_OVER_2;
304
*Latitude = -PI_OVER_2;
307
{ /* center of earth */
308
*Latitude = PI_OVER_2;
309
*Height = -Geocent_b;
317
S0 = sqrt(T0 * T0 + W2);
320
Sin3_B0 = Sin_B0 * Sin_B0 * Sin_B0;
321
T1 = Z + Geocent_b * Geocent_ep2 * Sin3_B0;
322
Sum = W - Geocent_a * Geocent_e2 * Cos_B0 * Cos_B0 * Cos_B0;
323
S1 = sqrt(T1*T1 + Sum * Sum);
326
Rn = Geocent_a / sqrt(1.0 - Geocent_e2 * Sin_p1 * Sin_p1);
327
if (Cos_p1 >= COS_67P5)
329
*Height = W / Cos_p1 - Rn;
331
else if (Cos_p1 <= -COS_67P5)
333
*Height = W / -Cos_p1 - Rn;
337
*Height = Z / Sin_p1 + Rn * (Geocent_e2 - 1.0);
339
if (At_Pole == FALSE)
341
*Latitude = atan(Sin_p1 / Cos_p1);
343
#else /* defined(USE_ITERATIVE_METHOD) */
347
* Wenzel, H.-G.(1985): Hochauflösende Kugelfunktionsmodelle für
348
* das Gravitationspotential der Erde. Wiss. Arb. Univ. Hannover
349
* Nr. 137, p. 130-131.
351
* Programmed by GGA- Leibniz-Institue of Applied Geophysics
354
* Federal Republic of Germany
355
* Internet: www.gga-hannover.de
357
* Hannover, March 1999, April 2004.
358
* see also: comments in statements
360
* Mathematically exact and because of symmetry of rotation-ellipsoid,
361
* each point (X,Y,Z) has at least two solutions (Latitude1,Longitude1,Height1) and
362
* (Latitude2,Longitude2,Height2). Is point=(0.,0.,Z) (P=0.), so you get even
363
* four solutions, every two symmetrical to the semi-minor axis.
364
* Here Height1 and Height2 have at least a difference in order of
365
* radius of curvature (e.g. (0,0,b)=> (90.,0.,0.) or (-90.,0.,-2b);
366
* (a+100.)*(sqrt(2.)/2.,sqrt(2.)/2.,0.) => (0.,45.,100.) or
367
* (0.,225.,-(2a+100.))).
368
* The algorithm always computes (Latitude,Longitude) with smallest |Height|.
369
* For normal computations, that means |Height|<10000.m, algorithm normally
370
* converges after to 2-3 steps!!!
371
* But if |Height| has the amount of length of ellipsoid's axis
372
* (e.g. -6300000.m), algorithm needs about 15 steps.
375
/* local defintions and variables */
376
/* end-criterium of loop, accuracy of sin(Latitude) */
378
#define genau2 (genau*genau)
381
double P; /* distance between semi-minor axis and location */
382
double RR; /* distance between center and location */
383
double CT; /* sin of geocentric latitude */
384
double ST; /* cos of geocentric latitude */
387
double RN; /* Earth radius at location */
388
double CPHI0; /* cos of start or old geodetic latitude in iterations */
389
double SPHI0; /* sin of start or old geodetic latitude in iterations */
390
double CPHI; /* cos of searched geodetic latitude */
391
double SPHI; /* sin of searched geodetic latitude */
392
double SDPHI; /* end-criterium: addition-theorem of sin(Latitude(iter)-Latitude(iter-1)) */
393
int At_Pole; /* indicates location is in polar region */
394
int iter; /* # of continous iteration, max. 30 is always enough (s.a.) */
398
RR = sqrt(X*X+Y*Y+Z*Z);
400
/* special cases for latitude and longitude */
401
if (P/Geocent_a < genau) {
403
/* special case, if P=0. (X=0., Y=0.) */
407
/* if (X,Y,Z)=(0.,0.,0.) then Height becomes semi-minor axis
408
* of ellipsoid (=center of mass), Latitude becomes PI/2 */
409
if (RR/Geocent_a < genau) {
410
*Latitude = PI_OVER_2;
411
*Height = -Geocent_b;
417
/* ellipsoidal (geodetic) longitude
418
* interval: -PI < Longitude <= +PI */
419
*Longitude=atan2(Y,X);
422
/* --------------------------------------------------------------
423
* Following iterative algorithm was developped by
424
* "Institut für Erdmessung", University of Hannover, July 1988.
425
* Internet: www.ife.uni-hannover.de
426
* Iterative computation of CPHI,SPHI and Height.
427
* Iteration of CPHI and SPHI to 10**-12 radian resp.
429
* --------------------------------------------------------------
433
RX = 1.0/sqrt(1.0-Geocent_e2*(2.0-Geocent_e2)*ST*ST);
434
CPHI0 = ST*(1.0-Geocent_e2)*RX;
438
/* loop to find sin(Latitude) resp. Latitude
439
* until |sin(Latitude(iter)-Latitude(iter-1))| < genau */
443
RN = Geocent_a/sqrt(1.0-Geocent_e2*SPHI0*SPHI0);
445
/* ellipsoidal (geodetic) height */
446
*Height = P*CPHI0+Z*SPHI0-RN*(1.0-Geocent_e2*SPHI0*SPHI0);
448
RK = Geocent_e2*RN/(RN+*Height);
449
RX = 1.0/sqrt(1.0-RK*(2.0-RK)*ST*ST);
450
CPHI = ST*(1.0-RK)*RX;
452
SDPHI = SPHI*CPHI0-CPHI*SPHI0;
456
while (SDPHI*SDPHI > genau2 && iter < maxiter);
458
/* ellipsoidal (geodetic) latitude */
459
*Latitude=atan(SPHI/fabs(CPHI));
462
#endif /* defined(USE_ITERATIVE_METHOD) */
330
463
} /* END OF Convert_Geocentric_To_Geodetic */