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