1 /** 2 * \file GARS.hpp 3 * \brief Header for GeographicLib::GARS class 4 * 5 * Copyright (c) Charles Karney (2015-2021) <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_GARS_HPP) 11 #define GEOGRAPHICLIB_GARS_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 the Global Area Reference System (GARS) 25 * 26 * The Global Area Reference System is described in 27 * - https://en.wikipedia.org/wiki/Global_Area_Reference_System 28 * - https://earth-info.nga.mil/index.php?dir=coordsys&action=coordsys#tab_gars 29 * . 30 * It provides a compact string representation of a geographic area 31 * (expressed as latitude and longitude). The classes Georef and Geohash 32 * implement similar compact representations. 33 * 34 * Example of use: 35 * \include example-GARS.cpp 36 **********************************************************************/ 37 38 class GEOGRAPHICLIB_EXPORT GARS { 39 private: 40 typedef Math::real real; 41 static const char* const digits_; 42 static const char* const letters_; 43 enum { 44 lonorig_ = -180, // Origin for longitude 45 latorig_ = -90, // Origin for latitude 46 baselon_ = 10, // Base for longitude tiles 47 baselat_ = 24, // Base for latitude tiles 48 lonlen_ = 3, 49 latlen_ = 2, 50 baselen_ = lonlen_ + latlen_, 51 mult1_ = 2, // base precision = 1/2 degree 52 mult2_ = 2, // 6th char gives 2x more precision 53 mult3_ = 3, // 7th char gives 3x more precision 54 m_ = mult1_ * mult2_ * mult3_, 55 maxprec_ = 2, 56 maxlen_ = baselen_ + maxprec_, 57 }; 58 GARS(); // Disable constructor 59 60 public: 61 62 /** 63 * Convert from geographic coordinates to GARS. 64 * 65 * @param[in] lat latitude of point (degrees). 66 * @param[in] lon longitude of point (degrees). 67 * @param[in] prec the precision of the resulting GARS. 68 * @param[out] gars the GARS string. 69 * @exception GeographicErr if \e lat is not in [−90°, 70 * 90°]. 71 * @exception std::bad_alloc if memory for \e gars can't be allocated. 72 * 73 * \e prec specifies the precision of \e gars as follows: 74 * - \e prec = 0 (min), 30' precision, e.g., 006AG; 75 * - \e prec = 1, 15' precision, e.g., 006AG3; 76 * - \e prec = 2 (max), 5' precision, e.g., 006AG39. 77 * 78 * If \e lat or \e lon is NaN, then \e gars is set to "INVALID". 79 **********************************************************************/ 80 static void Forward(real lat, real lon, int prec, std::string& gars); 81 82 /** 83 * Convert from GARS to geographic coordinates. 84 * 85 * @param[in] gars the GARS. 86 * @param[out] lat latitude of point (degrees). 87 * @param[out] lon longitude of point (degrees). 88 * @param[out] prec the precision of \e gars. 89 * @param[in] centerp if true (the default) return the center of the 90 * \e gars, otherwise return the south-west corner. 91 * @exception GeographicErr if \e gars is illegal. 92 * 93 * The case of the letters in \e gars is ignored. \e prec is in the range 94 * [0, 2] and gives the precision of \e gars as follows: 95 * - \e prec = 0 (min), 30' precision, e.g., 006AG; 96 * - \e prec = 1, 15' precision, e.g., 006AG3; 97 * - \e prec = 2 (max), 5' precision, e.g., 006AG39. 98 * 99 * If the first 3 characters of \e gars are "INV", then \e lat and \e lon 100 * are set to NaN and \e prec is unchanged. 101 **********************************************************************/ 102 static void Reverse(const std::string& gars, real& lat, real& lon, 103 int& prec, bool centerp = true); 104 105 /** 106 * The angular resolution of a GARS. 107 * 108 * @param[in] prec the precision of the GARS. 109 * @return the latitude-longitude resolution (degrees). 110 * 111 * Internally, \e prec is first put in the range [0, 2]. 112 **********************************************************************/ Resolution(int prec)113 static Math::real Resolution(int prec) { 114 return 1/real(prec <= 0 ? mult1_ : (prec == 1 ? mult1_ * mult2_ : 115 mult1_ * mult2_ * mult3_)); 116 } 117 118 /** 119 * The GARS precision required to meet a given geographic resolution. 120 * 121 * @param[in] res the minimum of resolution in latitude and longitude 122 * (degrees). 123 * @return GARS precision. 124 * 125 * The returned length is in the range [0, 2]. 126 **********************************************************************/ Precision(real res)127 static int Precision(real res) { 128 using std::abs; res = abs(res); 129 for (int prec = 0; prec < maxprec_; ++prec) 130 if (Resolution(prec) <= res) 131 return prec; 132 return maxprec_; 133 } 134 135 }; 136 137 } // namespace GeographicLib 138 139 #if defined(_MSC_VER) 140 # pragma warning (pop) 141 #endif 142 143 #endif // GEOGRAPHICLIB_GARS_HPP 144