GeographicLib  1.43
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) <charles@karney.com> and licensed under
6  * the MIT/X11 License. For more information, see
7  * http://geographiclib.sourceforge.net/
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/ (this link is broken as of 2012-12-11)
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.
34  *
35  * Example of use:
36  * \include example-Geohash.cpp
37  **********************************************************************/
38 
40  private:
41  typedef Math::real real;
42  static const int maxlen_ = 18;
43  static const unsigned long long mask_ = 1ULL << 45;
44  static const int decprec_[];
45  static inline real shift() {
46  using std::pow; static const real shift = pow(real(2), 45);
47  return shift;
48  }
49  static inline real loneps() {
50  static const real loneps = 180 / shift();
51  return loneps;
52  }
53  static inline real lateps() {
54  static const real lateps = 90 / shift();
55  return lateps;
56  }
57  static const real lateps_;
58  static const std::string lcdigits_;
59  static const std::string ucdigits_;
60  Geohash(); // Disable constructor
61 
62  public:
63 
64  /**
65  * Convert from geographic coordinates to a geohash.
66  *
67  * @param[in] lat latitude of point (degrees).
68  * @param[in] lon longitude of point (degrees).
69  * @param[in] len the length of the resulting geohash.
70  * @param[out] geohash the geohash.
71  * @exception GeographicErr if \e la is not in [&minus;90&deg;,
72  * 90&deg;].
73  * @exception GeographicErr if \e lon is not in [&minus;540&deg;,
74  * 540&deg;).
75  * @exception std::bad_alloc if memory for \e geohash can't be allocated.
76  *
77  * Internally, \e len is first put in the range [0, 18].
78  *
79  * If \e lat or \e lon is NaN, the returned geohash is "nan".
80  **********************************************************************/
81  static void Forward(real lat, real lon, int len, std::string& geohash);
82 
83  /**
84  * Convert from a geohash to geographic coordinates.
85  *
86  * @param[in] geohash the geohash.
87  * @param[out] lat latitude of point (degrees).
88  * @param[out] lon longitude of point (degrees).
89  * @param[out] len the length of the geohash.
90  * @param[in] centerp if true (the default) return the center of the
91  * geohash location, otherwise return the south-west corner.
92  * @exception GeographicErr if \e geohash contains illegal characters.
93  *
94  * Only the first 18 characters for \e geohash are considered. The case of
95  * the letters in \e geohash is ignored.
96  *
97  * If the first three characters in \e geohash are "nan", then \e lat and
98  * \e lon are set to NaN.
99  **********************************************************************/
100  static void Reverse(const std::string& geohash, real& lat, real& lon,
101  int& len, bool centerp = true);
102 
103  /**
104  * The latitude resolution of a geohash.
105  *
106  * @param[in] len the length of the geohash.
107  * @return the latitude resolution (degrees).
108  *
109  * Internally, \e len is first put in the range [0, 18].
110  **********************************************************************/
111  static Math::real LatitudeResolution(int len) {
112  len = (std::max)(0, (std::min)(int(maxlen_), len));
113  return 180 * std::pow(0.5, 5 * len / 2);
114  }
115 
116  /**
117  * The longitude resolution of a geohash.
118  *
119  * @param[in] len the length of the geohash.
120  * @return the longitude resolution (degrees).
121  *
122  * Internally, \e len is first put in the range [0, 18].
123  **********************************************************************/
124  static Math::real LongitudeResolution(int len) {
125  len = (std::max)(0, (std::min)(int(maxlen_), len));
126  return 360 * std::pow(0.5, 5 * len - 5 * len / 2);
127  }
128 
129  /**
130  * The geohash length required to meet a given geographic resolution.
131  *
132  * @param[in] res the minimum of resolution in latitude and longitude
133  * (degrees).
134  * @return geohash length.
135  *
136  * The returned length is in the range [0, 18].
137  **********************************************************************/
138  static int GeohashLength(real res) {
139  using std::abs;
140  res = abs(res);
141  for (int len = 0; len < maxlen_; ++len)
142  if (LongitudeResolution(len) <= res)
143  return len;
144  return maxlen_;
145  }
146 
147  /**
148  * The geohash length required to meet a given geographic resolution.
149  *
150  * @param[in] latres the resolution in latitude (degrees).
151  * @param[in] lonres the resolution in longitude (degrees).
152  * @return geohash length.
153  *
154  * The returned length is in the range [0, 18].
155  **********************************************************************/
156  static int GeohashLength(real latres, real lonres) {
157  using std::abs;
158  latres = abs(latres);
159  lonres = abs(lonres);
160  for (int len = 0; len < maxlen_; ++len)
161  if (LatitudeResolution(len) <= latres &&
162  LongitudeResolution(len) <= lonres)
163  return len;
164  return maxlen_;
165  }
166 
167  /**
168  * The decimal geographic precision required to match a given geohash
169  * length. This is the number of digits needed after decimal point in a
170  * decimal degrees representation.
171  *
172  * @param[in] len the length of the geohash.
173  * @return the decimal precision (may be negative).
174  *
175  * Internally, \e len is first put in the range [0, 18]. The returned
176  * decimal precision is in the range [&minus;2, 12].
177  **********************************************************************/
178  static int DecimalPrecision(int len) {
179  using std::floor; using std::log;
180  return -int(floor(log(LatitudeResolution(len))/log(Math::real(10))));
181  }
182 
183  };
184 
185 } // namespace GeographicLib
186 
187 #if defined(_MSC_VER)
188 # pragma warning (pop)
189 #endif
190 
191 #endif // GEOGRAPHICLIB_GEOHASH_HPP
static Math::real LongitudeResolution(int len)
Definition: Geohash.hpp:124
#define GEOGRAPHICLIB_EXPORT
Definition: Constants.hpp:90
GeographicLib::Math::real real
Definition: GeodSolve.cpp:32
static int GeohashLength(real res)
Definition: Geohash.hpp:138
Conversions for geohashes.
Definition: Geohash.hpp:39
Namespace for GeographicLib.
Definition: Accumulator.cpp:12
static int GeohashLength(real latres, real lonres)
Definition: Geohash.hpp:156
static int DecimalPrecision(int len)
Definition: Geohash.hpp:178
Header for GeographicLib::Constants class.
static Math::real LatitudeResolution(int len)
Definition: Geohash.hpp:111