17 const string MGRS::hemispheres_ =
"SN";
18 const string MGRS::utmcols_[3] = {
"ABCDEFGH",
"JKLMNPQR",
"STUVWXYZ" };
19 const string MGRS::utmrow_ =
"ABCDEFGHJKLMNPQRSTUV";
20 const string MGRS::upscols_[4] =
21 {
"JKLPQRSTUXYZ",
"ABCFGHJKLPQR",
"RSTUXYZ",
"ABCFGHJ" };
22 const string MGRS::upsrows_[2] =
23 {
"ABCDEFGHJKLMNPQRSTUVWXYZ",
"ABCDEFGHJKLMNP" };
24 const string MGRS::latband_ =
"CDEFGHJKLMNPQRSTUVWX";
25 const string MGRS::upsband_ =
"ABYZ";
26 const string MGRS::digits_ =
"0123456789";
28 const int MGRS::mineasting_[4] =
29 { minupsSind_, minupsNind_, minutmcol_, minutmcol_ };
30 const int MGRS::maxeasting_[4] =
31 { maxupsSind_, maxupsNind_, maxutmcol_, maxutmcol_ };
32 const int MGRS::minnorthing_[4] =
33 { minupsSind_, minupsNind_,
34 minutmSrow_, minutmSrow_ - (maxutmSrow_ - minutmNrow_) };
35 const int MGRS::maxnorthing_[4] =
36 { maxupsSind_, maxupsNind_,
37 maxutmNrow_ + (maxutmSrow_ - minutmNrow_), maxutmNrow_ };
40 int prec, std::string& mgrs) {
46 bool utmp = zone != 0;
47 CheckCoords(utmp, northp, x, y);
50 if (!(prec >= -1 && prec <= maxprec_))
56 char mgrs1[2 + 3 + 2 * maxprec_];
60 mlen = z + 3 + 2 * prec;
62 mgrs1[0] = digits_[ zone / base_ ];
63 mgrs1[1] = digits_[ zone % base_ ];
68 xh = int(floor(x)) / tile_,
69 yh = int(floor(y)) / tile_;
76 iband = abs(lat) > angeps() ? LatitudeBand(lat) : (northp ? 0 : -1),
77 icol = xh - minutmcol_,
78 irow = UTMRow(iband, icol, yh % utmrowperiod_);
79 if (irow != yh - (northp ? minutmNrow_ : maxutmSrow_))
81 +
" is inconsistent with UTM coordinates");
82 mgrs1[z++] = latband_[10 + iband];
83 mgrs1[z++] = utmcols_[zone1 % 3][icol];
84 mgrs1[z++] = utmrow_[(yh + (zone1 & 1 ? utmevenrowshift_ : 0))
87 bool eastp = xh >= upseasting_;
88 int iband = (northp ? 2 : 0) + (eastp ? 1 : 0);
89 mgrs1[z++] = upsband_[iband];
90 mgrs1[z++] = upscols_[iband][xh - (eastp ? upseasting_ :
91 (northp ? minupsNind_ : minupsSind_))];
92 mgrs1[z++] = upsrows_[northp][yh - (northp ? minupsNind_ : minupsSind_)];
95 real mult = pow(
real(base_), max(tilelevel_ - prec, 0));
97 ix = int(floor(xf / mult)),
98 iy = int(floor(yf / mult));
99 for (
int c = min(prec,
int(tilelevel_)); c--;) {
100 mgrs1[z + c] = digits_[ ix % base_ ];
102 mgrs1[z + c + prec] = digits_[ iy % base_ ];
105 if (prec > tilelevel_) {
106 xf -= floor(xf / mult);
107 yf -= floor(yf / mult);
108 mult = pow(
real(base_), prec - tilelevel_);
109 ix = int(floor(xf * mult));
110 iy = int(floor(yf * mult));
111 for (
int c = prec - tilelevel_; c--;) {
112 mgrs1[z + c + tilelevel_] = digits_[ ix % base_ ];
114 mgrs1[z + c + tilelevel_ + prec] = digits_[ iy % base_ ];
120 copy(mgrs1, mgrs1 + mlen, mgrs.begin());
124 int prec, std::string& mgrs) {
128 real ys = northp ? y : y - utmNshift_;
142 latp =
real(0.901) * ys + (ys > 0 ? 1 : -1) *
real(0.135),
145 late =
real(0.902) * ys * (1 -
real(1.85e-6) * ys * ys);
146 if (LatitudeBand(latp) == LatitudeBand(late))
155 Forward(zone, northp, x, y, lat, prec, mgrs);
159 int& zone,
bool& northp, real& x, real& y,
160 int& prec,
bool centerp) {
163 len = int(mgrs.size());
165 toupper(mgrs[0]) ==
'I' &&
166 toupper(mgrs[1]) ==
'N' &&
167 toupper(mgrs[2]) ==
'V') {
179 zone1 = 10 * zone1 + i;
186 + mgrs.substr(0, p));
190 int zonem1 = zone1 - 1;
191 const string& band = utmp ? latband_ : upsband_;
195 + (utmp ?
"UTM" :
"UPS") +
" set " + band);
196 bool northp1 = iband >= (utmp ? 10 : 2);
199 real deg =
real(utmNshift_) / (90 * tile_);
204 x = ((zone == 31 && iband == 17) ? 4 : 5) * tile_;
206 y = floor(8 * (iband -
real(9.5)) * deg +
real(0.5)) * tile_
207 + (northp ? 0 : utmNshift_);
210 x = ((iband & 1 ? 1 : -1) * floor(4 * deg +
real(0.5))
211 + upseasting_) * tile_;
213 y = upseasting_ * tile_;
217 }
else if (len - p < 2)
219 const string& col = utmp ? utmcols_[zonem1 % 3] : upscols_[iband];
220 const string& row = utmp ? utmrow_ : upsrows_[northp1];
225 + (utmp ?
"zone " + mgrs.substr(0, p-2) :
236 irow = (irow + utmrowperiod_ - utmevenrowshift_) % utmrowperiod_;
238 irow = UTMRow(iband, icol, irow);
239 if (irow == maxutmSrow_)
241 +
" not in zone/band " + mgrs.substr(0, p-2));
243 irow = northp1 ? irow : irow + 100;
244 icol = icol + minutmcol_;
246 bool eastp = iband & 1;
247 icol += eastp ? upseasting_ : (northp1 ? minupsNind_ : minupsSind_);
248 irow += northp1 ? minupsNind_ : minupsSind_;
250 int prec1 = (len - p)/2;
255 for (
int i = 0; i < prec1; ++i) {
260 if (ix < 0 || iy < 0)
261 throw GeographicErr(
"Encountered a non-digit in " + mgrs.substr(p));
267 throw GeographicErr(
"Encountered a non-digit in " + mgrs.substr(p));
272 if (prec1 > maxprec_)
287 void MGRS::CheckCoords(
bool utmp,
bool& northp, real& x, real& y) {
294 ix = int(floor(x / tile_)),
295 iy = int(floor(y / tile_)),
296 ind = (utmp ? 2 : 0) + (northp ? 1 : 0);
297 if (! (ix >= mineasting_[ind] && ix < maxeasting_[ind]) ) {
298 if (ix == maxeasting_[ind] && x == maxeasting_[ind] * tile_)
303 + (utmp ?
"UTM" :
"UPS") +
" range for " 304 + (northp ?
"N" :
"S" ) +
" hemisphere [" 310 if (! (iy >= minnorthing_[ind] && iy < maxnorthing_[ind]) ) {
311 if (iy == maxnorthing_[ind] && y == maxnorthing_[ind] * tile_)
316 + (utmp ?
"UTM" :
"UPS") +
" range for " 317 + (northp ?
"N" :
"S" ) +
" hemisphere [" 326 if (northp && iy < minutmNrow_) {
329 }
else if (!northp && iy >= maxutmSrow_) {
330 if (y == maxutmSrow_ * tile_)
341 int MGRS::UTMRow(
int iband,
int icol,
int irow) {
350 real c = 100 * (8 * iband + 4)/
real(90);
351 bool northp = iband >= 0;
375 minrow = iband > -10 ?
376 int(floor(c -
real(4.3) -
real(0.1) * northp)) : -90,
378 int(floor(c +
real(4.4) -
real(0.1) * northp)) : 94,
379 baserow = (minrow + maxrow) / 2 - utmrowperiod_ / 2;
383 irow = (irow - baserow + maxutmSrow_) % utmrowperiod_ + baserow;
384 if (!( irow >= minrow && irow <= maxrow )) {
393 sband = iband >= 0 ? iband : -iband - 1,
395 srow = irow >= 0 ? irow : -irow - 1,
397 scol = icol < 4 ? icol : -icol + 7;
400 if ( ! ( (srow == 70 && sband == 8 && scol >= 2) ||
401 (srow == 71 && sband == 7 && scol <= 2) ||
402 (srow == 79 && sband == 9 && scol >= 1) ||
403 (srow == 80 && sband == 8 && scol <= 1) ) )
410 real lat, lon, x, y, t = tile_;
int zone;
bool northp;
413 throw GeographicErr(
"MGRS::Check: equator coverage failure");
416 throw GeographicErr(
"MGRS::Check: UTM doesn't reach latitude = 84");
419 throw GeographicErr(
"MGRS::Check: UTM doesn't reach latitude = -80");
422 throw GeographicErr(
"MGRS::Check: Norway exception creates a gap");
425 throw GeographicErr(
"MGRS::Check: Svalbard exception creates a gap");
428 throw GeographicErr(
"MGRS::Check: North UPS doesn't reach latitude = 84");
432 GeographicErr(
"MGRS::Check: South UPS doesn't reach latitude = -80");
435 const short tab[] = {
451 7, 5, 70, 7, 7, 70, 7, 7, 71, 7, 9, 71,
452 8, 5, 71, 8, 6, 71, 8, 6, 72, 8, 9, 72,
453 8, 5, 79, 8, 8, 79, 8, 8, 80, 8, 9, 80,
454 9, 5, 80, 9, 7, 80, 9, 7, 81, 9, 9, 81,
457 const int bandchecks =
sizeof(tab) / (3 *
sizeof(
short));
458 for (
int i = 0; i < bandchecks; ++i) {
460 if (!( LatitudeBand(lat) == tab[3*i+0] ))
GeographicLib::Math::real real
Header for GeographicLib::Utility class.
Header for GeographicLib::MGRS class.
static void Forward(real lat, real lon, int &zone, bool &northp, real &x, real &y, real &gamma, real &k, int setzone=STANDARD, bool mgrslimits=false)
Namespace for GeographicLib.
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)