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