18 const char*
const MGRS::utmcols_[] = {
"ABCDEFGH",
"JKLMNPQR",
"STUVWXYZ" };
21 {
"JKLPQRSTUXYZ",
"ABCFGHJKLPQR",
"RSTUXYZ",
"ABCFGHJ" };
23 {
"ABCDEFGHJKLMNPQRSTUVWXYZ",
"ABCDEFGHJKLMNP" };
29 { minupsSind_, minupsNind_, minutmcol_, minutmcol_ };
31 { maxupsSind_, maxupsNind_, maxutmcol_, maxutmcol_ };
33 { minupsSind_, minupsNind_,
34 minutmSrow_, minutmSrow_ - (maxutmSrow_ - minutmNrow_) };
36 { maxupsSind_, maxupsNind_,
37 maxutmNrow_ + (maxutmSrow_ - minutmNrow_), maxutmNrow_ };
40 int prec, std::string& mgrs) {
49 bool utmp = zone != 0;
50 CheckCoords(utmp, northp,
x,
y);
53 if (!(prec >= -1 && prec <= maxprec_))
59 char mgrs1[2 + 3 + 2 * maxprec_];
63 mlen =
z + 3 + 2 * prec;
65 mgrs1[0] = digits_[ zone / base_ ];
66 mgrs1[1] = digits_[ zone % base_ ];
72 GEOGRAPHICLIB_STATIC_ASSERT(numeric_limits<long long>::digits >= 44,
73 "long long not wide enough to store 10e12");
75 ix = (
long long)(
floor(
x * mult_)),
76 iy = (
long long)(
floor(
y * mult_)),
77 m = (
long long)(mult_) * (
long long)(tile_);
78 int xh =
int(ix /
m), yh =
int(iy /
m);
82 iband =
abs(
lat) > angeps ? LatitudeBand(
lat) : (northp ? 0 : -1),
83 icol = xh - minutmcol_,
84 irow = UTMRow(iband, icol, yh % utmrowperiod_);
85 if (irow != yh - (northp ? minutmNrow_ : maxutmSrow_))
87 +
" is inconsistent with UTM coordinates");
88 mgrs1[
z++] = latband_[10 + iband];
89 mgrs1[
z++] = utmcols_[zone1 % 3][icol];
90 mgrs1[
z++] = utmrow_[(yh + (zone1 & 1 ? utmevenrowshift_ : 0))
93 bool eastp = xh >= upseasting_;
94 int iband = (northp ? 2 : 0) + (eastp ? 1 : 0);
95 mgrs1[
z++] = upsband_[iband];
96 mgrs1[
z++] = upscols_[iband][xh - (eastp ? upseasting_ :
97 (northp ? minupsNind_ :
99 mgrs1[
z++] = upsrows_[northp][yh - (northp ? minupsNind_ : minupsSind_)];
102 ix -=
m * xh; iy -=
m * yh;
103 long long d = (
long long)(
pow(
real(base_), maxprec_ - prec));
105 for (
int c = prec;
c--;) {
106 mgrs1[
z +
c ] = digits_[ix % base_]; ix /= base_;
107 mgrs1[
z +
c + prec] = digits_[iy % base_]; iy /= base_;
111 copy(mgrs1, mgrs1 + mlen, mgrs.begin());
115 int prec, std::string& mgrs) {
119 real ys = northp ?
y :
y - utmNshift_;
133 latp =
real(0.901) * ys + (ys > 0 ? 1 : -1) *
real(0.135),
136 late =
real(0.902) * ys * (1 -
real(1.85
e-6) * ys * ys);
137 if (LatitudeBand(latp) == LatitudeBand(late))
151 int& prec,
bool centerp) {
156 toupper(mgrs[0]) ==
'I' &&
157 toupper(mgrs[1]) ==
'N' &&
158 toupper(mgrs[2]) ==
'V') {
170 zone1 = 10 * zone1 +
i;
177 + mgrs.substr(0,
p));
181 int zonem1 = zone1 - 1;
182 const char*
band = utmp ? latband_ : upsband_;
186 + (utmp ?
"UTM" :
"UPS") +
" set " +
band);
187 bool northp1 = iband >= (utmp ? 10 : 2);
190 real deg =
real(utmNshift_) / (90 * tile_);
195 x = ((zone == 31 && iband == 17) ? 4 : 5) * tile_;
198 + (northp ? 0 : utmNshift_);
201 x = ((iband & 1 ? 1 : -1) *
floor(4 * deg +
real(0.5))
202 + upseasting_) * tile_;
204 y = upseasting_ * tile_;
208 }
else if (
len -
p < 2)
210 const char*
col = utmp ? utmcols_[zonem1 % 3] : upscols_[iband];
211 const char*
row = utmp ? utmrow_ : upsrows_[northp1];
216 + (utmp ?
"zone " + mgrs.substr(0,
p-2) :
227 irow = (irow + utmrowperiod_ - utmevenrowshift_) % utmrowperiod_;
229 irow = UTMRow(iband, icol, irow);
230 if (irow == maxutmSrow_)
232 +
" not in zone/band " + mgrs.substr(0,
p-2));
234 irow = northp1 ? irow : irow + 100;
235 icol = icol + minutmcol_;
237 bool eastp = iband & 1;
238 icol += eastp ? upseasting_ : (northp1 ? minupsNind_ : minupsSind_);
239 irow += northp1 ? minupsNind_ : minupsSind_;
241 int prec1 = (
len -
p)/2;
246 for (
int i = 0;
i < prec1; ++
i) {
251 if (ix < 0 || iy < 0)
252 throw GeographicErr(
"Encountered a non-digit in " + mgrs.substr(
p));
253 x1 = base_ *
x1 + ix;
254 y1 = base_ *
y1 + iy;
258 throw GeographicErr(
"Encountered a non-digit in " + mgrs.substr(
p));
263 if (prec1 > maxprec_)
265 +
" digits in " + mgrs.substr(
p));
267 unit *= 2;
x1 = 2 *
x1 + 1;
y1 = 2 *
y1 + 1;
271 x = (tile_ *
x1) / unit;
272 y = (tile_ *
y1) / unit;
290 ind = (utmp ? 2 : 0) + (northp ? 1 : 0);
291 if (! (ix >= mineasting_[
ind] && ix < maxeasting_[
ind]) ) {
292 if (ix == maxeasting_[
ind] &&
x == maxeasting_[
ind] * tile_)
297 + (utmp ?
"UTM" :
"UPS") +
" range for "
298 + (northp ?
"N" :
"S" ) +
" hemisphere ["
304 if (! (iy >= minnorthing_[
ind] && iy < maxnorthing_[
ind]) ) {
305 if (iy == maxnorthing_[
ind] &&
y == maxnorthing_[
ind] * tile_)
310 + (utmp ?
"UTM" :
"UPS") +
" range for "
311 + (northp ?
"N" :
"S" ) +
" hemisphere ["
320 if (northp && iy < minutmNrow_) {
323 }
else if (!northp && iy >= maxutmSrow_) {
324 if (
y == maxutmSrow_ * tile_)
345 bool northp = iband >= 0;
369 minrow = iband > -10 ?
373 baserow = (minrow + maxrow) / 2 - utmrowperiod_ / 2;
377 irow = (irow - baserow + maxutmSrow_) % utmrowperiod_ + baserow;
378 if (!( irow >= minrow && irow <= maxrow )) {
387 sband = iband >= 0 ? iband : -iband - 1,
389 srow = irow >= 0 ? irow : -irow - 1,
391 scol = icol < 4 ? icol : -icol + 7;
394 if ( ! ( (srow == 70 && sband == 8 && scol >= 2) ||
395 (srow == 71 && sband == 7 && scol <= 2) ||
396 (srow == 79 && sband == 9 && scol >= 1) ||
397 (srow == 80 && sband == 8 && scol <= 1) ) )
407 throw GeographicErr(
"MGRS::Check: equator coverage failure");
410 throw GeographicErr(
"MGRS::Check: UTM doesn't reach latitude = 84");
413 throw GeographicErr(
"MGRS::Check: UTM doesn't reach latitude = -80");
416 throw GeographicErr(
"MGRS::Check: Norway exception creates a gap");
419 throw GeographicErr(
"MGRS::Check: Svalbard exception creates a gap");
423 GeographicErr(
"MGRS::Check: North UPS doesn't reach latitude = 84");
427 GeographicErr(
"MGRS::Check: South UPS doesn't reach latitude = -80");
430 const short tab[] = {
446 7, 5, 70, 7, 7, 70, 7, 7, 71, 7, 9, 71,
447 8, 5, 71, 8, 6, 71, 8, 6, 72, 8, 9, 72,
448 8, 5, 79, 8, 8, 79, 8, 8, 80, 8, 9, 80,
449 9, 5, 80, 9, 7, 80, 9, 7, 81, 9, 9, 81,
452 const int bandchecks =
sizeof(tab) / (3 *
sizeof(
short));
453 for (
int i = 0;
i < bandchecks; ++
i) {
455 if (!( LatitudeBand(
lat) == tab[3*
i+0] ))