GeographicLib  1.49
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-2017) <charles@karney.com> 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 #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 
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(); // 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(180), -(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(360), -(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::abs; res = abs(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::abs;
147  latres = abs(latres);
148  lonres = abs(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
static Math::real LongitudeResolution(int len)
Definition: Geohash.hpp:113
#define GEOGRAPHICLIB_EXPORT
Definition: Constants.hpp:91
GeographicLib::Math::real real
Definition: GeodSolve.cpp:31
static int GeohashLength(real res)
Definition: Geohash.hpp:128
Conversions for geohashes.
Definition: Geohash.hpp:40
Namespace for GeographicLib.
Definition: Accumulator.cpp:12
static int GeohashLength(real latres, real lonres)
Definition: Geohash.hpp:145
static int DecimalPrecision(int len)
Definition: Geohash.hpp:167
Header for GeographicLib::Constants class.
static Math::real LatitudeResolution(int len)
Definition: Geohash.hpp:99