15 # pragma warning (disable: 4127)
22 const char*
const DMS::hemispheres_ =
"SNWE";
23 const char*
const DMS::signs_ =
"-+";
24 const char*
const DMS::digits_ =
"0123456789";
25 const char*
const DMS::dmsindicators_ =
"D'\":";
26 const char*
const DMS::components_[] = {
"degrees",
"minutes",
"seconds"};
92 replace(dmsa,
"\xc2\xb0",
'd' );
93 replace(dmsa,
"\xc2\xba",
'd' );
94 replace(dmsa,
"\xe2\x81\xb0",
'd' );
95 replace(dmsa,
"\xcb\x9a",
'd' );
96 replace(dmsa,
"\xe2\x88\x98",
'd' );
98 replace(dmsa,
"\xe2\x80\xb2",
'\'');
99 replace(dmsa,
"\xe2\x80\xb5",
'\'');
100 replace(dmsa,
"\xc2\xb4",
'\'');
101 replace(dmsa,
"\xe2\x80\x98",
'\'');
102 replace(dmsa,
"\xe2\x80\x99",
'\'');
103 replace(dmsa,
"\xe2\x80\x9b",
'\'');
104 replace(dmsa,
"\xca\xb9",
'\'');
105 replace(dmsa,
"\xcb\x8a",
'\'');
106 replace(dmsa,
"\xcb\x8b",
'\'');
108 replace(dmsa,
"\xe2\x80\xb3",
'"' );
109 replace(dmsa,
"\xe2\x80\xb6",
'"' );
110 replace(dmsa,
"\xcb\x9d",
'"' );
111 replace(dmsa,
"\xe2\x80\x9c",
'"' );
112 replace(dmsa,
"\xe2\x80\x9d",
'"' );
113 replace(dmsa,
"\xe2\x80\x9f",
'"' );
114 replace(dmsa,
"\xca\xba",
'"' );
116 replace(dmsa,
"\xe2\x9e\x95",
'+' );
117 replace(dmsa,
"\xe2\x81\xa4",
'+' );
119 replace(dmsa,
"\xe2\x80\x90",
'-' );
120 replace(dmsa,
"\xe2\x80\x91",
'-' );
121 replace(dmsa,
"\xe2\x80\x93",
'-' );
122 replace(dmsa,
"\xe2\x80\x94",
'-' );
123 replace(dmsa,
"\xe2\x88\x92",
'-' );
124 replace(dmsa,
"\xe2\x9e\x96",
'-' );
126 replace(dmsa,
"\xc2\xa0",
'\0');
127 replace(dmsa,
"\xe2\x80\x87",
'\0');
128 replace(dmsa,
"\xe2\x80\x89",
'\0');
129 replace(dmsa,
"\xe2\x80\x8a",
'\0');
130 replace(dmsa,
"\xe2\x80\x8b",
'\0');
131 replace(dmsa,
"\xe2\x80\xaf",
'\0');
132 replace(dmsa,
"\xe2\x81\xa3",
'\0');
134 replace(dmsa,
"\xb0",
'd' );
135 replace(dmsa,
"\xba",
'd' );
136 replace(dmsa,
"*",
'd' );
137 replace(dmsa,
"`",
'\'');
138 replace(dmsa,
"\xb4",
'\'');
146 replace(dmsa,
"\xa0",
'\0');
147 replace(dmsa,
"''",
'"' );
150 end = unsigned(dmsa.size());
151 while (beg < end && isspace(dmsa[beg]))
153 while (beg < end && isspace(dmsa[end - 1]))
160 for (string::size_type p = beg, pb; p < end; p = pb, ++i) {
161 string::size_type pa = p;
169 pb = min(dmsa.find_first_of(signs_, pa), end);
171 v += InternalDecode(dmsa.substr(p, pb - p), ind2);
174 else if (!(ind2 == NONE || ind1 == ind2))
175 throw GeographicErr(
"Incompatible hemisphere specifier in " +
176 dmsa.substr(beg, pb - beg));
180 dmsa.substr(beg, end - beg));
185 Math::real DMS::InternalDecode(
const string& dmsa, flag& ind) {
186 const int maxcomponents = 3;
192 end = unsigned(dmsa.size());
195 if (end > beg && (k =
Utility::lookup(hemispheres_, dmsa[beg])) >= 0) {
196 ind1 = (k / 2) ? LONGITUDE : LATITUDE;
197 sign = k % 2 ? 1 : -1;
200 if (end > beg && (k =
Utility::lookup(hemispheres_, dmsa[end-1])) >= 0) {
203 if (toupper(dmsa[beg - 1]) == toupper(dmsa[end - 1]))
204 errormsg =
"Repeated hemisphere indicators "
206 +
" in " + dmsa.substr(beg - 1, end - beg + 1);
208 errormsg =
"Contradictory hemisphere indicators "
211 + dmsa.substr(beg - 1, end - beg + 1);
214 ind1 = (k / 2) ? LONGITUDE : LATITUDE;
215 sign = k % 2 ? 1 : -1;
226 errormsg =
"Empty or incomplete DMS string " + dmsa;
229 real ipieces[maxcomponents] = {0, 0, 0};
230 real fpieces[maxcomponents] = {0, 0, 0};
234 unsigned ncurrent = 0, p = beg;
235 bool pointseen =
false;
236 unsigned digcount = 0, intcount = 0;
244 icurrent = 10 * icurrent + k;
247 }
else if (x ==
'.') {
249 errormsg =
"Multiple decimal points in "
250 + dmsa.substr(beg, end - beg);
256 if (k >= maxcomponents) {
258 errormsg =
"Illegal for : to appear at the end of " +
259 dmsa.substr(beg, end - beg);
264 if (
unsigned(k) == npiece - 1) {
265 errormsg =
"Repeated " + string(components_[k]) +
266 " component in " + dmsa.substr(beg, end - beg);
268 }
else if (
unsigned(k) < npiece) {
269 errormsg = string(components_[k]) +
" component follows "
270 + string(components_[npiece - 1]) +
" component in "
271 + dmsa.substr(beg, end - beg);
275 errormsg =
"Missing numbers in " + string(components_[k]) +
276 " component of " + dmsa.substr(beg, end - beg);
280 istringstream s(dmsa.substr(p - intcount - digcount - 1,
281 intcount + digcount));
285 ipieces[k] = icurrent;
286 fpieces[k] = icurrent + fcurrent;
289 if (npiece >= maxcomponents) {
290 errormsg =
"More than 3 DMS components in "
291 + dmsa.substr(beg, end - beg);
294 icurrent = fcurrent = 0;
295 ncurrent = digcount = intcount = 0;
298 errormsg =
"Internal sign in DMS string "
299 + dmsa.substr(beg, end - beg);
302 errormsg =
"Illegal character " +
Utility::str(x) +
" in DMS string "
303 + dmsa.substr(beg, end - beg);
307 if (!errormsg.empty())
310 if (npiece >= maxcomponents) {
311 errormsg =
"Extra text following seconds in DMS string "
312 + dmsa.substr(beg, end - beg);
316 errormsg =
"Missing numbers in trailing component of "
317 + dmsa.substr(beg, end - beg);
321 istringstream s(dmsa.substr(p - intcount - digcount,
322 intcount + digcount));
326 ipieces[npiece] = icurrent;
327 fpieces[npiece] = icurrent + fcurrent;
329 if (pointseen && digcount == 0) {
330 errormsg =
"Decimal point in non-terminal component of "
331 + dmsa.substr(beg, end - beg);
335 if (ipieces[1] >= 60 || fpieces[1] > 60 ) {
337 +
" not in range [0, 60)";
340 if (ipieces[2] >= 60 || fpieces[2] > 60) {
342 +
" not in range [0, 60)";
350 (60*(60*fpieces[0] + fpieces[1]) + fpieces[2]) / 3600 :
352 (60*fpieces[0] + fpieces[1]) / 60 : fpieces[0] ) );
354 real val = Utility::nummatch<real>(dmsa);
356 throw GeographicErr(errormsg);
363 real& lat, real& lon,
367 a = Decode(stra, ia);
368 b = Decode(strb, ib);
369 if (ia == NONE && ib == NONE) {
371 ia = longfirst ? LONGITUDE : LATITUDE;
372 ib = longfirst ? LATITUDE : LONGITUDE;
373 }
else if (ia == NONE)
374 ia =
flag(LATITUDE + LONGITUDE - ib);
376 ib =
flag(LATITUDE + LONGITUDE - ia);
379 + strb +
" interpreted as "
380 + (ia == LATITUDE ?
"latitudes" :
"longitudes"));
382 lat1 = ia == LATITUDE ? a : b,
383 lon1 = ia == LATITUDE ? b : a;
386 +
"d not in [-90d, 90d]");
393 real ang = Decode(angstr, ind);
396 +
" includes a hemisphere, N/E/W/S");
402 real azi = Decode(azistr, ind);
405 +
" has a latitude hemisphere, N/S");
413 if (!isfinite(angle))
414 return angle < 0 ? string(
"-inf") :
415 (angle > 0 ? string(
"inf") : string(
"nan"));
421 for (
unsigned i = 0; i < unsigned(trailing); ++i)
423 for (
unsigned i = 0; i < prec; ++i)
426 angle -= floor(angle/360) * 360;
427 int sign = angle < 0 ? -1 : 1;
433 idegree = floor(angle),
434 fdegree = (angle - idegree) * scale +
real(0.5);
437 real f = floor(fdegree);
438 fdegree = (f == fdegree && fmod(f,
real(2)) == 1) ? f - 1 : f;
445 real pieces[3] = {fdegree, 0, 0};
446 for (
unsigned i = 1; i <= unsigned(trailing); ++i) {
448 ip = floor(pieces[i - 1]),
449 fp = pieces[i - 1] - ip;
453 pieces[0] += idegree;
455 s << fixed << setfill(
'0');
456 if (ind == NONE && sign < 0)
461 s << setw(1 + min(
int(ind), 2) + prec + (prec ? 1 : 0));
467 s << setw(1 + min(
int(ind), 2));
469 << (dmssep ? dmssep : char(tolower(dmsindicators_[0])));
472 s << setw(2 + prec + (prec ? 1 : 0)) <<
Utility::str(pieces[1], prec);
474 s << char(tolower(dmsindicators_[1]));
479 << (dmssep ? dmssep : char(tolower(dmsindicators_[1])))
480 << setw(2 + prec + (prec ? 1 : 0)) <<
Utility::str(pieces[2], prec);
482 s << char(tolower(dmsindicators_[2]));
488 if (ind != NONE && ind != AZIMUTH)
489 s << hemispheres_[(ind == LATITUDE ? 0 : 2) + (sign < 0 ? 0 : 1)];
Header for GeographicLib::DMS class.
GeographicLib::Math::real real
Header for GeographicLib::Utility class.
static Math::real DecodeAzimuth(const std::string &azistr)
static Math::real DecodeAngle(const std::string &angstr)
static std::string Encode(real angle, component trailing, unsigned prec, flag ind=NONE, char dmssep=char(0))
static void DecodeLatLon(const std::string &dmsa, const std::string &dmsb, real &lat, real &lon, bool longfirst=false)
static Math::real Decode(const std::string &dms, flag &ind)
Exception handling for GeographicLib.
static T AngNormalize(T x)
static int extra_digits()
static int lookup(const std::string &s, char c)
static std::string str(T x, int p=-1)
Namespace for GeographicLib.