GeographicLib
2.7
Toggle main menu visibility
Loading...
Searching...
No Matches
Geohash.cpp
Go to the documentation of this file.
1
/**
2
* \file Geohash.cpp
3
* \brief Implementation for GeographicLib::Geohash class
4
*
5
* Copyright (c) Charles Karney (2012-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/Geohash.hpp
>
11
#include <
GeographicLib/Utility.hpp
>
12
13
namespace
GeographicLib
{
14
15
using namespace
std;
16
17
const
char
*
const
Geohash::lcdigits_ =
"0123456789bcdefghjkmnpqrstuvwxyz"
;
18
const
char
*
const
Geohash::ucdigits_ =
"0123456789BCDEFGHJKMNPQRSTUVWXYZ"
;
19
20
void
Geohash::Forward
(real lat, real lon,
int
len,
string
& geohash) {
21
static
const
real shift = ldexp(
real
(1), 45);
22
static
const
real loneps =
Math::hd
/ shift;
23
static
const
real lateps =
Math::qd
/ shift;
24
if
(fabs(lat) >
Math::qd
)
25
throw
GeographicErr
(
"Latitude "
+
Utility::str
(lat)
26
+
"d not in [-"
+ to_string(
Math::qd
)
27
+
"d, "
+ to_string(
Math::qd
) +
"d]"
);
28
if
(isnan(lat) || isnan(lon)) {
29
geohash =
"invalid"
;
30
return
;
31
}
32
if
(lat ==
Math::qd
) lat -= lateps / 2;
33
lon =
Math::AngNormalize
(lon);
34
if
(lon ==
Math::hd
) lon = -
Math::hd
;
// lon now in [-180,180)
35
// lon/loneps in [-2^45,2^45); lon/loneps + shift in [0,2^46)
36
// similarly for lat
37
len = max(0, min(
int
(maxlen_), len));
38
unsigned
long
long
39
ulon = (
unsigned
long
long)(floor(lon/loneps) + shift),
40
ulat = (
unsigned
long
long)(floor(lat/lateps) + shift);
41
char
geohash1[maxlen_];
42
unsigned
byte
= 0;
43
for
(
unsigned
i = 0; i < 5 * unsigned(len);) {
44
if
((i & 1) == 0) {
45
byte
= (
byte
<< 1) +
unsigned
((ulon & mask_) != 0);
46
ulon <<= 1;
47
}
else
{
48
byte
= (
byte
<< 1) +
unsigned
((ulat & mask_) != 0);
49
ulat <<= 1;
50
}
51
++i;
52
if
(i % 5 == 0) {
53
geohash1[(i/5)-1] = lcdigits_[
byte
];
54
byte
= 0;
55
}
56
}
57
geohash.resize(len);
58
copy(geohash1, geohash1 + len, geohash.begin());
59
}
60
61
void
Geohash::Reverse
(
const
string
& geohash, real& lat, real& lon,
62
int
& len,
bool
centerp) {
63
static
const
real shift = ldexp(
real
(1), 45);
64
static
const
real loneps =
Math::hd
/ shift;
65
static
const
real lateps =
Math::qd
/ shift;
66
int
len1 = min(
int
(maxlen_),
int
(geohash.length()));
67
if
(len1 >= 3 &&
68
((toupper(geohash[0]) ==
'I'
&&
69
toupper(geohash[1]) ==
'N'
&&
70
toupper(geohash[2]) ==
'V'
) ||
71
// Check A first because it is not in a standard geohash
72
(toupper(geohash[1]) ==
'A'
&&
73
toupper(geohash[0]) ==
'N'
&&
74
toupper(geohash[2]) ==
'N'
))) {
75
lat = lon =
Math::NaN
();
76
return
;
77
}
78
unsigned
long
long
ulon = 0, ulat = 0;
79
for
(
unsigned
k = 0, j = 0; k < unsigned(len1); ++k) {
80
int
byte
=
Utility::lookup
(ucdigits_, geohash[k]);
81
if
(
byte
< 0)
82
throw
GeographicErr
(
"Illegal character in geohash "
+ geohash);
83
for
(
unsigned
m = 16; m; m >>= 1) {
84
if
(j == 0)
85
ulon = (ulon << 1) +
unsigned
((
byte
& m) != 0);
86
else
87
ulat = (ulat << 1) +
unsigned
((
byte
& m) != 0);
88
j ^= 1;
89
}
90
}
91
ulon <<= 1; ulat <<= 1;
92
if
(centerp) {
93
ulon += 1;
94
ulat += 1;
95
}
96
int
s = 5 * (maxlen_ - len1);
97
ulon <<= (s / 2);
98
ulat <<= s - (s / 2);
99
lon = ulon * loneps -
Math::hd
;
100
lat = ulat * lateps -
Math::qd
;
101
len = len1;
102
}
103
104
}
// namespace GeographicLib
real
GeographicLib::Math::real real
Definition
Geod3Solve.cpp:25
Geohash.hpp
Header for GeographicLib::Geohash class.
Utility.hpp
Header for GeographicLib::Utility class.
GeographicLib::GeographicErr
Exception handling for GeographicLib.
Definition
Constants.hpp:344
GeographicLib::Geohash::Forward
static void Forward(real lat, real lon, int len, std::string &geohash)
Definition
Geohash.cpp:20
GeographicLib::Geohash::Reverse
static void Reverse(const std::string &geohash, real &lat, real &lon, int &len, bool centerp=true)
Definition
Geohash.cpp:61
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::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
Geohash.cpp
Generated by
1.17.0