GeographicLib: Geohash.cpp Source File

GeographicLib 2.7

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
13namespace 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