src/UTMUPS.cpp
Go to the documentation of this file.
1 
10 #include <GeographicLib/UTMUPS.hpp>
11 #include <GeographicLib/MGRS.hpp>
15 
16 namespace GeographicLib {
17 
18  using namespace std;
19 
20  const int UTMUPS::falseeasting_[] =
23  const int UTMUPS::falsenorthing_[] =
26  const int UTMUPS::mineasting_[] =
29  const int UTMUPS::maxeasting_[] =
32  const int UTMUPS::minnorthing_[] =
36  * MGRS::tile_ };
37  const int UTMUPS::maxnorthing_[] =
40  MGRS::tile_,
41  MGRS::maxutmNrow_ * MGRS::tile_ };
42 
43  int UTMUPS::StandardZone(real lat, real lon, int setzone) {
44  if (!(setzone >= MINPSEUDOZONE && setzone <= MAXZONE))
45  throw GeographicErr("Illegal zone requested " + Utility::str(setzone));
46  if (setzone >= MINZONE || setzone == INVALID)
47  return setzone;
48  if (Math::isnan(lat) || Math::isnan(lon)) // Check if lat or lon is a NaN
49  return INVALID;
50  if (setzone == UTM || (lat >= -80 && lat < 84)) {
51  int ilon = int(floor(fmod(lon, real(360))));
52  if (ilon >= 180)
53  ilon -= 360;
54  else if (ilon < -180)
55  ilon += 360;
56  int zone = (ilon + 186)/6;
57  int band = MGRS::LatitudeBand(lat);
58  if (band == 7 && zone == 31 && ilon >= 3) // The Norway exception
59  zone = 32;
60  else if (band == 9 && ilon >= 0 && ilon < 42) // The Svalbard exception
61  zone = 2 * ((ilon + 183)/12) + 1;
62  return zone;
63  } else
64  return UPS;
65  }
66 
68  int& zone, bool& northp, real& x, real& y,
69  real& gamma, real& k,
70  int setzone, bool mgrslimits) {
71  if (abs(lat) > 90)
72  throw GeographicErr("Latitude " + Utility::str(lat)
73  + "d not in [-90d, 90d]");
74  bool northp1 = lat >= 0;
75  int zone1 = StandardZone(lat, lon, setzone);
76  if (zone1 == INVALID) {
77  zone = zone1;
78  northp = northp1;
79  x = y = gamma = k = Math::NaN();
80  return;
81  }
82  real x1, y1, gamma1, k1;
83  bool utmp = zone1 != UPS;
84  if (utmp) {
85  real
86  lon0 = CentralMeridian(zone1),
87  dlon = lon - lon0;
88  dlon = abs(dlon - 360 * floor((dlon + 180)/360));
89  if (!(dlon <= 60))
90  // Check isn't really necessary because CheckCoords catches this case.
91  // But this allows a more meaningful error message to be given.
92  throw GeographicErr("Longitude " + Utility::str(lon)
93  + "d more than 60d from center of UTM zone "
94  + Utility::str(zone1));
95  TransverseMercator::UTM().Forward(lon0, lat, lon, x1, y1, gamma1, k1);
96  } else {
97  if (abs(lat) < 70)
98  // Check isn't really necessary ... (see above).
99  throw GeographicErr("Latitude " + Utility::str(lat)
100  + "d more than 20d from "
101  + (northp1 ? "N" : "S") + " pole");
102  PolarStereographic::UPS().Forward(northp1, lat, lon, x1, y1, gamma1, k1);
103  }
104  int ind = (utmp ? 2 : 0) + (northp1 ? 1 : 0);
105  x1 += falseeasting_[ind];
106  y1 += falsenorthing_[ind];
107  if (! CheckCoords(zone1 != UPS, northp1, x1, y1, mgrslimits, false) )
108  throw GeographicErr("Latitude " + Utility::str(lat)
109  + ", longitude " + Utility::str(lon)
110  + " out of legal range for "
111  + (utmp ? "UTM zone " + Utility::str(zone1) :
112  "UPS"));
113  zone = zone1;
114  northp = northp1;
115  x = x1;
116  y = y1;
117  gamma = gamma1;
118  k = k1;
119  }
120 
121  void UTMUPS::Reverse(int zone, bool northp, real x, real y,
122  real& lat, real& lon, real& gamma, real& k,
123  bool mgrslimits) {
124  if (zone == INVALID || Math::isnan(x) || Math::isnan(y)) {
125  lat = lon = gamma = k = Math::NaN();
126  return;
127  }
128  if (!(zone >= MINZONE && zone <= MAXZONE))
129  throw GeographicErr("Zone " + Utility::str(zone)
130  + " not in range [0, 60]");
131  bool utmp = zone != UPS;
132  CheckCoords(utmp, northp, x, y, mgrslimits);
133  int ind = (utmp ? 2 : 0) + (northp ? 1 : 0);
134  x -= falseeasting_[ind];
135  y -= falsenorthing_[ind];
136  if (utmp)
137  TransverseMercator::UTM().Reverse(CentralMeridian(zone),
138  x, y, lat, lon, gamma, k);
139  else
140  PolarStereographic::UPS().Reverse(northp, x, y, lat, lon, gamma, k);
141  }
142 
143  bool UTMUPS::CheckCoords(bool utmp, bool northp, real x, real y,
144  bool mgrslimits, bool throwp) {
145  // Limits are all multiples of 100km and are all closed on the both ends.
146  // Failure tests are such that NaNs succeed.
147  real slop = mgrslimits ? 0 : MGRS::tile_;
148  int ind = (utmp ? 2 : 0) + (northp ? 1 : 0);
149  if (x < mineasting_[ind] - slop || x > maxeasting_[ind] + slop) {
150  if (!throwp) return false;
151  throw GeographicErr("Easting " + Utility::str(x/1000) + "km not in "
152  + (mgrslimits ? "MGRS/" : "")
153  + (utmp ? "UTM" : "UPS") + " range for "
154  + (northp ? "N" : "S" ) + " hemisphere ["
155  + Utility::str((mineasting_[ind] - slop)/1000)
156  + "km, "
157  + Utility::str((maxeasting_[ind] + slop)/1000)
158  + "km]");
159  }
160  if (y < minnorthing_[ind] - slop || y > maxnorthing_[ind] + slop) {
161  if (!throwp) return false;
162  throw GeographicErr("Northing " + Utility::str(y/1000) + "km not in "
163  + (mgrslimits ? "MGRS/" : "")
164  + (utmp ? "UTM" : "UPS") + " range for "
165  + (northp ? "N" : "S" ) + " hemisphere ["
166  + Utility::str((minnorthing_[ind] - slop)/1000)
167  + "km, "
168  + Utility::str((maxnorthing_[ind] + slop)/1000)
169  + "km]");
170  }
171  return true;
172  }
173 
174  void UTMUPS::Transfer(int zonein, bool northpin, real xin, real yin,
175  int zoneout, bool northpout, real& xout, real& yout,
176  int& zone) {
177  bool northp = northpin;
178  if (zonein != zoneout) {
179  // Determine lat, lon
180  real lat, lon;
181  GeographicLib::UTMUPS::Reverse(zonein, northpin, xin, yin, lat, lon);
182  // Try converting to zoneout
183  real x, y;
184  int zone1;
185  GeographicLib::UTMUPS::Forward(lat, lon, zone1, northp, x, y,
186  zoneout == UTMUPS::MATCH
187  ? zonein : zoneout);
188  if (zone1 == 0 && northp != northpout)
189  throw GeographicErr
190  ("Attempt to transfer UPS coordinates between hemispheres");
191  zone = zone1;
192  xout = x;
193  yout = y;
194  } else {
195  if (zoneout == 0 && northp != northpout)
196  throw GeographicErr
197  ("Attempt to transfer UPS coordinates between hemispheres");
198  zone = zoneout;
199  xout = xin;
200  yout = yin;
201  }
202  if (northp != northpout)
203  // Can't get here if UPS
204  yout += (northpout ? -1 : 1) * MGRS::utmNshift_;
205  return;
206  }
207 
208  void UTMUPS::DecodeZone(const std::string& zonestr, int& zone, bool& northp)
209  {
210  unsigned zlen = unsigned(zonestr.size());
211  if (zlen == 0)
212  throw GeographicErr("Empty zone specification");
213  // Longest zone spec is 32north, 42south, invalid = 7
214  if (zlen > 7)
215  throw GeographicErr("More than 7 characters in zone specification "
216  + zonestr);
217 
218  const char* c = zonestr.c_str();
219  char* q;
220  int zone1 = strtol(c, &q, 10);
221  // if (zone1 == 0) zone1 = UPS; (not necessary)
222 
223  if (zone1 == UPS) {
224  if (!(q == c))
225  // Don't allow 0n as an alternative to n for UPS coordinates
226  throw GeographicErr("Illegal zone 0 in " + zonestr +
227  ", use just the hemisphere for UPS");
228  } else if (!(zone1 >= MINUTMZONE && zone1 <= MAXUTMZONE))
229  throw GeographicErr("Zone " + Utility::str(zone1)
230  + " not in range [1, 60]");
231  else if (!isdigit(zonestr[0]))
232  throw GeographicErr("Must use unsigned number for zone "
233  + Utility::str(zone1));
234  else if (q - c > 2)
235  throw GeographicErr("More than 2 digits use to specify zone "
236  + Utility::str(zone1));
237 
238  string hemi(zonestr, q - c);
239  for (std::string::iterator p = hemi.begin(); p != hemi.end(); ++p)
240  *p = char(std::tolower(*p));
241  if (q == c && (hemi == "inv" || hemi == "invalid")) {
242  zone = INVALID;
243  northp = false;
244  return;
245  }
246  bool northp1 = hemi == "north" || hemi == "n";
247  if (!(northp1 || hemi == "south" || hemi == "s"))
248  throw GeographicErr(string("Illegal hemisphere ") + hemi + " in "
249  + zonestr + ", specify north or south");
250  zone = zone1;
251  northp = northp1;
252  }
253 
254  std::string UTMUPS::EncodeZone(int zone, bool northp, bool abbrev) {
255  if (zone == INVALID)
256  return string(abbrev ? "inv" : "invalid");
257  if (!(zone >= MINZONE && zone <= MAXZONE))
258  throw GeographicErr("Zone " + Utility::str(zone)
259  + " not in range [0, 60]");
260  ostringstream os;
261  if (zone != UPS)
262  os << setfill('0') << setw(2) << zone;
263  if (abbrev)
264  os << (northp ? 'n' : 's');
265  else
266  os << (northp ? "north" : "south");
267  return os.str();
268  }
269 
270  void UTMUPS::DecodeEPSG(int epsg, int& zone, bool& northp) {
271  northp = false;
272  if (epsg >= epsg01N && epsg <= epsg60N) {
273  zone = (epsg - epsg01N) + MINUTMZONE;
274  northp = true;
275  } else if (epsg == epsgN) {
276  zone = UPS;
277  northp = true;
278  } else if (epsg >= epsg01S && epsg <= epsg60S) {
279  zone = (epsg - epsg01S) + MINUTMZONE;
280  } else if (epsg == epsgS) {
281  zone = UPS;
282  } else {
283  zone = INVALID;
284  }
285  }
286 
287  int UTMUPS::EncodeEPSG(int zone, bool northp) {
288  int epsg = -1;
289  if (zone == UPS)
290  epsg = epsgS;
291  else if (zone >= MINUTMZONE && zone <= MAXUTMZONE)
292  epsg = (zone - MINUTMZONE) + epsg01S;
293  if (epsg >= 0 && northp)
294  epsg += epsgN - epsgS;
295  return epsg;
296  }
297 
299 
300 } // namespace GeographicLib
static T NaN()
Definition: Math.hpp:830
static std::string EncodeZone(int zone, bool northp, bool abbrev=true)
Definition: src/UTMUPS.cpp:254
float real
Definition: datatypes.h:10
Scalar * y
return int(ret)+1
static const double lat
Math::real real
Definition: UTMUPS.hpp:77
static const int falseeasting_[4]
Definition: UTMUPS.hpp:78
Header for GeographicLib::Utility class.
static bool isnan(T x)
Definition: Math.hpp:853
Header for GeographicLib::UTMUPS class.
Scalar Scalar * c
Definition: benchVecAdd.cpp:17
static const int minnorthing_[4]
Definition: UTMUPS.hpp:82
static const int maxnorthing_[4]
Definition: UTMUPS.hpp:83
static const int maxeasting_[4]
Definition: UTMUPS.hpp:81
static void Transfer(int zonein, bool northpin, real xin, real yin, int zoneout, bool northpout, real &xout, real &yout, int &zone)
Definition: src/UTMUPS.cpp:174
static void DecodeEPSG(int epsg, int &zone, bool &northp)
Definition: src/UTMUPS.cpp:270
Definition: Half.h:150
void Forward(real lon0, real lat, real lon, real &x, real &y, real &gamma, real &k) const
static const TransverseMercator & UTM()
static const int mineasting_[4]
Definition: UTMUPS.hpp:80
static int LatitudeBand(real lat)
Definition: MGRS.hpp:109
Header for GeographicLib::TransverseMercator class.
void Forward(bool northp, real lat, real lon, real &x, real &y, real &gamma, real &k) const
Header for GeographicLib::MGRS class.
void Reverse(bool northp, real x, real y, real &lat, real &lon, real &gamma, real &k) const
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)
Definition: src/UTMUPS.cpp:67
static const int falsenorthing_[4]
Definition: UTMUPS.hpp:79
const mpreal gamma(const mpreal &x, mp_rnd_t r=mpreal::get_default_rnd())
Definition: mpreal.h:2262
static int EncodeEPSG(int zone, bool northp)
Definition: src/UTMUPS.cpp:287
static const PolarStereographic & UPS()
Namespace for GeographicLib.
EIGEN_DEVICE_FUNC const Scalar & q
static void DecodeZone(const std::string &zonestr, int &zone, bool &northp)
Definition: src/UTMUPS.cpp:208
const double lon0
static std::string str(T x, int p=-1)
Definition: Utility.hpp:276
void Reverse(real lon0, real x, real y, real &lat, real &lon, real &gamma, real &k) const
static void Reverse(int zone, bool northp, real x, real y, real &lat, real &lon, real &gamma, real &k, bool mgrslimits=false)
Definition: src/UTMUPS.cpp:121
EIGEN_DEVICE_FUNC const FloorReturnType floor() const
Exception handling for GeographicLib.
Definition: Constants.hpp:389
ofstream os("timeSchurFactors.csv")
Pose3 x1
Definition: testPose3.cpp:588
float * p
static bool CheckCoords(bool utmp, bool northp, real x, real y, bool msgrlimits=false, bool throwp=true)
Definition: src/UTMUPS.cpp:143
static const double lon
static Math::real UTMShift()
Definition: src/UTMUPS.cpp:298
Header for GeographicLib::PolarStereographic class.
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy x
#define abs(x)
Definition: datatypes.h:17
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T fmod(const T &a, const T &b)
static int StandardZone(real lat, real lon, int setzone=STANDARD)
Definition: src/UTMUPS.cpp:43


gtsam
Author(s):
autogenerated on Sat May 8 2021 02:51:23