GeographicLib: GARS.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 GARS::digits_ = "0123456789";
18 const char* const GARS::letters_ = "ABCDEFGHJKLMNPQRSTUVWXYZ";
19
20 void GARS::Forward(real lat, real lon, int prec, string& gars) {
21 using std::isnan;
24 + "d not in [-" + to_string(Math::qd)
25 + "d, " + to_string(Math::qd) + "d]");
26 if (isnan(lat) || isnan(lon)) {
27 gars = "INVALID";
28 return;
29 }
31 if (lon == Math::hd) lon = -Math::hd;
32 if (lat == Math::qd) lat *= (1 - numeric_limits::epsilon() / 2);
33 prec = max(0, min(int(maxprec_), prec));
34 int
35 x = int(floor(lon * m_)) - lonorig_ * m_,
36 y = int(floor(lat * m_)) - latorig_ * m_,
37 ilon = x * mult1_ / m_,
38 ilat = y * mult1_ / m_;
39 x -= ilon * m_ / mult1_; y -= ilat * m_ / mult1_;
40 char gars1[maxlen_];
41 ++ilon;
42 for (int c = lonlen_; c--;) {
43 gars1[c] = digits_[ ilon % baselon_]; ilon /= baselon_;
44 }
45 for (int c = latlen_; c--;) {
46 gars1[lonlen_ + c] = letters_[ilat % baselat_]; ilat /= baselat_;
47 }
48 if (prec > 0) {
49 ilon = x / mult3_; ilat = y / mult3_;
50 gars1[baselen_] = digits_[mult2_ * (mult2_ - 1 - ilat) + ilon + 1];
51 if (prec > 1) {
52 ilon = x % mult3_; ilat = y % mult3_;
53 gars1[baselen_ + 1] = digits_[mult3_ * (mult3_ - 1 - ilat) + ilon + 1];
54 }
55 }
56 gars.resize(baselen_ + prec);
57 copy(gars1, gars1 + baselen_ + prec, gars.begin());
58 }
59
60 void GARS::Reverse(const string& gars, real& lat, real& lon,
61 int& prec, bool centerp) {
62 int len = int(gars.length());
63 if (len >= 3 &&
64 toupper(gars[0]) == 'I' &&
65 toupper(gars[1]) == 'N' &&
66 toupper(gars[2]) == 'V') {
68 return;
69 }
70 if (len < baselen_)
71 throw GeographicErr("GARS must have at least 5 characters " + gars);
72 if (len > maxlen_)
73 throw GeographicErr("GARS can have at most 7 characters " + gars);
74 int prec1 = len - baselen_;
75 int ilon = 0;
76 for (int c = 0; c < lonlen_; ++c) {
78 if (k < 0)
79 throw GeographicErr("GARS must start with 3 digits " + gars);
80 ilon = ilon * baselon_ + k;
81 }
82 if (!(ilon >= 1 && ilon <= 2 * Math::td))
83 throw GeographicErr("Initial digits in GARS must lie in [1, 720] " +
84 gars);
85 --ilon;
86 int ilat = 0;
87 for (int c = 0; c < latlen_; ++c) {
89 if (k < 0)
90 throw GeographicErr("Illegal letters in GARS " + gars.substr(3,2));
91 ilat = ilat * baselat_ + k;
92 }
94 throw GeographicErr("GARS letters must lie in [AA, QZ] " + gars);
95 real
96 unit = mult1_,
97 lat1 = ilat + latorig_ * unit,
98 lon1 = ilon + lonorig_ * unit;
99 if (prec1 > 0) {
101 if (!(k >= 1 && k <= mult2_ * mult2_))
102 throw GeographicErr("6th character in GARS must [1, 4] " + gars);
103 --k;
104 unit *= mult2_;
105 lat1 = mult2_ * lat1 + (mult2_ - 1 - k / mult2_);
106 lon1 = mult2_ * lon1 + (k % mult2_);
107 if (prec1 > 1) {
109 if (!(k >= 1 ))
110 throw GeographicErr("7th character in GARS must [1, 9] " + gars);
111 --k;
112 unit *= mult3_;
113 lat1 = mult3_ * lat1 + (mult3_ - 1 - k / mult3_);
114 lon1 = mult3_ * lon1 + (k % mult3_);
115 }
116 }
117 if (centerp) {
118 unit *= 2; lat1 = 2 * lat1 + 1; lon1 = 2 * lon1 + 1;
119 }
120 lat = lat1 / unit;
121 lon = lon1 / unit;
122 prec = prec1;
123 }
124
125}
Header for GeographicLib::GARS class.
Header for GeographicLib::Utility class.
static void Reverse(const std::string &gars, real &lat, real &lon, int &prec, bool centerp=true)
Definition GARS.cpp:60
static void Forward(real lat, real lon, int prec, std::string &gars)
Definition GARS.cpp:20
Exception handling for GeographicLib.
static constexpr int qd
degrees per quarter turn
static T AngNormalize(T x)
static constexpr int td
degrees per turn
static constexpr int hd
degrees per half turn
static int lookup(const std::string &s, char c)
static std::string str(T x, int p=-1)
Namespace for GeographicLib.