13 namespace GeographicLib {
20 pow(
real(0.5), numeric_limits<real>::digits - 25);
23 pow(
real(0.5), numeric_limits<real>::digits - 7);
24 const string MGRS::hemispheres_ =
"SN";
25 const string MGRS::utmcols_[3] = {
"ABCDEFGH",
"JKLMNPQR",
"STUVWXYZ" };
26 const string MGRS::utmrow_ =
"ABCDEFGHJKLMNPQRSTUV";
27 const string MGRS::upscols_[4] =
28 {
"JKLPQRSTUXYZ",
"ABCFGHJKLPQR",
"RSTUXYZ",
"ABCFGHJ" };
29 const string MGRS::upsrows_[2] =
30 {
"ABCDEFGHJKLMNPQRSTUVWXYZ",
"ABCDEFGHJKLMNP" };
31 const string MGRS::latband_ =
"CDEFGHJKLMNPQRSTUVWX";
32 const string MGRS::upsband_ =
"ABYZ";
33 const string MGRS::digits_ =
"0123456789";
35 const int MGRS::mineasting_[4] =
36 { minupsSind_, minupsNind_, minutmcol_, minutmcol_ };
37 const int MGRS::maxeasting_[4] =
38 { maxupsSind_, maxupsNind_, maxutmcol_, maxutmcol_ };
39 const int MGRS::minnorthing_[4] =
40 { minupsSind_, minupsNind_,
41 minutmSrow_, minutmSrow_ - (maxutmSrow_ - minutmNrow_) };
42 const int MGRS::maxnorthing_[4] =
43 { maxupsSind_, maxupsNind_,
44 maxutmNrow_ + (maxutmSrow_ - minutmNrow_), maxutmNrow_ };
47 int prec, std::string& mgrs) {
54 bool utmp = zone != 0;
55 CheckCoords(utmp, northp, x, y);
58 if (!(prec >= 0 && prec <= maxprec_))
64 char mgrs1[2 + 3 + 2 * maxprec_];
68 mlen = z + 3 + 2 * prec;
70 mgrs1[0] = digits_[ zone / base_ ];
71 mgrs1[1] = digits_[ zone % base_ ];
76 xh = int(floor(x)) / tile_,
77 yh = int(floor(y)) / tile_;
84 iband = abs(lat) > angeps_ ? LatitudeBand(lat) : (northp ? 0 : -1),
85 icol = xh - minutmcol_,
86 irow = UTMRow(iband, icol, yh % utmrowperiod_);
87 if (irow != yh - (northp ? minutmNrow_ : maxutmSrow_))
89 +
" is inconsistent with UTM coordinates");
90 mgrs1[z++] = latband_[10 + iband];
91 mgrs1[z++] = utmcols_[zone1 % 3][icol];
92 mgrs1[z++] = utmrow_[(yh + (zone1 & 1 ? utmevenrowshift_ : 0))
95 bool eastp = xh >= upseasting_;
96 int iband = (northp ? 2 : 0) + (eastp ? 1 : 0);
97 mgrs1[z++] = upsband_[iband];
98 mgrs1[z++] = upscols_[iband][xh - (eastp ? upseasting_ :
99 (northp ? minupsNind_ : minupsSind_))];
100 mgrs1[z++] = upsrows_[northp][yh - (northp ? minupsNind_ : minupsSind_)];
102 real mult = pow(
real(base_), max(tilelevel_ - prec, 0));
104 ix = int(floor(xf / mult)),
105 iy = int(floor(yf / mult));
106 for (
int c = min(prec,
int(tilelevel_)); c--;) {
107 mgrs1[z + c] = digits_[ ix % base_ ];
109 mgrs1[z + c + prec] = digits_[ iy % base_ ];
112 if (prec > tilelevel_) {
113 xf -= floor(xf / mult);
114 yf -= floor(yf / mult);
115 mult = pow(
real(base_), prec - tilelevel_);
116 ix = int(floor(xf * mult));
117 iy = int(floor(yf * mult));
118 for (
int c = prec - tilelevel_; c--;) {
119 mgrs1[z + c + tilelevel_] = digits_[ ix % base_ ];
121 mgrs1[z + c + tilelevel_ + prec] = digits_[ iy % base_ ];
126 copy(mgrs1, mgrs1 + mlen, mgrs.begin());
130 int prec, std::string& mgrs) {
134 real ys = northp ? y : y - utmNshift_;
148 latp =
real(0.901) * ys + (ys > 0 ? 1 : -1) *
real(0.135),
151 late =
real(0.902) * ys * (1 -
real(1.85e-6) * ys * ys);
152 if (LatitudeBand(latp) == LatitudeBand(late))
161 Forward(zone, northp, x, y, lat, prec, mgrs);
165 int& zone,
bool& northp, real& x, real& y,
166 int& prec,
bool centerp) {
169 len = int(mgrs.size());
171 toupper(mgrs[0]) ==
'I' &&
172 toupper(mgrs[1]) ==
'N' &&
173 toupper(mgrs[2]) ==
'V') {
176 x = y = Math::NaN<real>();
185 zone1 = 10 * zone1 + i;
192 + mgrs.substr(0, p));
196 int zonem1 = zone1 - 1;
197 const string& band = utmp ? latband_ : upsband_;
201 + (utmp ?
"UTM" :
"UPS") +
" set " + band);
202 bool northp1 = iband >= (utmp ? 10 : 2);
203 const string& col = utmp ? utmcols_[zonem1 % 3] : upscols_[iband];
204 const string& row = utmp ? utmrow_ : upsrows_[northp1];
209 + (utmp ?
"zone " + mgrs.substr(0, p-2) :
220 irow = (irow + utmrowperiod_ - utmevenrowshift_) % utmrowperiod_;
222 irow = UTMRow(iband, icol, irow);
223 if (irow == maxutmSrow_)
225 +
" not in zone/band " + mgrs.substr(0, p-2));
227 irow = northp1 ? irow : irow + 100;
228 icol = icol + minutmcol_;
230 bool eastp = iband & 1;
231 icol += eastp ? upseasting_ : (northp1 ? minupsNind_ : minupsSind_);
232 irow += northp1 ? minupsNind_ : minupsSind_;
234 int prec1 = (len - p)/2;
239 for (
int i = 0; i < prec1; ++i) {
244 if (ix < 0 || iy < 0)
245 throw GeographicErr(
"Encountered a non-digit in " + mgrs.substr(p));
251 throw GeographicErr(
"Encountered a non-digit in " + mgrs.substr(p));
256 if (prec1 > maxprec_)
271 void MGRS::CheckCoords(
bool utmp,
bool& northp,
real& x,
real& y) {
278 ix = int(floor(x / tile_)),
279 iy = int(floor(y / tile_)),
280 ind = (utmp ? 2 : 0) + (northp ? 1 : 0);
281 if (! (ix >= mineasting_[ind] && ix < maxeasting_[ind]) ) {
282 if (ix == maxeasting_[ind] && x == maxeasting_[ind] * tile_)
287 + (utmp ?
"UTM" :
"UPS") +
" range for "
288 + (northp ?
"N" :
"S" ) +
" hemisphere ["
294 if (! (iy >= minnorthing_[ind] && iy < maxnorthing_[ind]) ) {
295 if (iy == maxnorthing_[ind] && y == maxnorthing_[ind] * tile_)
298 throw GeographicErr(
"Northing " +
Utility::str(
int(floor(y/1000)))
300 + (utmp ?
"UTM" :
"UPS") +
" range for "
301 + (northp ?
"N" :
"S" ) +
" hemisphere ["
310 if (northp && iy < minutmNrow_) {
313 }
else if (!northp && iy >= maxutmSrow_) {
314 if (y == maxutmSrow_ * tile_)
325 int MGRS::UTMRow(
int iband,
int icol,
int irow)
throw() {
333 real c = 100 * (8 * iband + 4)/
real(90);
334 bool northp = iband >= 0;
357 minrow = iband > -10 ?
358 int(floor(c -
real(4.3) -
real(0.1) * northp)) : -90,
360 int(floor(c +
real(4.4) -
real(0.1) * northp)) : 94,
361 baserow = (minrow + maxrow) / 2 - utmrowperiod_ / 2;
363 irow = (irow - baserow + maxutmSrow_) % utmrowperiod_ + baserow;
364 if (irow < minrow || irow > maxrow) {
369 sband = iband >= 0 ? iband : -iband - 1,
371 srow = irow >= 0 ? irow : -irow - 1,
373 scol = icol < 4 ? icol : -icol + 7;
374 if ( ! ( (srow == 70 && sband == 8 && scol >= 2) ||
375 (srow == 71 && sband == 7 && scol <= 2) ||
376 (srow == 79 && sband == 9 && scol >= 1) ||
377 (srow == 80 && sband == 8 && scol <= 1) ) )
GeographicLib::Math::real real
Header for GeographicLib::Utility class.
Header for GeographicLib::MGRS class.
static std::string str(T x, int p=-1)
static void Reverse(int zone, bool northp, real x, real y, real &lat, real &lon, real &gamma, real &k, bool mgrslimits=false)
static void Reverse(const std::string &mgrs, int &zone, bool &northp, real &x, real &y, int &prec, bool centerp=true)
Exception handling for GeographicLib.
static int lookup(const std::string &s, char c)
static void Forward(int zone, bool northp, real x, real y, int prec, std::string &mgrs)