GeographicLib
2.7
Toggle main menu visibility
Loading...
Searching...
No Matches
GARS.cpp
Go to the documentation of this file.
1
/**
2
* \file GARS.cpp
3
* \brief Implementation for GeographicLib::GARS class
4
*
5
* Copyright (c) Charles Karney (2015-2022) <karney@alum.mit.edu> and licensed
6
* under the MIT/X11 License. For more information, see
7
* https://geographiclib.sourceforge.io/
8
**********************************************************************/
9
10
#include <
GeographicLib/GARS.hpp
>
11
#include <
GeographicLib/Utility.hpp
>
12
13
namespace
GeographicLib
{
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
if
(fabs(lat) >
Math::qd
)
22
throw
GeographicErr
(
"Latitude "
+
Utility::str
(lat)
23
+
"d not in [-"
+ to_string(
Math::qd
)
24
+
"d, "
+ to_string(
Math::qd
) +
"d]"
);
25
if
(isnan(lat) || isnan(lon)) {
26
gars =
"INVALID"
;
27
return
;
28
}
29
lon =
Math::AngNormalize
(lon);
30
if
(lon ==
Math::hd
) lon = -
Math::hd
;
// lon now in [-180,180)
31
if
(lat ==
Math::qd
) lat *= (1 - numeric_limits<real>::epsilon() / 2);
32
prec = max(0, min(
int
(maxprec_), prec));
33
int
34
x = int(floor(lon * m_)) - lonorig_ * m_,
35
y = int(floor(lat * m_)) - latorig_ * m_,
36
ilon = x * mult1_ / m_,
37
ilat = y * mult1_ / m_;
38
x -= ilon * m_ / mult1_; y -= ilat * m_ / mult1_;
39
char
gars1[maxlen_];
40
++ilon;
41
for
(
int
c = lonlen_; c--;) {
42
gars1[c] = digits_[ ilon % baselon_]; ilon /= baselon_;
43
}
44
for
(
int
c = latlen_; c--;) {
45
gars1[lonlen_ + c] = letters_[ilat % baselat_]; ilat /= baselat_;
46
}
47
if
(prec > 0) {
48
ilon = x / mult3_; ilat = y / mult3_;
49
gars1[baselen_] = digits_[mult2_ * (mult2_ - 1 - ilat) + ilon + 1];
50
if
(prec > 1) {
51
ilon = x % mult3_; ilat = y % mult3_;
52
gars1[baselen_ + 1] = digits_[mult3_ * (mult3_ - 1 - ilat) + ilon + 1];
53
}
54
}
55
gars.resize(baselen_ + prec);
56
copy(gars1, gars1 + baselen_ + prec, gars.begin());
57
}
58
59
void
GARS::Reverse
(
const
string
& gars, real& lat, real& lon,
60
int
& prec,
bool
centerp) {
61
int
len = int(gars.length());
62
if
(len >= 3 &&
63
toupper(gars[0]) ==
'I'
&&
64
toupper(gars[1]) ==
'N'
&&
65
toupper(gars[2]) ==
'V'
) {
66
lat = lon =
Math::NaN
();
67
return
;
68
}
69
if
(len < baselen_)
70
throw
GeographicErr
(
"GARS must have at least 5 characters "
+ gars);
71
if
(len > maxlen_)
72
throw
GeographicErr
(
"GARS can have at most 7 characters "
+ gars);
73
int
prec1 = len - baselen_;
74
int
ilon = 0;
75
for
(
int
c = 0; c < lonlen_; ++c) {
76
int
k =
Utility::lookup
(digits_, gars[c]);
77
if
(k < 0)
78
throw
GeographicErr
(
"GARS must start with 3 digits "
+ gars);
79
ilon = ilon * baselon_ + k;
80
}
81
if
(!(ilon >= 1 && ilon <= 2 *
Math::td
))
82
throw
GeographicErr
(
"Initial digits in GARS must lie in [1, 720] "
+
83
gars);
84
--ilon;
85
int
ilat = 0;
86
for
(
int
c = 0; c < latlen_; ++c) {
87
int
k =
Utility::lookup
(letters_, gars[lonlen_ + c]);
88
if
(k < 0)
89
throw
GeographicErr
(
"Illegal letters in GARS "
+ gars.substr(3,2));
90
ilat = ilat * baselat_ + k;
91
}
92
if
(!(ilat <
Math::td
))
93
throw
GeographicErr
(
"GARS letters must lie in [AA, QZ] "
+ gars);
94
real
95
unit = mult1_,
96
lat1 = ilat + latorig_ * unit,
97
lon1 = ilon + lonorig_ * unit;
98
if
(prec1 > 0) {
99
int
k =
Utility::lookup
(digits_, gars[baselen_]);
100
if
(!(k >= 1 && k <= mult2_ * mult2_))
101
throw
GeographicErr
(
"6th character in GARS must [1, 4] "
+ gars);
102
--k;
103
unit *= mult2_;
104
lat1 = mult2_ * lat1 + (mult2_ - 1 - k / mult2_);
105
lon1 = mult2_ * lon1 + (k % mult2_);
106
if
(prec1 > 1) {
107
k =
Utility::lookup
(digits_, gars[baselen_ + 1]);
108
if
(!(k >= 1
/* && k <= mult3_ * mult3_ */
))
109
throw
GeographicErr
(
"7th character in GARS must [1, 9] "
+ gars);
110
--k;
111
unit *= mult3_;
112
lat1 = mult3_ * lat1 + (mult3_ - 1 - k / mult3_);
113
lon1 = mult3_ * lon1 + (k % mult3_);
114
}
115
}
116
if
(centerp) {
117
unit *= 2; lat1 = 2 * lat1 + 1; lon1 = 2 * lon1 + 1;
118
}
119
lat = lat1 / unit;
120
lon = lon1 / unit;
121
prec = prec1;
122
}
123
124
}
// namespace GeographicLib
GARS.hpp
Header for GeographicLib::GARS class.
Utility.hpp
Header for GeographicLib::Utility class.
GeographicLib::GARS::Reverse
static void Reverse(const std::string &gars, real &lat, real &lon, int &prec, bool centerp=true)
Definition
GARS.cpp:59
GeographicLib::GARS::Forward
static void Forward(real lat, real lon, int prec, std::string &gars)
Definition
GARS.cpp:20
GeographicLib::GeographicErr
Exception handling for GeographicLib.
Definition
Constants.hpp:344
GeographicLib::Math::qd
static constexpr int qd
degrees per quarter turn
Definition
Math.hpp:142
GeographicLib::Math::AngNormalize
static T AngNormalize(T x)
Definition
Math.cpp:69
GeographicLib::Math::td
static constexpr int td
degrees per turn
Definition
Math.hpp:146
GeographicLib::Math::NaN
static T NaN()
Definition
Math.cpp:301
GeographicLib::Math::hd
static constexpr int hd
degrees per half turn
Definition
Math.hpp:145
GeographicLib::Utility::lookup
static int lookup(const std::string &s, char c)
Definition
Utility.cpp:160
GeographicLib::Utility::str
static std::string str(T x, int p=-1)
Definition
Utility.hpp:161
GeographicLib
Namespace for GeographicLib.
Definition
Accumulator.cpp:12
src
GARS.cpp
Generated by
1.17.0