00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include "GeographicLib/TransverseMercator.hpp"
00042 #include "GeographicLib/Constants.hpp"
00043 #include <limits>
00044
00045 namespace {
00046 char RCSID[] = "$Id: TransverseMercator.cpp 6568 2009-03-01 17:58:41Z ckarney $";
00047 char RCSID_H[] = TRANSVERSEMERCATOR_HPP;
00048 }
00049
00050 namespace GeographicLib {
00051
00052 using namespace std;
00053
00054 const double TransverseMercator::tol =
00055 0.1*sqrt(numeric_limits<double>::epsilon());
00056
00057 TransverseMercator::TransverseMercator(double a, double invf, double k0)
00058 throw()
00059 : _a(a)
00060 , _f(invf > 0 ? 1 / invf : 0)
00061 , _k0(k0)
00062 , _e2(_f * (2 - _f))
00063 , _e(sqrt(_e2))
00064 , _e2m(1 - _e2)
00065 , _n(_f / (2 - _f))
00066 {
00067 #if TM_TX_MAXPOW <= 4
00068 _b1 = 1/(1+_n)*(sq(_n)*(sq(_n)+16)+64)/64;
00069 _h[0] = _n*(_n*((555-4*_n)*_n-960)+720)/1440;
00070 _h[1] = sq(_n)*((96-437*_n)*_n+30)/1440;
00071 _h[2] = (119-148*_n)*sq(_n)*_n/3360;
00072 _h[3] = 4397*sq(sq(_n))/161280;
00073 _hp[0] = _n*(_n*(_n*(164*_n+225)-480)+360)/720;
00074 _hp[1] = sq(_n)*(_n*(557*_n-864)+390)/1440;
00075 _hp[2] = (427-1236*_n)*sq(_n)*_n/1680;
00076 _hp[3] = 49561*sq(sq(_n))/161280;
00077 #elif TM_TX_MAXPOW == 5
00078 _b1 = 1/(1+_n)*(sq(_n)*(sq(_n)+16)+64)/64;
00079 _h[0] = _n*(_n*(_n*((-3645*_n-64)*_n+8880)-15360)+11520)/23040;
00080 _h[1] = sq(_n)*(_n*(_n*(4416*_n-3059)+672)+210)/10080;
00081 _h[2] = sq(_n)*_n*((-627*_n-592)*_n+476)/13440;
00082 _h[3] = (4397-3520*_n)*sq(sq(_n))/161280;
00083 _h[4] = 4583*sq(sq(_n))*_n/161280;
00084 _hp[0] = _n*(_n*(_n*((328-635*_n)*_n+450)-960)+720)/1440;
00085 _hp[1] = sq(_n)*(_n*(_n*(4496*_n+3899)-6048)+2730)/10080;
00086 _hp[2] = sq(_n)*_n*(_n*(15061*_n-19776)+6832)/26880;
00087 _hp[3] = (49561-171840*_n)*sq(sq(_n))/161280;
00088 _hp[4] = 34729*sq(sq(_n))*_n/80640;
00089 #elif TM_TX_MAXPOW == 6
00090 _b1 = 1/(1+_n)*(sq(_n)*(sq(_n)*(sq(_n)+4)+64)+256)/256;
00091 _h[0] = _n*(_n*(_n*(_n*(_n*(384796*_n-382725)-6720)+932400)-1612800)+
00092 1209600)/2419200;
00093 _h[1] = sq(_n)*(_n*(_n*((1695744-1118711*_n)*_n-1174656)+258048)+80640)/
00094 3870720;
00095 _h[2] = sq(_n)*_n*(_n*(_n*(22276*_n-16929)-15984)+12852)/362880;
00096 _h[3] = sq(sq(_n))*((-830251*_n-158400)*_n+197865)/7257600;
00097 _h[4] = (453717-435388*_n)*sq(sq(_n))*_n/15966720;
00098 _h[5] = 20648693*sq(sq(_n))*sq(_n)/638668800;
00099 _hp[0] = _n*(_n*(_n*(_n*(_n*(31564*_n-66675)+34440)+47250)-100800)+75600)/
00100 151200;
00101 _hp[1] = sq(_n)*(_n*(_n*((863232-1983433*_n)*_n+748608)-1161216)+524160)/
00102 1935360;
00103 _hp[2] = sq(_n)*_n*(_n*(_n*(670412*_n+406647)-533952)+184464)/725760;
00104 _hp[3] = sq(sq(_n))*(_n*(6601661*_n-7732800)+2230245)/7257600;
00105 _hp[4] = (3438171-13675556*_n)*sq(sq(_n))*_n/7983360;
00106 _hp[5] = 212378941*sq(sq(_n))*sq(_n)/319334400;
00107 #elif TM_TX_MAXPOW == 7
00108 _b1 = 1/(1+_n)*(sq(_n)*(sq(_n)*(sq(_n)+4)+64)+256)/256;
00109 _h[0] = _n*(_n*(_n*(_n*(_n*((6156736-5406467*_n)*_n-6123600)-107520)+
00110 14918400)-25804800)+19353600)/38707200;
00111 _h[1] = sq(_n)*(_n*(_n*(_n*(_n*(829456*_n-5593555)+8478720)-5873280)+
00112 1290240)+403200)/19353600;
00113 _h[2] = sq(_n)*_n*(_n*(_n*(_n*(9261899*_n+3564160)-2708640)-2557440)+
00114 2056320)/58060800;
00115 _h[3] = sq(sq(_n))*(_n*(_n*(14928352*_n-9132761)-1742400)+2176515)/
00116 79833600;
00117 _h[4] = sq(sq(_n))*_n*((-8005831*_n-1741552)*_n+1814868)/63866880;
00118 _h[5] = (268433009-261810608*_n)*sq(sq(_n))*sq(_n)/8302694400.;
00119 _h[6] = 219941297*sq(sq(_n))*sq(_n)*_n/5535129600.;
00120 _hp[0] = _n*(_n*(_n*(_n*(_n*(_n*(1804025*_n+2020096)-4267200)+2204160)+
00121 3024000)-6451200)+4838400)/9676800;
00122 _hp[1] = sq(_n)*(_n*(_n*(_n*(_n*(4626384*_n-9917165)+4316160)+3743040)-
00123 5806080)+2620800)/9676800;
00124 _hp[2] = sq(_n)*_n*(_n*(_n*((26816480-67102379*_n)*_n+16265880)-21358080)+
00125 7378560)/29030400;
00126 _hp[3] = sq(sq(_n))*(_n*(_n*(155912000*_n+72618271)-85060800)+24532695)/
00127 79833600;
00128 _hp[4] = sq(sq(_n))*_n*(_n*(102508609*_n-109404448)+27505368)/63866880;
00129 _hp[5] = (2760926233.-12282192400.*_n)*sq(sq(_n))*sq(_n)/4151347200.;
00130 _hp[6] = 1522256789.*sq(sq(_n))*sq(_n)*_n/1383782400.;
00131 #elif TM_TX_MAXPOW >= 8
00132 _b1 = 1/(1+_n)*(sq(_n)*(sq(_n)*(sq(_n)*(25*sq(_n)+64)+256)+4096)+16384)/
00133 16384;
00134 _h[0] = _n*(_n*(_n*(_n*(_n*(_n*(_n*(31777436*_n-37845269)+43097152)-
00135 42865200)-752640)+104428800)-180633600)+
00136 135475200)/270950400;
00137 _h[1] = sq(_n)*(_n*(_n*(_n*(_n*(_n*(24749483*_n+14930208)-100683990)+
00138 152616960)-105719040)+23224320)+7257600)/
00139 348364800;
00140 _h[2] = sq(_n)*_n*(_n*(_n*(_n*((101880889-232468668*_n)*_n+39205760)-
00141 29795040)-28131840)+22619520)/638668800;
00142 _h[3] = sq(sq(_n))*(_n*(_n*(_n*(324154477*_n+1433121792.)-876745056)-
00143 167270400)+208945440)/7664025600.;
00144 _h[4] = sq(sq(_n))*_n*(_n*(_n*(457888660*_n-312227409)-67920528)+
00145 70779852)/2490808320.;
00146 _h[5] = sq(sq(_n))*sq(_n)*((-19841813847.*_n-3665348512.)*_n+3758062126.)/
00147 116237721600.;
00148 _h[6] = (1979471673.-1989295244.*_n)*sq(sq(_n))*sq(_n)*_n/49816166400.;
00149 _h[7] = 191773887257.*sq(sq(sq(_n)))/3719607091200.;
00150 _hp[0] = _n*(_n*(_n*(_n*(_n*(_n*((37884525-75900428*_n)*_n+42422016)-
00151 89611200)+46287360)+63504000)-135475200)+
00152 101606400)/203212800;
00153 _hp[1] = sq(_n)*(_n*(_n*(_n*(_n*(_n*(148003883*_n+83274912)-178508970)+
00154 77690880)+67374720)-104509440)+47174400)/
00155 174182400;
00156 _hp[2] = sq(_n)*_n*(_n*(_n*(_n*(_n*(318729724*_n-738126169)+294981280)+
00157 178924680)-234938880)+81164160)/319334400;
00158 _hp[3] = sq(sq(_n))*(_n*(_n*((14967552000.-40176129013.*_n)*_n+
00159 6971354016.)-8165836800.)+2355138720.)/
00160 7664025600.;
00161 _hp[4] = sq(sq(_n))*_n*(_n*(_n*(10421654396.*_n+3997835751.)-4266773472.)+
00162 1072709352.)/2490808320.;
00163 _hp[5] = sq(sq(_n))*sq(_n)*(_n*(175214326799.*_n-171950693600.)+
00164 38652967262.)/58118860800.;
00165 _hp[6] = (13700311101.-67039739596.*_n)*sq(sq(_n))*sq(_n)*_n/12454041600.;
00166 _hp[7] = 1424729850961.*sq(sq(sq(_n)))/743921418240.;
00167 #endif
00168
00169
00170 _a1 = _b1 * _a;
00171 }
00172
00173 const TransverseMercator
00174 TransverseMercator::UTM(Constants::WGS84_a(), Constants::WGS84_invf(),
00175 Constants::UTM_k0());
00176
00177 void TransverseMercator::Forward(double lon0, double lat, double lon,
00178 double& x, double& y,
00179 double& gamma, double& k) const throw() {
00180
00181 if (lon - lon0 > 180)
00182 lon -= lon0 - 360;
00183 else if (lon - lon0 <= -180)
00184 lon -= lon0 + 360;
00185 else
00186 lon -= lon0;
00187
00188
00189 int
00190 latsign = lat < 0 ? -1 : 1,
00191 lonsign = lon < 0 ? -1 : 1;
00192 lon *= lonsign;
00193 lat *= latsign;
00194 bool backside = lon > 90;
00195 if (backside) {
00196 if (lat == 0)
00197 latsign = -1;
00198 lon = 180 - lon;
00199 }
00200 double
00201 phi = lat * Constants::degree(),
00202 lam = lon * Constants::degree();
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 double etap, xip;
00224 if (lat < 90) {
00225 double
00226 qp = asinh(tan(phi)),
00227 qpp = atanh(_e * sin(phi)),
00228 q = qp - _e * qpp;
00229 xip = atan2(sinh(q), cos(lam));
00230 etap = atanh(sin(lam) / cosh(q));
00231
00232
00233 gamma = atan(tan(lam) * tanh(q));
00234
00235
00236
00237 k = sqrt(_e2m + _e2 * sq(cos(phi))) * cosh(qp) / hypot(sinh(q), cos(lam));
00238 } else {
00239 xip = Constants::pi()/2;
00240 etap = 0;
00241 gamma = lam;
00242
00243 k = sqrt( pow(1 + _e, 1 + _e) * pow(1 - _e, 1 - _e) );
00244 }
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 double
00299 c0 = cos(2 * xip), ch0 = cosh(2 * etap),
00300 s0 = sin(2 * xip), sh0 = sinh(2 * etap),
00301 ar = 2 * c0 * ch0, ai = -2 * s0 * sh0;
00302 double
00303 xi0 = _hp[maxpow - 1], eta0 = 0,
00304 xi1 = 0, eta1 = 0,
00305 xi2, eta2;
00306 double
00307 yr0 = 2 * maxpow * _hp[maxpow - 1], yi0 = 0,
00308 yr1 = 0, yi1 = 0,
00309 yr2, yi2;
00310 for (int j = maxpow; --j;) {
00311 xi2 = xi1; eta2 = eta1; yr2 = yr1; yi2 = yi1;
00312 xi1 = xi0; eta1 = eta0; yr1 = yr0; yi1 = yi0;
00313 xi0 = ar * xi1 - ai * eta1 - xi2 + _hp[j - 1];
00314 eta0 = ai * xi1 + ar * eta1 - eta2;
00315 yr0 = ar * yr1 - ai * yi1 - yr2 + 2 * j * _hp[j - 1];
00316 yi0 = ai * yr1 + ar * yi1 - yi2;
00317 }
00318 ar /= 2; ai /= 2;
00319 yr2 = 1 - yr1 + ar * yr0 - ai * yi0;
00320 yi2 = - yi1 + ai * yr0 + ar * yi0;
00321 ar = s0 * ch0; ai = c0 * sh0;
00322 double
00323 xi = xip + ar * xi0 - ai * eta0,
00324 eta = etap + ai * xi0 + ar * eta0;
00325
00326
00327 gamma -= atan2(yi2, yr2);
00328 k *= _b1 * hypot(yr2, yi2);
00329 gamma /= Constants::degree();
00330 y = _a1 * _k0 * (backside ? Constants::pi() - xi : xi) * latsign;
00331 x = _a1 * _k0 * eta * lonsign;
00332 if (backside)
00333 gamma = 180 - gamma;
00334 gamma *= latsign * lonsign;
00335 k *= _k0;
00336 }
00337
00338 void TransverseMercator::Reverse(double lon0, double x, double y,
00339 double& lat, double& lon,
00340 double& gamma, double& k) const throw() {
00341
00342
00343
00344 double
00345 xi = y / (_a1 * _k0),
00346 eta = x / (_a1 * _k0);
00347
00348 int
00349 xisign = xi < 0 ? -1 : 1,
00350 etasign = eta < 0 ? -1 : 1;
00351 xi *= xisign;
00352 eta *= etasign;
00353 bool backside = xi > Constants::pi()/2;
00354 if (backside)
00355 xi = Constants::pi() - xi;
00356 double
00357 c0 = cos(2 * xi), ch0 = cosh(2 * eta),
00358 s0 = sin(2 * xi), sh0 = sinh(2 * eta),
00359 ar = 2 * c0 * ch0, ai = -2 * s0 * sh0;
00360 double
00361 xip0 = -_h[maxpow - 1], etap0 = 0,
00362 xip1 = 0, etap1 = 0,
00363 xip2, etap2;
00364 double
00365 yr0 = - 2 * maxpow * _h[maxpow - 1], yi0 = 0,
00366 yr1 = 0, yi1 = 0,
00367 yr2, yi2;
00368 for (int j = maxpow; --j;) {
00369 xip2 = xip1; etap2 = etap1; yr2 = yr1; yi2 = yi1;
00370 xip1 = xip0; etap1 = etap0; yr1 = yr0; yi1 = yi0;
00371 xip0 = ar * xip1 - ai * etap1 - xip2 - _h[j - 1];
00372 etap0 = ai * xip1 + ar * etap1 - etap2;
00373 yr0 = ar * yr1 - ai * yi1 - yr2 - 2 * j * _h[j - 1];
00374 yi0 = ai * yr1 + ar * yi1 - yi2;
00375 }
00376 ar /= 2; ai /= 2;
00377 yr2 = 1 - yr1 + ar * yr0 - ai * yi0;
00378 yi2 = - yi1 + ai * yr0 + ar * yi0;
00379 ar = s0 * ch0; ai = c0 * sh0;
00380 double
00381 xip = xi + ar * xip0 - ai * etap0,
00382 etap = eta + ai * xip0 + ar * etap0;
00383
00384 gamma = atan2(yi2, yr2);
00385 k = _b1 / hypot(yr2, yi2);
00386
00387
00388
00389
00390
00391
00392
00393 double lam, phi;
00394 double
00395 s = sinh(etap),
00396 c = cos(xip),
00397 r = hypot(s, c);
00398 if (r > 0) {
00399 lam = atan2(s, c);
00400
00401
00402
00403 double
00404 q = asinh(sin(xip)/r),
00405 qp = q;
00406
00407 for (int i = 0; i < numit; ++i) {
00408 double
00409 t = tanh(qp),
00410 dqp = -(qp - _e * atanh(_e * t) - q) * (1 - _e2 * sq(t)) / _e2m;
00411 qp += dqp;
00412 if (abs(dqp) < tol)
00413 break;
00414 }
00415 phi = atan(sinh(qp));
00416 gamma += atan(tan(xip) * tanh(etap));
00417
00418 k *= sqrt(_e2m + _e2 * sq(cos(phi))) * cosh(qp) * r;
00419 } else {
00420 phi = Constants::pi()/2;
00421 lam = 0;
00422 k *= sqrt( pow(1 + _e, 1 + _e) * pow(1 - _e, 1 - _e) );
00423 }
00424 lat = phi / Constants::degree() * xisign;
00425 lon = lam / Constants::degree();
00426 if (backside)
00427 lon = 180 - lon;
00428 lon *= etasign;
00429
00430 if (lon + lon0 >= 180)
00431 lon += lon0 - 360;
00432 else if (lon + lon0 < -180)
00433 lon += lon0 + 360;
00434 else
00435 lon += lon0;
00436 gamma /= Constants::degree();
00437 if (backside)
00438 gamma = 180 - gamma;
00439 gamma *= xisign * etasign;
00440 k *= _k0;
00441 }
00442
00443 }