50 TransverseMercatorExact::TransverseMercatorExact(real a, real f, real k0,
52 : tol_(numeric_limits<real>::epsilon())
53 , tol2_(real(0.1) * tol_)
54 , taytol_(pow(tol_, real(0.6)))
65 if (!(isfinite(_a) && _a > 0))
71 if (!(isfinite(_k0) && _k0 > 0))
91 overflow = 1 /
Math::sq(numeric_limits<real>::epsilon());
95 t1 = (d1 != 0 ? snu * dnv / d1 : (signbit(snu) ? -overflow : overflow)),
96 t2 = (d2 != 0 ? sinh( _e * asinh(_e * snu / d2) ) :
97 (signbit(snu) ? -overflow : overflow));
100 taup = t1 * hypot(
real(1), t2) - t2 * hypot(
real(1), t1);
101 lam = (d1 != 0 && d2 != 0) ?
102 atan2(dnu * snv, cnu * cnv) - _e * atan2(_e * cnu * snv, dnu * cnv) :
106 void TransverseMercatorExact::dwdzeta(
real ,
119 bool TransverseMercatorExact::zetainv0(
real psi,
real lam,
123 lam > (1 - 2 * _e) *
Math::pi()/2 &&
124 psi < lam - (1 - _e) *
Math::pi()/2) {
137 u = asinh(sin(lamx) / hypot(cos(lamx), sinh(psix))) *
139 v = atan2(cos(lamx), sinh(psix)) * (1 + _mu/2);
142 }
else if (psi < _e *
Math::pi()/2 &&
143 lam > (1 - 2 * _e) *
Math::pi()/2) {
156 dlam = lam - (1 - _e) *
Math::pi()/2,
157 rad = hypot(psi, dlam),
163 ang = atan2(dlam-psi, psi+dlam) -
real(0.75) *
Math::pi();
165 retval = rad < _e * taytol_;
166 rad = cbrt(3 / (_mv * _e) * rad);
169 v = rad * sin(ang) + _eEv.
K();
174 v = asinh(sin(lam) / hypot(cos(lam), sinh(psi)));
175 u = atan2(sinh(psi), cos(lam));
184 void TransverseMercatorExact::zetainv(
real taup,
real lam,
188 scal = 1/hypot(
real(1), taup);
189 if (zetainv0(psi, lam, u, v))
193 for (
int i = 0, trip = 0;
196 (
"Convergence failure in TransverseMercatorExact");
198 real snu, cnu, dnu, snv, cnv, dnv;
199 _eEu.
am(u, snu, cnu, dnu);
200 _eEv.
am(v, snv, cnv, dnv);
201 real tau1, lam1, du1, dv1;
202 zeta(u, snu, cnu, dnu, v, snv, cnv, dnv, tau1, lam1);
203 dwdzeta(u, snu, cnu, dnu, v, snv, cnv, dnv, du1, dv1);
208 delu = tau1 * du1 - lam1 * dv1,
209 delv = tau1 * dv1 + lam1 * du1;
215 if (!(delw2 >= stol2))
226 xi = _eEu.
E(snu, cnu, dnu) - _mu * snu * cnu * dnu / d;
227 eta = v - _eEv.
E(snv, cnv, dnv) + _mv * snv * cnv * dnv / d;
230 void TransverseMercatorExact::dwdsigma(
real ,
239 dnr = dnu * cnv * dnv,
240 dni = - _mu * snu * cnu * snv;
242 dv = 2 * dnr * dni / d;
246 bool TransverseMercatorExact::sigmainv0(
real xi,
real eta,
249 if (eta >
real(1.25) * _eEv.
KE() ||
250 (xi < -
real(0.25) * _eEu.
E() && xi < eta - _eEv.
KE())) {
261 }
else if ((eta >
real(0.75) * _eEv.
KE() && xi <
real(0.25) * _eEu.
E())
262 || eta > _eEv.
KE()) {
276 deta = eta - _eEv.
KE(),
277 rad = hypot(xi, deta),
280 ang = atan2(deta-xi, xi+deta) -
real(0.75) *
Math::pi();
282 retval = rad < 2 * taytol_;
283 rad = cbrt(3 / _mv * rad);
286 v = rad * sin(ang) + _eEv.
K();
289 u = xi * _eEu.
K()/_eEu.
E();
290 v = eta * _eEu.
K()/_eEu.
E();
296 void TransverseMercatorExact::sigmainv(
real xi,
real eta,
298 if (sigmainv0(xi, eta, u, v))
301 for (
int i = 0, trip = 0;
304 (
"Convergence failure in TransverseMercatorExact");
306 real snu, cnu, dnu, snv, cnv, dnv;
307 _eEu.
am(u, snu, cnu, dnu);
308 _eEv.
am(v, snv, cnv, dnv);
309 real xi1, eta1, du1, dv1;
310 sigma(u, snu, cnu, dnu, v, snv, cnv, dnv, xi1, eta1);
311 dwdsigma(u, snu, cnu, dnu, v, snv, cnv, dnv, du1, dv1);
315 delu = xi1 * du1 - eta1 * dv1,
316 delv = xi1 * dv1 + eta1 * du1;
322 if (!(delw2 >= tol2_))
327 void TransverseMercatorExact::Scale(
real tau,
real ,
334 gamma = atan2(_mv * snu * snv * cnv, cnu * dnu * dnv);
348 k = sqrt(_mv + _mu / sec2) * sqrt(sec2) *
355 real& gamma, real& k)
const {
360 latsign = (!_extendp && signbit(lat)) ? -1 : 1,
361 lonsign = (!_extendp && signbit(lon)) ? -1 : 1;
364 bool backside = !_extendp && lon >
Math::qd;
379 }
else if (lat == 0 && lon ==
Math::qd * (1 - _e)) {
386 real snu, cnu, dnu, snv, cnv, dnv;
387 _eEu.
am(u, snu, cnu, dnu);
388 _eEv.
am(v, snv, cnv, dnv);
391 sigma(u, snu, cnu, dnu, v, snv, cnv, dnv, xi, eta);
393 xi = 2 * _eEu.
E() - xi;
394 y = xi * _a * _k0 * latsign;
395 x = eta * _a * _k0 * lonsign;
402 zeta(u, snu, cnu, dnu, v, snv, cnv, dnv, tau, lam);
404 Scale(tau, lam, snu, cnu, dnu, snv, cnv, dnv, gamma, k);
409 gamma *= latsign * lonsign;
414 real& lat, real& lon,
415 real& gamma, real& k)
const {
419 eta = x / (_a * _k0);
422 xisign = (!_extendp && signbit(xi)) ? -1 : 1,
423 etasign = (!_extendp && signbit(eta)) ? -1 : 1;
426 bool backside = !_extendp && xi > _eEu.
E();
428 xi = 2 * _eEu.
E()- xi;
432 if (xi == 0 && eta == _eEv.
KE()) {
436 sigmainv(xi, eta, u, v);
438 real snu, cnu, dnu, snv, cnv, dnv;
439 _eEu.
am(u, snu, cnu, dnu);
440 _eEv.
am(v, snv, cnv, dnv);
442 if (v != 0 || u != _eEu.
K()) {
443 zeta(u, snu, cnu, dnu, v, snv, cnv, dnv, tau, lam);
448 Scale(tau, lam, snu, cnu, dnu, snv, cnv, dnv, gamma, k);
452 lon = lam = gamma = 0;
463 gamma *= xisign * etasign;
GeographicLib::Math::real real
#define GEOGRAPHICLIB_PANIC(msg)
Header for GeographicLib::TransverseMercatorExact class.
Math::real am(real x) const
Exception handling for GeographicLib.
static constexpr int qd
degrees per quarter turn
static T tauf(T taup, T es)
static T AngNormalize(T x)
static T taupf(T tau, T es)
static T AngDiff(T x, T y, T &e)
static constexpr int hd
degrees per half turn
An exact implementation of the transverse Mercator projection.
void Forward(real lon0, real lat, real lon, real &x, real &y, real &gamma, real &k) const
static const TransverseMercatorExact & UTM()
void Reverse(real lon0, real x, real y, real &lat, real &lon, real &gamma, real &k) const
Namespace for GeographicLib.