20 const int UTMUPS::falseeasting_[] =
21 { MGRS::upseasting_ * MGRS::tile_, MGRS::upseasting_ * MGRS::tile_,
22 MGRS::utmeasting_ * MGRS::tile_, MGRS::utmeasting_ * MGRS::tile_ };
23 const int UTMUPS::falsenorthing_[] =
24 { MGRS::upseasting_ * MGRS::tile_, MGRS::upseasting_ * MGRS::tile_,
25 MGRS::maxutmSrow_ * MGRS::tile_, MGRS::minutmNrow_ * MGRS::tile_ };
26 const int UTMUPS::mineasting_[] =
27 { MGRS::minupsSind_ * MGRS::tile_, MGRS::minupsNind_ * MGRS::tile_,
28 MGRS::minutmcol_ * MGRS::tile_, MGRS::minutmcol_ * MGRS::tile_ };
29 const int UTMUPS::maxeasting_[] =
30 { MGRS::maxupsSind_ * MGRS::tile_, MGRS::maxupsNind_ * MGRS::tile_,
31 MGRS::maxutmcol_ * MGRS::tile_, MGRS::maxutmcol_ * MGRS::tile_ };
32 const int UTMUPS::minnorthing_[] =
33 { MGRS::minupsSind_ * MGRS::tile_, MGRS::minupsNind_ * MGRS::tile_,
34 MGRS::minutmSrow_ * MGRS::tile_,
35 (MGRS::minutmNrow_ + MGRS::minutmSrow_ - MGRS::maxutmSrow_)
37 const int UTMUPS::maxnorthing_[] =
38 { MGRS::maxupsSind_ * MGRS::tile_, MGRS::maxupsNind_ * MGRS::tile_,
39 (MGRS::maxutmSrow_ + MGRS::maxutmNrow_ - MGRS::minutmNrow_) *
41 MGRS::maxutmNrow_ * MGRS::tile_ };
49 if (isnan(lat) || isnan(lon))
51 if (setzone ==
UTM || (lat >= -80 && lat < 84)) {
54 int zone = (ilon + 186)/6;
55 int band = MGRS::LatitudeBand(lat);
56 if (band == 7 && zone == 31 && ilon >= 3)
58 else if (band == 9 && ilon >= 0 && ilon < 42)
59 zone = 2 * ((ilon + 183)/12) + 1;
66 int& zone,
bool& northp, real& x, real& y,
68 int setzone,
bool mgrslimits) {
71 +
"d not in [-" + to_string(
Math::qd)
72 +
"d, " + to_string(
Math::qd) +
"d]");
73 bool northp1 = !(signbit(lat));
81 real x1, y1, gamma1, k1;
82 bool utmp = zone1 !=
UPS;
85 lon0 = CentralMeridian(zone1),
91 +
"d more than 60d from center of UTM zone "
98 +
"d more than 20d from "
99 + (northp1 ?
"N" :
"S") +
" pole");
102 int ind = (utmp ? 2 : 0) + (northp1 ? 1 : 0);
103 x1 += falseeasting_[ind];
104 y1 += falsenorthing_[ind];
105 if (! CheckCoords(zone1 !=
UPS, northp1, x1, y1, mgrslimits,
false) )
108 +
" out of legal range for "
120 real& lat, real& lon, real& gamma, real& k,
123 if (zone ==
INVALID || isnan(x) || isnan(y)) {
129 +
" not in range [0, 60]");
130 bool utmp = zone !=
UPS;
131 CheckCoords(utmp, northp, x, y, mgrslimits);
132 int ind = (utmp ? 2 : 0) + (northp ? 1 : 0);
133 x -= falseeasting_[ind];
134 y -= falsenorthing_[ind];
137 x, y, lat, lon, gamma, k);
142 bool UTMUPS::CheckCoords(
bool utmp,
bool northp,
real x,
real y,
143 bool mgrslimits,
bool throwp) {
146 real slop = mgrslimits ? 0 : MGRS::tile_;
147 int ind = (utmp ? 2 : 0) + (northp ? 1 : 0);
148 if (x < mineasting_[ind] - slop || x > maxeasting_[ind] + slop) {
149 if (!throwp)
return false;
151 + (mgrslimits ?
"MGRS/" :
"")
152 + (utmp ?
"UTM" :
"UPS") +
" range for "
153 + (northp ?
"N" :
"S" ) +
" hemisphere ["
154 +
Utility::str((mineasting_[ind] - slop)/1000)
156 +
Utility::str((maxeasting_[ind] + slop)/1000)
159 if (y < minnorthing_[ind] - slop || y > maxnorthing_[ind] + slop) {
160 if (!throwp)
return false;
161 throw GeographicErr(
"Northing " +
Utility::str(y/1000) +
"km not in "
162 + (mgrslimits ?
"MGRS/" :
"")
163 + (utmp ?
"UTM" :
"UPS") +
" range for "
164 + (northp ?
"N" :
"S" ) +
" hemisphere ["
165 + Utility::str((minnorthing_[ind] - slop)/1000)
167 + Utility::str((maxnorthing_[ind] + slop)/1000)
174 int zoneout,
bool northpout, real& xout, real& yout,
176 bool northp = northpin;
177 if (zonein != zoneout) {
187 if (zone1 == 0 && northp != northpout)
189 (
"Attempt to transfer UPS coordinates between hemispheres");
194 if (zoneout == 0 && northp != northpout)
196 (
"Attempt to transfer UPS coordinates between hemispheres");
201 if (northp != northpout)
203 yout += (northpout ? -1 : 1) * MGRS::utmNshift_;
209 unsigned zlen = unsigned(zonestr.size());
214 throw GeographicErr(
"More than 7 characters in zone specification "
217 const char* c = zonestr.c_str();
219 int zone1 = strtol(c, &q, 10);
226 ", use just the hemisphere for UPS");
229 +
" not in range [1, 60]");
230 else if (!isdigit(zonestr[0]))
234 throw GeographicErr(
"More than 2 digits use to specify zone "
237 string hemi(zonestr, q - c);
238 for (string::iterator p = hemi.begin(); p != hemi.end(); ++p)
239 *p =
char(tolower(*p));
240 if (q == c && (hemi ==
"inv" || hemi ==
"invalid")) {
245 bool northp1 = hemi ==
"north" || hemi ==
"n";
246 if (!(northp1 || hemi ==
"south" || hemi ==
"s"))
247 throw GeographicErr(
string(
"Illegal hemisphere ") + hemi +
" in "
248 + zonestr +
", specify north or south");
255 return string(abbrev ?
"inv" :
"invalid");
258 +
" not in range [0, 60]");
261 os << setfill(
'0') << setw(2) << zone;
263 os << (northp ?
'n' :
's');
265 os << (northp ?
"north" :
"south");
271 if (epsg >= epsg01N && epsg <= epsg60N) {
274 }
else if (epsg == epsgN) {
277 }
else if (epsg >= epsg01S && epsg <= epsg60S) {
279 }
else if (epsg == epsgS) {
292 if (epsg >= 0 && northp)
293 epsg += epsgN - epsgS;
GeographicLib::Math::real real
Header for GeographicLib::MGRS class.
Header for GeographicLib::PolarStereographic class.
Header for GeographicLib::TransverseMercator class.
Header for GeographicLib::UTMUPS class.
Header for GeographicLib::Utility class.
Exception handling for GeographicLib.
static constexpr int qd
degrees per quarter turn
static T AngNormalize(T x)
static T AngDiff(T x, T y, T &e)
static constexpr int hd
degrees per half turn
void Reverse(bool northp, real x, real y, real &lat, real &lon, real &gamma, real &k) const
static const PolarStereographic & UPS()
void Forward(bool northp, 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
static const TransverseMercator & UTM()
void Forward(real lon0, real lat, real lon, real &x, real &y, real &gamma, real &k) const
static int EncodeEPSG(int zone, bool northp)
static int StandardZone(real lat, real lon, int setzone=STANDARD)
static std::string EncodeZone(int zone, bool northp, bool abbrev=true)
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)
static void DecodeEPSG(int epsg, int &zone, bool &northp)
static void Reverse(int zone, bool northp, real x, real y, real &lat, real &lon, real &gamma, real &k, bool mgrslimits=false)
static Math::real UTMShift()
static void Transfer(int zonein, bool northpin, real xin, real yin, int zoneout, bool northpout, real &xout, real &yout, int &zone)
static void DecodeZone(const std::string &zonestr, int &zone, bool &northp)
Some utility routines for GeographicLib.
static std::string str(T x, int p=-1)
Namespace for GeographicLib.