GeographicLib: Georef.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
12
14
15 using namespace std;
16
17 const char* const Georef::digits_ = "0123456789";
18 const char* const Georef::lontile_ = "ABCDEFGHJKLMNPQRSTUVWXYZ";
19 const char* const Georef::lattile_ = "ABCDEFGHJKLM";
20 const char* const Georef::degrees_ = "ABCDEFGHJKLMNPQ";
21
22 void Georef::Forward(real lat, real lon, int prec, string& georef) {
23 using std::isnan;
26 + "d not in [-" + to_string(Math::qd)
27 + "d, " + to_string(Math::qd) + "d]");
28 if (isnan(lat) || isnan(lon)) {
29 georef = "INVALID";
30 return;
31 }
33 if (lat == Math::qd) lat *= (1 - numeric_limits::epsilon() / 2);
34 prec = max(-1, min(int(maxprec_), prec));
35 if (prec == 1) ++prec;
36
37
38 static_assert(numeric_limits::digits >= 45,
39 "long long not wide enough to store 21600e9");
40 const long long m = 60000000000LL;
41 long long
42 x = (long long)(floor(lon * real(m))) - lonorig_ * m,
43 y = (long long)(floor(lat * real(m))) - latorig_ * m;
44 int ilon = int(x / m); int ilat = int(y / m);
45 char georef1[maxlen_];
46 georef1[0] = lontile_[ilon / tile_];
47 georef1[1] = lattile_[ilat / tile_];
48 if (prec >= 0) {
49 georef1[2] = degrees_[ilon % tile_];
50 georef1[3] = degrees_[ilat % tile_];
51 if (prec > 0) {
52 x -= m * ilon; y -= m * ilat;
53 long long d = (long long)pow(real(base_), maxprec_ - prec);
54 x /= d; y /= d;
55 for (int c = prec; c--;) {
56 georef1[baselen_ + c ] = digits_[x % base_]; x /= base_;
57 georef1[baselen_ + c + prec] = digits_[y % base_]; y /= base_;
58 }
59 }
60 }
61 georef.resize(baselen_ + 2 * prec);
62 copy(georef1, georef1 + baselen_ + 2 * prec, georef.begin());
63 }
64
66 int& prec, bool centerp) {
67 int len = int(georef.length());
68 if (len >= 3 &&
69 toupper(georef[0]) == 'I' &&
70 toupper(georef[1]) == 'N' &&
71 toupper(georef[2]) == 'V') {
73 return;
74 }
75 if (len < baselen_ - 2)
76 throw GeographicErr("Georef must start with at least 2 letters "
77 + georef);
78 int prec1 = (2 + len - baselen_) / 2 - 1;
79 int k;
81 if (k < 0)
82 throw GeographicErr("Bad longitude tile letter in georef " + georef);
83 real lon1 = k + lonorig_ / tile_;
85 if (k < 0)
86 throw GeographicErr("Bad latitude tile letter in georef " + georef);
87 real lat1 = k + latorig_ / tile_;
88 real unit = 1;
89 if (len > 2) {
90 unit *= tile_;
92 if (k < 0)
93 throw GeographicErr("Bad longitude degree letter in georef " + georef);
94 lon1 = lon1 * tile_ + k;
95 if (len < 4)
96 throw GeographicErr("Missing latitude degree letter in georef "
97 + georef);
99 if (k < 0)
100 throw GeographicErr("Bad latitude degree letter in georef " + georef);
101 lat1 = lat1 * tile_ + k;
102 if (prec1 > 0) {
103 if (georef.find_first_not_of(digits_, baselen_) != string::npos)
104 throw GeographicErr("Non digits in trailing portion of georef "
105 + georef.substr(baselen_));
106 if (len % 2)
107 throw GeographicErr("Georef must end with an even number of digits "
108 + georef.substr(baselen_));
109 if (prec1 == 1)
110 throw GeographicErr("Georef needs at least 4 digits for minutes "
111 + georef.substr(baselen_));
112 if (prec1 > maxprec_)
114 + " digits in georef "
115 + georef.substr(baselen_));
116 for (int i = 0; i < prec1; ++i) {
117 int m = i ? base_ : 6;
118 unit *= m;
119 int
121 y = Utility::lookup(digits_, georef[baselen_ + i + prec1]);
122 if (!(i || (x < m && y < m)))
123 throw GeographicErr("Minutes terms in georef must be less than 60 "
124 + georef.substr(baselen_));
125 lon1 = m * lon1 + x;
126 lat1 = m * lat1 + y;
127 }
128 }
129 }
130 if (centerp) {
131 unit *= 2; lat1 = 2 * lat1 + 1; lon1 = 2 * lon1 + 1;
132 }
133 lat = (tile_ * lat1) / unit;
134 lon = (tile_ * lon1) / unit;
135 prec = prec1;
136 }
137
138}
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)
Definition Georef.cpp:22
static void Reverse(const std::string &georef, real &lat, real &lon, int &prec, bool centerp=true)
Definition Georef.cpp:65
static constexpr int qd
degrees per quarter turn
static T AngNormalize(T x)
static int lookup(const std::string &s, char c)
static std::string str(T x, int p=-1)
Namespace for GeographicLib.