GeographicLib 2.3

Geohash.hpp
Go to the documentation of this file.
1/**
2 * \file Geohash.hpp
3 * \brief Header 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#if !defined(GEOGRAPHICLIB_GEOHASH_HPP)
11#define GEOGRAPHICLIB_GEOHASH_HPP 1
12
13#include <GeographicLib/Constants.hpp>
14
15#if defined(_MSC_VER)
16// Squelch warnings about dll vs string
17# pragma warning (push)
18# pragma warning (disable: 4251)
19#endif
20
21 namespace GeographicLib {
22
23 /**
24 * \brief Conversions for geohashes
25 *
26 * Geohashes are described in
27 * - https://en.wikipedia.org/wiki/Geohash
28 * - http://geohash.org/
29 * .
30 * They provide a compact string representation of a particular geographic
31 * location (expressed as latitude and longitude), with the property that if
32 * trailing characters are dropped from the string the geographic location
33 * remains nearby. The classes Georef and GARS implement similar compact
34 * representations.
35 *
36 * Example of use:
37 * \include example-Geohash.cpp
38 **********************************************************************/
39
40 class GEOGRAPHICLIB_EXPORT Geohash {
41 private:
42 typedef Math::real real;
43 static const int maxlen_ = 18;
44 static const unsigned long long mask_ = 1ULL << 45;
45 static const char* const lcdigits_;
46 static const char* const ucdigits_;
47 Geohash() = delete; // Disable constructor
48
49 public:
50
51 /**
52 * Convert from geographic coordinates to a geohash.
53 *
54 * @param[in] lat latitude of point (degrees).
55 * @param[in] lon longitude of point (degrees).
56 * @param[in] len the length of the resulting geohash.
57 * @param[out] geohash the geohash.
58 * @exception GeographicErr if \e lat is not in [&minus;90&deg;,
59 * 90&deg;].
60 * @exception std::bad_alloc if memory for \e geohash can't be allocated.
61 *
62 * Internally, \e len is first put in the range [0, 18]. (\e len = 18
63 * provides approximately 1&mu;m precision.)
64 *
65 * If \e lat or \e lon is NaN, the returned geohash is "invalid".
66 **********************************************************************/
67 static void Forward(real lat, real lon, int len, std::string& geohash);
68
69 /**
70 * Convert from a geohash to geographic coordinates.
71 *
72 * @param[in] geohash the geohash.
73 * @param[out] lat latitude of point (degrees).
74 * @param[out] lon longitude of point (degrees).
75 * @param[out] len the length of the geohash.
76 * @param[in] centerp if true (the default) return the center of the
77 * geohash location, otherwise return the south-west corner.
78 * @exception GeographicErr if \e geohash contains illegal characters.
79 *
80 * Only the first 18 characters for \e geohash are considered. (18
81 * characters provides approximately 1&mu;m precision.) The case of the
82 * letters in \e geohash is ignored.
83 *
84 * If the first 3 characters of \e geohash are "inv", then \e lat and \e
85 * lon are set to NaN and \e len is unchanged. ("nan" is treated
86 * similarly.)
87 **********************************************************************/
88 static void Reverse(const std::string& geohash, real& lat, real& lon,
89 int& len, bool centerp = true);
90
91 /**
92 * The latitude resolution of a geohash.
93 *
94 * @param[in] len the length of the geohash.
95 * @return the latitude resolution (degrees).
96 *
97 * Internally, \e len is first put in the range [0, 18].
98 **********************************************************************/
99 static Math::real LatitudeResolution(int len) {
100 using std::ldexp;
101 len = (std::max)(0, (std::min)(int(maxlen_), len));
102 return ldexp(real(Math::hd), -(5 * len / 2));
103 }
104
105 /**
106 * The longitude resolution of a geohash.
107 *
108 * @param[in] len the length of the geohash.
109 * @return the longitude resolution (degrees).
110 *
111 * Internally, \e len is first put in the range [0, 18].
112 **********************************************************************/
113 static Math::real LongitudeResolution(int len) {
114 using std::ldexp;
115 len = (std::max)(0, (std::min)(int(maxlen_), len));
116 return ldexp(real(Math::td), -(5 * len - 5 * len / 2));
117 }
118
119 /**
120 * The geohash length required to meet a given geographic resolution.
121 *
122 * @param[in] res the minimum of resolution in latitude and longitude
123 * (degrees).
124 * @return geohash length.
125 *
126 * The returned length is in the range [0, 18].
127 **********************************************************************/
128 static int GeohashLength(real res) {
129 using std::fabs; res = fabs(res);
130 for (int len = 0; len < maxlen_; ++len)
131 if (LongitudeResolution(len) <= res)
132 return len;
133 return maxlen_;
134 }
135
136 /**
137 * The geohash length required to meet a given geographic resolution.
138 *
139 * @param[in] latres the resolution in latitude (degrees).
140 * @param[in] lonres the resolution in longitude (degrees).
141 * @return geohash length.
142 *
143 * The returned length is in the range [0, 18].
144 **********************************************************************/
145 static int GeohashLength(real latres, real lonres) {
146 using std::fabs;
147 latres = fabs(latres);
148 lonres = fabs(lonres);
149 for (int len = 0; len < maxlen_; ++len)
150 if (LatitudeResolution(len) <= latres &&
151 LongitudeResolution(len) <= lonres)
152 return len;
153 return maxlen_;
154 }
155
156 /**
157 * The decimal geographic precision required to match a given geohash
158 * length. This is the number of digits needed after decimal point in a
159 * decimal degrees representation.
160 *
161 * @param[in] len the length of the geohash.
162 * @return the decimal precision (may be negative).
163 *
164 * Internally, \e len is first put in the range [0, 18]. The returned
165 * decimal precision is in the range [&minus;2, 12].
166 **********************************************************************/
167 static int DecimalPrecision(int len) {
168 using std::floor; using std::log;
169 return -int(floor(log(LatitudeResolution(len))/log(Math::real(10))));
170 }
171
172 };
173
174} // namespace GeographicLib
175
176#if defined(_MSC_VER)
177# pragma warning (pop)
178#endif
179
180#endif // GEOGRAPHICLIB_GEOHASH_HPP
Constants.hpp
Header for GeographicLib::Constants class.
GEOGRAPHICLIB_EXPORT
#define GEOGRAPHICLIB_EXPORT
Definition: Constants.hpp:67
real
GeographicLib::Math::real real
Definition: GeodSolve.cpp:29
GeographicLib::Geohash
Conversions for geohashes.
Definition: Geohash.hpp:40
GeographicLib::Geohash::LatitudeResolution
static Math::real LatitudeResolution(int len)
Definition: Geohash.hpp:99
GeographicLib::Geohash::DecimalPrecision
static int DecimalPrecision(int len)
Definition: Geohash.hpp:167
GeographicLib::Geohash::LongitudeResolution
static Math::real LongitudeResolution(int len)
Definition: Geohash.hpp:113
GeographicLib::Geohash::GeohashLength
static int GeohashLength(real latres, real lonres)
Definition: Geohash.hpp:145
GeographicLib::Geohash::GeohashLength
static int GeohashLength(real res)
Definition: Geohash.hpp:128
GeographicLib::Math::real
double real
Definition: Math.hpp:100
GeographicLib::Math::td
@ td
degrees per turn
Definition: Math.hpp:142
GeographicLib::Math::hd
@ hd
degrees per half turn
Definition: Math.hpp:141
GeographicLib
Namespace for GeographicLib.
Definition: Accumulator.cpp:12