42# pragma warning (disable: 5055)
50 bool exact,
bool extendp)
56 , _es((_f < 0 ? -1 : 1) * sqrt(fabs(_e2)))
60 , _c( sqrt(_e2m) * exp(
Math::eatanhe(real(1), _es)) )
66 if (!(isfinite(_a) && _a > 0))
68 if (!(isfinite(_f) && _f < 1))
70 if (!(isfinite(_k0) && _k0 > 0))
73 throw GeographicErr(
"TransverseMercator extendp not allowed if !exact");
76#if GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER/2 == 2
77 static const real b1coeff[] = {
81#elif GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER/2 == 3
82 static const real b1coeff[] = {
86#elif GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER/2 == 4
87 static const real b1coeff[] = {
89 25, 64, 256, 4096, 16384, 16384,
92#error "Bad value for GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER"
95#if GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER == 4
96 static const real alpcoeff[] = {
98 164, 225, -480, 360, 720,
100 557, -864, 390, 1440,
106#elif GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER == 5
107 static const real alpcoeff[] = {
109 -635, 328, 450, -960, 720, 1440,
111 4496, 3899, -6048, 2730, 10080,
113 15061, -19776, 6832, 26880,
115 -171840, 49561, 161280,
119#elif GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER == 6
120 static const real alpcoeff[] = {
122 31564, -66675, 34440, 47250, -100800, 75600, 151200,
124 -1983433, 863232, 748608, -1161216, 524160, 1935360,
126 670412, 406647, -533952, 184464, 725760,
128 6601661, -7732800, 2230245, 7257600,
130 -13675556, 3438171, 7983360,
132 212378941, 319334400,
134#elif GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER == 7
135 static const real alpcoeff[] = {
137 1804025, 2020096, -4267200, 2204160, 3024000, -6451200, 4838400, 9676800,
139 4626384, -9917165, 4316160, 3743040, -5806080, 2620800, 9676800,
141 -67102379, 26816480, 16265880, -21358080, 7378560, 29030400,
143 155912000, 72618271, -85060800, 24532695, 79833600,
145 102508609, -109404448, 27505368, 63866880,
147 -12282192400LL, 2760926233LL, 4151347200LL,
149 1522256789, 1383782400,
151#elif GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER == 8
152 static const real alpcoeff[] = {
154 -75900428, 37884525, 42422016, -89611200, 46287360, 63504000, -135475200,
155 101606400, 203212800,
157 148003883, 83274912, -178508970, 77690880, 67374720, -104509440,
160 318729724, -738126169, 294981280, 178924680, -234938880, 81164160,
163 -40176129013LL, 14967552000LL, 6971354016LL, -8165836800LL, 2355138720LL,
166 10421654396LL, 3997835751LL, -4266773472LL, 1072709352, 2490808320LL,
168 175214326799LL, -171950693600LL, 38652967262LL, 58118860800LL,
170 -67039739596LL, 13700311101LL, 12454041600LL,
172 1424729850961LL, 743921418240LL,
175#error "Bad value for GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER"
178#if GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER == 4
179 static const real betcoeff[] = {
181 -4, 555, -960, 720, 1440,
189#elif GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER == 5
190 static const real betcoeff[] = {
192 -3645, -64, 8880, -15360, 11520, 23040,
194 4416, -3059, 672, 210, 10080,
196 -627, -592, 476, 13440,
202#elif GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER == 6
203 static const real betcoeff[] = {
205 384796, -382725, -6720, 932400, -1612800, 1209600, 2419200,
207 -1118711, 1695744, -1174656, 258048, 80640, 3870720,
209 22276, -16929, -15984, 12852, 362880,
211 -830251, -158400, 197865, 7257600,
213 -435388, 453717, 15966720,
217#elif GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER == 7
218 static const real betcoeff[] = {
220 -5406467, 6156736, -6123600, -107520, 14918400, -25804800, 19353600,
223 829456, -5593555, 8478720, -5873280, 1290240, 403200, 19353600,
225 9261899, 3564160, -2708640, -2557440, 2056320, 58060800,
227 14928352, -9132761, -1742400, 2176515, 79833600,
229 -8005831, -1741552, 1814868, 63866880,
231 -261810608, 268433009, 8302694400LL,
233 219941297, 5535129600LL,
235#elif GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER == 8
236 static const real betcoeff[] = {
238 31777436, -37845269, 43097152, -42865200, -752640, 104428800, -180633600,
239 135475200, 270950400,
241 24749483, 14930208, -100683990, 152616960, -105719040, 23224320, 7257600,
244 -232468668, 101880889, 39205760, -29795040, -28131840, 22619520,
247 324154477, 1433121792, -876745056, -167270400, 208945440, 7664025600LL,
249 457888660, -312227409, -67920528, 70779852, 2490808320LL,
251 -19841813847LL, -3665348512LL, 3758062126LL, 116237721600LL,
253 -1989295244, 1979471673, 49816166400LL,
255 191773887257LL, 3719607091200LL,
258#error "Bad value for GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER"
261 static_assert(
sizeof(b1coeff) /
sizeof(real) == maxpow_/2 + 2,
262 "Coefficient array size mismatch for b1");
263 static_assert(
sizeof(alpcoeff) /
sizeof(real) ==
264 (maxpow_ * (maxpow_ + 3))/2,
265 "Coefficient array size mismatch for alp");
266 static_assert(
sizeof(betcoeff) /
sizeof(real) ==
267 (maxpow_ * (maxpow_ + 3))/2,
268 "Coefficient array size mismatch for bet");
276 for (
int l = 1; l <= maxpow_; ++l) {
278 _alp[l] = d *
Math::polyval(m, alpcoeff + o, _n) / alpcoeff[o + m + 1];
279 _bet[l] = d *
Math::polyval(m, betcoeff + o, _n) / betcoeff[o + m + 1];
362 real& gamma, real& k)
const {
364 return _tmexact.
Forward(lon0, lat, lon, x, y, gamma, k);
369 latsign = signbit(lat) ? -1 : 1,
370 lonsign = signbit(lon) ? -1 : 1;
379 real sphi, cphi, slam, clam;
404 xip = atan2(taup, clam);
407 etap = asinh(slam / hypot(taup, clam));
412 gamma =
Math::atan2d(slam * taup, clam * hypot(real(1), taup));
420 k = sqrt(_e2m + _e2 *
Math::sq(cphi)) * hypot(real(1), tau)
494 c0 = cos(2 * xip), ch0 = cosh(2 * etap),
495 s0 = sin(2 * xip), sh0 = sinh(2 * etap);
496 complex<real> a(2 * c0 * ch0, -2 * s0 * sh0);
499 y0(n & 1 ? _alp[n] : 0), y1,
500 z0(n & 1 ? 2*n * _alp[n] : 0), z1;
503 y1 = a * y0 - y1 + _alp[n];
504 z1 = a * z0 - z1 + 2*n * _alp[n];
506 y0 = a * y1 - y0 + _alp[n];
507 z0 = a * z1 - z0 + 2*n * _alp[n];
511 z1 = real(1) - z1 + a * z0;
512 a = complex<real>(s0 * ch0, c0 * sh0);
513 y1 = complex<real>(xip, etap) + a * y0;
518 real xi = y1.real(), eta = y1.imag();
519 y = _a1 * _k0 * (backside ?
Math::pi() - xi : xi) * latsign;
520 x = _a1 * _k0 * eta * lonsign;
523 gamma *= latsign * lonsign;
529 real& lat, real& lon,
530 real& gamma, real& k)
const {
532 return _tmexact.
Reverse(lon0, x, y, lat, lon, gamma, k);
537 xi = y / (_a1 * _k0),
538 eta = x / (_a1 * _k0);
541 xisign = signbit(xi) ? -1 : 1,
542 etasign = signbit(eta) ? -1 : 1;
549 c0 = cos(2 * xi), ch0 = cosh(2 * eta),
550 s0 = sin(2 * xi), sh0 = sinh(2 * eta);
551 complex<real> a(2 * c0 * ch0, -2 * s0 * sh0);
554 y0(n & 1 ? -_bet[n] : 0), y1,
555 z0(n & 1 ? -2*n * _bet[n] : 0), z1;
558 y1 = a * y0 - y1 - _bet[n];
559 z1 = a * z0 - z1 - 2*n * _bet[n];
561 y0 = a * y1 - y0 - _bet[n];
562 z0 = a * z1 - z0 - 2*n * _bet[n];
566 z1 = real(1) - z1 + a * z0;
567 a = complex<real>(s0 * ch0, c0 * sh0);
568 y1 = complex<real>(xi, eta) + a * y0;
578 xip = y1.real(), etap = y1.imag(),
580 c = fmax(real(0), cos(xip)),
591 k *= sqrt(_e2m + _e2 / (1 +
Math::sq(tau))) *
592 hypot(real(1), tau) * r;
605 gamma *= xisign * etasign;
Header for GeographicLib::TransverseMercator class.
Exception handling for GeographicLib.
Mathematical functions needed by GeographicLib.
static void sincosd(T x, T &sinx, T &cosx)
static T atan2d(T y, T x)
static T tauf(T taup, T es)
static T AngNormalize(T x)
static T taupf(T tau, T es)
static T polyval(int N, const T p[], T x)
static T AngDiff(T x, T y, T &e)
@ hd
degrees per half turn
@ qd
degrees per quarter 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
void Reverse(real lon0, real x, real y, real &lat, real &lon, real &gamma, real &k) const
Transverse Mercator projection.
TransverseMercator(real a, real f, real k0, bool exact=false, bool extendp=false)
void Reverse(real lon0, real x, real y, real &lat, real &lon, real &gamma, real &k) const
static const TransverseMercator & UTM()
void Forward(real lon0, real lat, real lon, real &x, real &y, real &gamma, real &k) const
Namespace for GeographicLib.