GARS.hpp 5.1 KB

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