#include "util/util.h" #include "geo/private/math/math.h" #include "geo/private/coord/gauss.h" namespace ns { namespace geo { // BeiJing54 -> Gauss-Kruger const char* Wgs84Proj4Init = "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"; GaussConverter::GaussConverter(double centerMeridian, double bandWidth, double pm) : m_pm(pm), m_bandWidth(bandWidth) { m_ctx = pj_ctx_alloc(); // m_ctx=proj_context_create(); m_beiJing54Proj = pj_init_plus_ctx(m_ctx, Wgs84Proj4Init); m_centralMeridian = unifyCentralMeridian(centerMeridian); char str[128] = {0}; sprintf(str, "+proj=tmerc +ellps=WGS84 +lon_0=%.2fe +x_0=500000 +y_0=0 +lon_wrap=180 +units=m +k=1.0", m_centralMeridian); m_centralProj = pj_init_plus_ctx(m_ctx, str); } GaussConverter::~GaussConverter() { if (m_centralProj) pj_free(m_centralProj); if (m_beiJing54Proj) pj_free(m_beiJing54Proj); if (m_ctx) pj_ctx_free(m_ctx); // proj_context_destroy(m_ctx); } int GaussConverter::reset(double centerLon, double bandWidth, double pm) { if (are_equal(bandWidth, 0) && are_equal(pm, 0)) { double c = unifyCentralMeridian(centerLon); if (are_equal(c, m_centralMeridian)) return 0; } else { m_bandWidth = bandWidth; m_pm = pm; } pj_free(m_centralProj); m_centralMeridian = unifyCentralMeridian(centerLon); char str[128] = {0}; sprintf( str, "+proj=tmerc +ellps=WGS84 +lon_0=%.2fe +x_0=500000 +y_0=0 +lon_wrap=180 +units=m +k=1.0", m_centralMeridian); m_centralProj = pj_init_plus_ctx(m_ctx, str); return 0; } bool GaussConverter::reset(std::string pjParamsStr) { pj_free(m_centralProj); m_centralProj = pj_init_plus_ctx(m_ctx, pjParamsStr.c_str()); if (m_centralProj) { return calcCenterLon(pjParamsStr, m_centralMeridian); } return false; } bool GaussConverter::calcCenterLon(std::string params, double& cenLon) { std::vector subs = util::split(params, " "); for (auto& s : subs) { if (util::startswith(s, "+lon_0=")) { std::string numStr = s.substr(7); numStr = util::trim(numStr, " "); if (util::isNum(numStr)) { cenLon = std::stod(numStr.c_str()); return true; } } } return false; } double GaussConverter::unifyCentralMeridian(double lon) { m_zone = static_cast(std::floor((lon - m_pm) / m_bandWidth)) + 1; return getCentralMeridian(m_zone); } PointD GaussConverter::wgs842Gauss(const PointD& p) const { double x = p.x * DEG_TO_RAD; double y = p.y * DEG_TO_RAD; double z = 0.0; pj_transform(m_beiJing54Proj, m_centralProj, 1, 1, &x, &y, &z); return PointD(x, y, p.z); } PointD GaussConverter::gauss2Wgs84(const PointD& p) const { double x = p.x, y = p.y, z = 0.0; pj_transform(m_centralProj, m_beiJing54Proj, 1, 1, &x, &y, &z); return PointD(x * RAD_TO_DEG, y * RAD_TO_DEG, p.z); } } // namespace geo } // namespace ns