15# pragma warning (disable: 5055)
22 const char*
const Georef::digits_ =
"0123456789";
23 const char*
const Georef::lontile_ =
"ABCDEFGHJKLMNPQRSTUVWXYZ";
24 const char*
const Georef::lattile_ =
"ABCDEFGHJKLM";
25 const char*
const Georef::degrees_ =
"ABCDEFGHJKLMNPQ";
31 +
"d not in [-" + to_string(
Math::qd)
32 +
"d, " + to_string(
Math::qd) +
"d]");
33 if (isnan(lat) || isnan(lon)) {
38 if (lat ==
Math::qd) lat *= (1 - numeric_limits<real>::epsilon() / 2);
39 prec = max(-1, min(
int(maxprec_), prec));
40 if (prec == 1) ++prec;
43 static_assert(numeric_limits<long long>::digits >= 45,
44 "long long not wide enough to store 21600e9");
45 const long long m = 60000000000LL;
47 x = (
long long)(floor(lon * real(m))) - lonorig_ * m,
48 y = (
long long)(floor(lat * real(m))) - latorig_ * m;
49 int ilon = int(x / m);
int ilat = int(y / m);
50 char georef1[maxlen_];
51 georef1[0] = lontile_[ilon / tile_];
52 georef1[1] = lattile_[ilat / tile_];
54 georef1[2] = degrees_[ilon % tile_];
55 georef1[3] = degrees_[ilat % tile_];
57 x -= m * ilon; y -= m * ilat;
58 long long d = (
long long)pow(real(base_), maxprec_ - prec);
60 for (
int c = prec; c--;) {
61 georef1[baselen_ + c ] = digits_[x % base_]; x /= base_;
62 georef1[baselen_ + c + prec] = digits_[y % base_]; y /= base_;
66 georef.resize(baselen_ + 2 * prec);
67 copy(georef1, georef1 + baselen_ + 2 * prec, georef.begin());
71 int& prec,
bool centerp) {
72 int len = int(georef.length());
74 toupper(georef[0]) ==
'I' &&
75 toupper(georef[1]) ==
'N' &&
76 toupper(georef[2]) ==
'V') {
80 if (len < baselen_ - 2)
81 throw GeographicErr(
"Georef must start with at least 2 letters "
83 int prec1 = (2 + len - baselen_) / 2 - 1;
87 throw GeographicErr(
"Bad longitude tile letter in georef " + georef);
88 real lon1 = k + lonorig_ / tile_;
91 throw GeographicErr(
"Bad latitude tile letter in georef " + georef);
92 real lat1 = k + latorig_ / tile_;
98 throw GeographicErr(
"Bad longitude degree letter in georef " + georef);
99 lon1 = lon1 * tile_ + k;
101 throw GeographicErr(
"Missing latitude degree letter in georef "
105 throw GeographicErr(
"Bad latitude degree letter in georef " + georef);
106 lat1 = lat1 * tile_ + k;
108 if (georef.find_first_not_of(digits_, baselen_) != string::npos)
109 throw GeographicErr(
"Non digits in trailing portion of georef "
110 + georef.substr(baselen_));
112 throw GeographicErr(
"Georef must end with an even number of digits "
113 + georef.substr(baselen_));
115 throw GeographicErr(
"Georef needs at least 4 digits for minutes "
116 + georef.substr(baselen_));
117 if (prec1 > maxprec_)
119 +
" digits in georef "
120 + georef.substr(baselen_));
121 for (
int i = 0; i < prec1; ++i) {
122 int m = i ? base_ : 6;
127 if (!(i || (x < m && y < m)))
128 throw GeographicErr(
"Minutes terms in georef must be less than 60 "
129 + georef.substr(baselen_));
136 unit *= 2; lat1 = 2 * lat1 + 1; lon1 = 2 * lon1 + 1;
138 lat = (tile_ * lat1) / unit;
139 lon = (tile_ * lon1) / unit;
Header for GeographicLib::Georef class.
Header for GeographicLib::Utility class.
Exception handling for GeographicLib.
static void Forward(real lat, real lon, int prec, std::string &georef)
static void Reverse(const std::string &georef, real &lat, real &lon, int &prec, bool centerp=true)
static T AngNormalize(T x)
@ qd
degrees per quarter turn
static int lookup(const std::string &s, char c)
static std::string str(T x, int p=-1)
Namespace for GeographicLib.