You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

gauss.cpp 3.1 kB

2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. #include "util/util.h"
  2. #include "geo/private/math/math.h"
  3. #include "geo/private/coord/gauss.h"
  4. namespace ns
  5. {
  6. namespace geo
  7. {
  8. // BeiJing54 -> Gauss-Kruger
  9. const char* Wgs84Proj4Init = "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs";
  10. GaussConverter::GaussConverter(double centerMeridian, double bandWidth, double pm)
  11. : m_pm(pm), m_bandWidth(bandWidth)
  12. {
  13. m_ctx = pj_ctx_alloc();
  14. // m_ctx=proj_context_create();
  15. m_beiJing54Proj = pj_init_plus_ctx(m_ctx, Wgs84Proj4Init);
  16. m_centralMeridian = unifyCentralMeridian(centerMeridian);
  17. char str[128] = {0};
  18. sprintf(str,
  19. "+proj=tmerc +ellps=WGS84 +lon_0=%.2fe +x_0=500000 +y_0=0 +lon_wrap=180 +units=m +k=1.0",
  20. m_centralMeridian);
  21. m_centralProj = pj_init_plus_ctx(m_ctx, str);
  22. }
  23. GaussConverter::~GaussConverter()
  24. {
  25. if (m_centralProj)
  26. pj_free(m_centralProj);
  27. if (m_beiJing54Proj)
  28. pj_free(m_beiJing54Proj);
  29. if (m_ctx)
  30. pj_ctx_free(m_ctx);
  31. // proj_context_destroy(m_ctx);
  32. }
  33. int GaussConverter::reset(double centerLon, double bandWidth, double pm)
  34. {
  35. if (are_equal(bandWidth, 0) && are_equal(pm, 0))
  36. {
  37. double c = unifyCentralMeridian(centerLon);
  38. if (are_equal(c, m_centralMeridian))
  39. return 0;
  40. }
  41. else
  42. {
  43. m_bandWidth = bandWidth;
  44. m_pm = pm;
  45. }
  46. pj_free(m_centralProj);
  47. m_centralMeridian = unifyCentralMeridian(centerLon);
  48. char str[128] = {0};
  49. sprintf(
  50. str,
  51. "+proj=tmerc +ellps=WGS84 +lon_0=%.2fe +x_0=500000 +y_0=0 +lon_wrap=180 +units=m +k=1.0",
  52. m_centralMeridian);
  53. m_centralProj = pj_init_plus_ctx(m_ctx, str);
  54. return 0;
  55. }
  56. bool GaussConverter::reset(std::string pjParamsStr)
  57. {
  58. pj_free(m_centralProj);
  59. m_centralProj = pj_init_plus_ctx(m_ctx, pjParamsStr.c_str());
  60. if (m_centralProj)
  61. {
  62. return calcCenterLon(pjParamsStr, m_centralMeridian);
  63. }
  64. return false;
  65. }
  66. bool GaussConverter::calcCenterLon(std::string params, double& cenLon)
  67. {
  68. std::vector<std::string> subs = util::split(params, " ");
  69. for (auto& s : subs)
  70. {
  71. if (util::startswith(s, "+lon_0="))
  72. {
  73. std::string numStr = s.substr(7);
  74. numStr = util::trim(numStr, " ");
  75. if (util::isNum(numStr))
  76. {
  77. cenLon = std::stod(numStr.c_str());
  78. return true;
  79. }
  80. }
  81. }
  82. return false;
  83. }
  84. double GaussConverter::unifyCentralMeridian(double lon)
  85. {
  86. m_zone = static_cast<unsigned>(std::floor((lon - m_pm) / m_bandWidth)) + 1;
  87. return getCentralMeridian(m_zone);
  88. }
  89. PointD GaussConverter::wgs842Gauss(const PointD& p) const
  90. {
  91. double x = p.x * DEG_TO_RAD;
  92. double y = p.y * DEG_TO_RAD;
  93. double z = 0.0;
  94. pj_transform(m_beiJing54Proj, m_centralProj, 1, 1, &x, &y, &z);
  95. return PointD(x, y, p.z);
  96. }
  97. PointD GaussConverter::gauss2Wgs84(const PointD& p) const
  98. {
  99. double x = p.x, y = p.y, z = 0.0;
  100. pj_transform(m_centralProj, m_beiJing54Proj, 1, 1, &x, &y, &z);
  101. return PointD(x * RAD_TO_DEG, y * RAD_TO_DEG, p.z);
  102. }
  103. } // namespace geo
  104. } // namespace ns