@@ -9274,32 +9274,35 @@ void gmt_ECEF_forward (struct GMT_CTRL *GMT, double in[], double out[]) {
9274
9274
}
9275
9275
9276
9276
/*! . */
9277
- void gmt_ECEF_inverse (struct GMT_CTRL * GMT , double in [], double out []) {
9277
+ void gmt_ECEF_inverse (struct GMT_CTRL * GMT , double in [], double out []) {
9278
9278
/* Convert ECEF coordinates to geodetic lon, lat, height given the datum parameters.
9279
9279
* GMT->current.proj.datum.from is always the ellipsoid to use */
9280
9280
9281
9281
unsigned int i ;
9282
- double in_p [3 ], sin_lat , cos_lat , N , p , theta , sin_theta , cos_theta ;
9282
+ double in_p [3 ], sin_lat , cos_lat , N , p , r , theta , sin_theta , cos_theta , slam , clam , sphi , cphi ;
9283
9283
9284
9284
/* First remove the xyz shifts, us in_p to avoid changing in */
9285
9285
for (i = 0 ; i < 3 ; i ++ ) in_p [i ] = in [i ] - GMT -> current .proj .datum .from .xyz [i ];
9286
9286
9287
9287
p = hypot (in_p [GMT_X ], in_p [GMT_Y ]);
9288
- if (p > 0.0 ) { /* Not the S|N pole so we can invert */
9289
- theta = atan (in_p [GMT_Z ] * GMT -> current .proj .datum .from .a / (p * GMT -> current .proj .datum .from .b ));
9290
- sincos (theta , & sin_theta , & cos_theta );
9291
- out [GMT_X ] = d_atan2d (in_p [GMT_Y ], in_p [GMT_X ]);
9292
- out [GMT_Y ] = atand ((in_p [GMT_Z ] + GMT -> current .proj .datum .from .ep_squared * GMT -> current .proj .datum .from .b * pow (sin_theta , 3.0 )) / (p - GMT -> current .proj .datum .from .e_squared * GMT -> current .proj .datum .from .a * pow (cos_theta , 3.0 )));
9293
- if (in_p [GMT_Z ] > 0.0 && out [GMT_Y ] < 0.0 ) out [GMT_Y ] = - out [GMT_Y ];
9294
- if (in_p [GMT_Z ] < 0.0 && out [GMT_Y ] > 0.0 ) out [GMT_Y ] = - out [GMT_Y ];
9288
+ slam = p != 0 ? in_p [GMT_Y ] / p : 0 ;
9289
+ clam = p != 0 ? in_p [GMT_X ] / p : 1 ;
9290
+ theta = atan (in_p [GMT_Z ] * GMT -> current .proj .datum .from .a / (p * GMT -> current .proj .datum .from .b ));
9291
+ sincos (theta , & sin_theta , & cos_theta );
9292
+ sphi = in_p [GMT_Z ] + GMT -> current .proj .datum .from .ep_squared * GMT -> current .proj .datum .from .b * pow (sin_theta , 3.0 );
9293
+ cphi = p - GMT -> current .proj .datum .from .e_squared * GMT -> current .proj .datum .from .a * pow (cos_theta , 3.0 );
9294
+ out [GMT_X ] = d_atan2d (slam , clam );
9295
+ out [GMT_Y ] = d_atan2d (sphi , cphi );
9296
+ if (in_p [GMT_Z ] > 0.0 && out [GMT_Y ] < 0.0 ) out [GMT_Y ] = - out [GMT_Y ];
9297
+ if (in_p [GMT_Z ] < 0.0 && out [GMT_Y ] > 0.0 ) out [GMT_Y ] = - out [GMT_Y ];
9298
+ if (fabs (out [GMT_Y ]) < 89.999 ) {
9295
9299
sincosd (out [GMT_Y ], & sin_lat , & cos_lat );
9296
- N = GMT -> current .proj .datum .from .a / sqrt (1.0 - GMT -> current .proj .datum .from .e_squared * sin_lat * sin_lat );
9300
+ N = GMT -> current .proj .datum .from .a / sqrt (1.0 - GMT -> current .proj .datum .from .e_squared * sin_lat * sin_lat );
9297
9301
out [GMT_Z ] = (p / cos_lat ) - N ;
9298
9302
}
9299
- else { /* S or N pole, use sign of in_p[GMT_Z] to set latitude and height */
9300
- out [GMT_X ] = 0.0 ; /* Might as well pick0 since any longitude will work */
9301
- out [GMT_Y ] = (in_p [GMT_Z ] > 0.0 ) ? 90.0 : -90.0 ; /* EIther at north or south pole, check via Z coordinate */
9302
- out [GMT_Z ] = in_p [GMT_Z ] - copysign (GMT -> current .proj .datum .from .b , in_p [GMT_Z ]);
9303
+ else { /* very close to the poles */
9304
+ r = hypot (p , in_p [GMT_Z ]);
9305
+ out [GMT_Z ] = r - hypot (GMT -> current .proj .datum .from .b , p );
9303
9306
}
9304
9307
}
9305
9308
0 commit comments