GeographicLib: UTMUPS.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

15

17

18 using namespace std;

19

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_)

36 * MGRS::tile_ };

37 const int UTMUPS::maxnorthing_[] =

38 { MGRS::maxupsSind_ * MGRS::tile_, MGRS::maxupsNind_ * MGRS::tile_,

39 (MGRS::maxutmSrow_ + MGRS::maxutmNrow_ - MGRS::minutmNrow_) *

40 MGRS::tile_,

41 MGRS::maxutmNrow_ * MGRS::tile_ };

42

44 using std::isnan;

48 return setzone;

49 if (isnan(lat) || isnan(lon))

51 if (setzone == UTM || (lat >= -80 && lat < 84)) {

53 if (ilon == Math::hd) ilon = -Math::hd;

54 int zone = (ilon + 186)/6;

55 int band = MGRS::LatitudeBand(lat);

56 if (band == 7 && zone == 31 && ilon >= 3)

57 zone = 32;

58 else if (band == 9 && ilon >= 0 && ilon < 42)

59 zone = 2 * ((ilon + 183)/12) + 1;

60 return zone;

61 } else

62 return UPS;

63 }

64

66 int& zone, bool& northp, real& x, real& y,

67 real& gamma, real& k,

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));

76 zone = zone1;

77 northp = northp1;

79 return;

80 }

81 real x1, y1, gamma1, k1;

82 bool utmp = zone1 != UPS;

83 if (utmp) {

84 real

85 lon0 = CentralMeridian(zone1),

87 if (!(dlon <= 60))

88

89

91 + "d more than 60d from center of UTM zone "

94 } else {

95 if (fabs(lat) < 70)

96

98 + "d more than 20d from "

99 + (northp1 ? "N" : "S") + " pole");

101 }

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 "

109 + (utmp ? "UTM zone " + Utility::str(zone1) :

110 "UPS"));

111 zone = zone1;

112 northp = northp1;

113 x = x1;

114 y = y1;

115 gamma = gamma1;

116 k = k1;

117 }

118

120 real& lat, real& lon, real& gamma, real& k,

121 bool mgrslimits) {

122 using std::isnan;

123 if (zone == INVALID || isnan(x) || isnan(y)) {

124 lat = lon = gamma = k = Math::NaN();

125 return;

126 }

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];

135 if (utmp)

137 x, y, lat, lon, gamma, k);

138 else

140 }

141

142 bool UTMUPS::CheckCoords(bool utmp, bool northp, real x, real y,

143 bool mgrslimits, bool throwp) {

144

145

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)

155 + "km, "

156 + Utility::str((maxeasting_[ind] + slop)/1000)

157 + "km]");

158 }

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)

166 + "km, "

167 + Utility::str((maxnorthing_[ind] + slop)/1000)

168 + "km]");

169 }

170 return true;

171 }

172

174 int zoneout, bool northpout, real& xout, real& yout,

175 int& zone) {

176 bool northp = northpin;

177 if (zonein != zoneout) {

178

179 real lat, lon;

181

182 real x, y;

183 int zone1;

186 ? zonein : zoneout);

187 if (zone1 == 0 && northp != northpout)

189 ("Attempt to transfer UPS coordinates between hemispheres");

190 zone = zone1;

191 xout = x;

192 yout = y;

193 } else {

194 if (zoneout == 0 && northp != northpout)

196 ("Attempt to transfer UPS coordinates between hemispheres");

197 zone = zoneout;

198 xout = xin;

199 yout = yin;

200 }

201 if (northp != northpout)

202

203 yout += (northpout ? -1 : 1) * MGRS::utmNshift_;

204 return;

205 }

206

208 {

209 unsigned zlen = unsigned(zonestr.size());

210 if (zlen == 0)

212

213 if (zlen > 7)

214 throw GeographicErr("More than 7 characters in zone specification "

215 + zonestr);

216

217 const char* c = zonestr.c_str();

218 char* q;

219 int zone1 = strtol(c, &q, 10);

220

221

222 if (zone1 == UPS) {

223 if (!(q == c))

224

225 throw GeographicErr("Illegal zone 0 in " + zonestr +

226 ", use just the hemisphere for UPS");

229 + " not in range [1, 60]");

230 else if (!isdigit(zonestr[0]))

231 throw GeographicErr("Must use unsigned number for zone "

233 else if (q - c > 2)

234 throw GeographicErr("More than 2 digits use to specify zone "

236

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")) {

242 northp = false;

243 return;

244 }

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");

249 zone = zone1;

250 northp = northp1;

251 }

252

255 return string(abbrev ? "inv" : "invalid");

258 + " not in range [0, 60]");

259 ostringstream os;

260 if (zone != UPS)

261 os << setfill('0') << setw(2) << zone;

262 if (abbrev)

263 os << (northp ? 'n' : 's');

264 else

265 os << (northp ? "north" : "south");

266 return os.str();

267 }

268

270 northp = false;

271 if (epsg >= epsg01N && epsg <= epsg60N) {

272 zone = (epsg - epsg01N) + MINUTMZONE;

273 northp = true;

274 } else if (epsg == epsgN) {

275 zone = UPS;

276 northp = true;

277 } else if (epsg >= epsg01S && epsg <= epsg60S) {

278 zone = (epsg - epsg01S) + MINUTMZONE;

279 } else if (epsg == epsgS) {

280 zone = UPS;

281 } else {

283 }

284 }

285

287 int epsg = -1;

288 if (zone == UPS)

289 epsg = epsgS;

291 epsg = (zone - MINUTMZONE) + epsg01S;

292 if (epsg >= 0 && northp)

293 epsg += epsgN - epsgS;

294 return epsg;

295 }

296

298

299}

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)

Definition UTMUPS.cpp:286

static int StandardZone(real lat, real lon, int setzone=STANDARD)

Definition UTMUPS.cpp:43

static std::string EncodeZone(int zone, bool northp, bool abbrev=true)

Definition UTMUPS.cpp:253

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 UTMUPS.cpp:65

static void DecodeEPSG(int epsg, int &zone, bool &northp)

Definition UTMUPS.cpp:269

static void Reverse(int zone, bool northp, real x, real y, real &lat, real &lon, real &gamma, real &k, bool mgrslimits=false)

Definition UTMUPS.cpp:119

static Math::real UTMShift()

Definition UTMUPS.cpp:297

static void Transfer(int zonein, bool northpin, real xin, real yin, int zoneout, bool northpout, real &xout, real &yout, int &zone)

Definition UTMUPS.cpp:173

static void DecodeZone(const std::string &zonestr, int &zone, bool &northp)

Definition UTMUPS.cpp:207

Some utility routines for GeographicLib.

static std::string str(T x, int p=-1)

Namespace for GeographicLib.