#include "stdafx.h" #include "ProjectionParameterAssistant.h" #include #include #include #include #define _PROJECTION_GAUSS_TITLE "Gauss" #define _PROJECTION_GAUSS_TITLE_LOWER "gauss" #define _PROJECTION_UTM_TITLE "UTM" #define _PROJECTION_UTM_TITLE_LOWER "utm" #define _PROJECTION_LAMBER_TITLE "Lamber" #define _PROJECTION_LAMBER_TITLE_LOWER "lamber" #define _PROJECTION_MERCATOR_TITLE "Mercator" #define _PROJECTION_MERCATOR_TITLE_LOWER "mercator" #define _PROJECTION_ALBERS_TITLE "Albers" #define _PROJECTION_ALBERS_TITLE_LOWER "albers" //解析这种格式的字符串 WD=%d ZN=%d CL=0 CT=0 class KeyValueParser { public: bool Parse(char * kvStr); bool GetValueStr(const char * kry, double & v); private: bool ParseToken(char * s, char * e); private: std::map m_map; }; ProjectionParameterAssistant * ProjectionParameterAssistant::m_pInstance = 0; ProjectionParameterAssistant * ProjectionParameterAssistant::GetInstance() { if (m_pInstance == 0) m_pInstance = new ProjectionParameterAssistant(); return m_pInstance; } void ProjectionParameterAssistant::SetParameter(SigmaProjectionParameter * para) { m_para = para; } ProjectionParameterAssistant::ProjectionParameterAssistant() :m_para(0) { InitEllipsoidMap(); } void ProjectionParameterAssistant::InitEllipsoidMap() { m_ellipsoidMap["china-1954"] = 0; m_ellipsoidMap["china-1967"] = 1; m_ellipsoidMap["china-1975"] = 2; m_ellipsoidMap["china-1980"] = 3; m_ellipsoidMap["china-1983"] = 4; m_ellipsoidMap["wgs-60"] = 5; m_ellipsoidMap["wgs-66"] = 6; m_ellipsoidMap["wgs-72"] = 7; m_ellipsoidMap["wgs-84"] = 8; m_ellipsoidMap["bessel"] = 9; m_ellipsoidMap["hayfard"] = 10; m_ellipsoidMap["clarke-1866"] = 11; m_ellipsoidMap["krasovsky"] = 12; m_ellipsoidMap["youcunyi(china)"] = 13; m_ellipsoidMap["grim-1"] = 14; m_ellipsoidMap["grim-2"] = 15; m_ellipsoidMap["gem-8"] = 16; m_ellipsoidMap["gem-10"] = 17; //对老投影参数的自动转换对应 m_ellipsoidMap["54"] = 0; m_ellipsoidMap["80"] = 1; m_ellipsoidMap["1954"] = 0; m_ellipsoidMap["1967"] = 1; m_ellipsoidMap["1975"] = 2; m_ellipsoidMap["1980"] = 3; m_ellipsoidMap["1983"] = 4; //------------------------------------------- m_ellipsoidIntMap[0] = "China-1954"; m_ellipsoidIntMap[1] = "China-1967"; m_ellipsoidIntMap[2] = "China-1975"; m_ellipsoidIntMap[3] = "China-1980"; m_ellipsoidIntMap[4] = "China-1983"; m_ellipsoidIntMap[5] = "WGS-60"; m_ellipsoidIntMap[6] = "WGS-66"; m_ellipsoidIntMap[7] = "WGS-72"; m_ellipsoidIntMap[8] = "WGS-84"; m_ellipsoidIntMap[9] = "Bessel"; m_ellipsoidIntMap[10] = "Hayfard"; m_ellipsoidIntMap[11] = "Clarke-1866"; m_ellipsoidIntMap[12] = "Krasovsky"; m_ellipsoidIntMap[13] = "YouCunYi(china)"; m_ellipsoidIntMap[14] = "GRIM-1"; m_ellipsoidIntMap[15] = "GRIM-2"; m_ellipsoidIntMap[16] = "GEM-8"; m_ellipsoidIntMap[17] = "GEM-10"; } //Projection //椭球体 Gauss 带宽,带号[,自定义中央经线(度分秒表示方式)] 坐标类型,单位 北半球[南半球],东经[西经] //[椭球体 Taper 中央经度线,双标准纬线纬度1,双标准纬线纬度2,坐标原点的纬度 坐标类型,单位] 北半球[南半球],东经[西经] int ProjectionParameterAssistant::ParseParameterFromString(CString & projStr) { if (m_para == 0) return 0; InitParameter(); char se[256], sp[256], sz[256], su[256], sa[256]; int t = sscanf(projStr, "%s%s%s%s%s", se, sp, sz, su, sa); if (t < 2) return 0; std::string ellipsoidStr(se); m_para->ellipsoidKind = GetIndexOfEllipsoid(ellipsoidStr); if (m_para->ellipsoidKind == -1) return 0; std::string typeStr(sp); if (GetPrjectionType(typeStr) == 0) { m_para->projection = _PROJECTION_GAUSS; m_para->coordinate_type = _XY_BL_BL; m_para->coordinate_unit = _XY_BL_DEGREE; return 2; } if (t == 2) return 2; switch (m_para->projection) { case _PROJECTION_GAUSS: case _PROJECTION_UTM: { CString str = sz; int flags = 0; str.MakeUpper(); str.Replace("AUTO", "-1"); int r = sscanf(str, "%d,%d,%lf,%u", &m_para->w, &m_para->zone, &m_para->m_dCustomCenterLongitude, &flags); if (flags & _XY_MODE_WITH_ZONE) m_para->bZone = 1; else m_para->bZone = 0; if (flags & _XY_MODE_CUSTOM) m_para->bCustomCenterLongitude = 1;//EnableCustomCenterLongitude(TRUE); else m_para->bCustomCenterLongitude = 0; } break; case _PROJECTION_LAMBERT: sscanf(sz, "%lf,%lf,%lf,%lf", &m_para->conic_OriginLongitude, &m_para->conic_b1, &m_para->conic_b2, &m_para->conic_OriginLatitude); break; } if (t == 3) { m_para->coordinate_type = _XY_XY_XY; m_para->coordinate_unit = _XY_XY_KM; return 3; } sscanf(su, "%d,%d", &m_para->coordinate_type, &m_para->coordinate_unit); if (t == 5) sscanf(sa, "%ld,%ld", &m_para->latitude, &m_para->longitude); return 5; } bool ProjectionParameterAssistant::GenerateOtherString(std::string & otherStrOut) { if (m_para == 0) return false; char buffer[512]; memset(buffer, 0, sizeof(buffer)); if (m_para->projection == _PROJECTION_GAUSS || m_para->projection == _PROJECTION_UTM) { if (m_para->bCustomCenterLongitude == 1) snprintf(buffer, sizeof(buffer)-1, "WD=%d ZN=%d CL=%d CT=1", m_para->w, m_para->zone, (int)m_para->m_dCustomCenterLongitude); else snprintf(buffer, sizeof(buffer)-1, "WD=%d ZN=%d CL=0 CT=0", m_para->w, m_para->zone); otherStrOut = buffer; return true; } else if (m_para->projection == _PROJECTION_LAMBERT) { //程序使用度分秒的格式显示 例如120度30分30秒就写成 1203030 所以直接显示成整数就好了 snprintf(buffer, sizeof(buffer)-1, "L0=%d B1=%d B2=%d BS=%d", (int)m_para->conic_OriginLongitude, (int)m_para->conic_b1, (int)m_para->conic_b2, (int)m_para->conic_OriginLatitude); otherStrOut = buffer; return true; } return false; } int ProjectionParameterAssistant::GetProjectStr(std::string & projStrOut) { if (m_para == 0) return -1; char buffer[512]; memset(buffer, 0, sizeof(buffer)); char su[512]; memset(su, 0, sizeof(su)); char sz[512]; memset(sz, 0, sizeof(sz)); char sa[512]; memset(sa, 0, sizeof(sa)); std::string sp; GetPrjectionName(sp); if (sp.empty()) return -1; auto ite = m_ellipsoidIntMap.find(m_para->ellipsoidKind); if (ite == m_ellipsoidIntMap.end()) return -1; std::string ellipsoidName = (*ite).second; snprintf(su, sizeof(su)-1, "%d,%d", m_para->coordinate_type, m_para->coordinate_unit); int flag = m_para->bZone; flag = flag << 1; //是否有代号写在到了flag的第二位 flag |= m_para->bCustomCenterLongitude;; switch (m_para->projection) { case _PROJECTION_GAUSS: case _PROJECTION_UTM: if (m_para->bCustomCenterLongitude) snprintf(sz, sizeof(sz) - 1, "%d,%d,%f,%d", m_para->w, m_para->zone, m_para->m_dCustomCenterLongitude, flag); else snprintf(sz, sizeof(sz) - 1, "%d,%d,0,%d", m_para->w, m_para->zone, flag); //sz.Format("%d,%d,0,%u", w, zone, m_nFlags); //dfFloatToString(sccl, m_dCustomCenterLongitude, 8); //if (IsCustomCenterLongitude()) // sz.Format("%d,%d,%s,%u", w, zone, sccl, m_nFlags); //else // sz.Format("%d,%d,0,%u", w, zone, m_nFlags); break; case _PROJECTION_LAMBERT: { snprintf(sz, sizeof(sz) - 1, "%f,%f,%f,%f", m_para->conic_OriginLongitude, m_para->conic_b1, m_para->conic_b2, m_para->conic_OriginLatitude); } break; } snprintf(sa, sizeof(sa)-1, "%d,%d", m_para->latitude, m_para->longitude); snprintf(buffer, sizeof(buffer)-1, "%s %s %s %s %s", ellipsoidName.c_str(), sp.c_str(), sz, su, sa); projStrOut = buffer; return 1; } void ProjectionParameterAssistant::InitParameter() { m_para->zone = -1; m_para->w = 6; m_para->projection = _PROJECTION_GAUSS; m_para->m_dScaleFactor = 1.0; m_para->ellipsoidKind = 3; //China-1980 m_para->coordinate_type = _XY_XY_XY; m_para->coordinate_unit = _XY_XY_M; m_para->conic_OriginLongitude = 0; m_para->conic_OriginLatitude = 0; m_para->conic_b1 = m_para->conic_b2 = 0; m_para->m_dCustomCenterLongitude = 0; m_para->latitude = _AREA_NORTH_LATITUDE; m_para->longitude = _AREA_EAST_LONGITUDE; //m_para->flags = _XY_MODE_WITH_ZONE; m_para->bZone = 1; m_para->bCustomCenterLongitude = 0; } //高斯投影时 解析带宽、 //兰渤托投影时 bool ProjectionParameterAssistant::FillOtherParameter(std::string & otherStr) { if (m_para->projection == _PROJECTION_GAUSS || m_para->projection == _PROJECTION_UTM) return ProcessForGuass(otherStr); else if (m_para->projection == _PROJECTION_LAMBERT) return ProcessForLambert(otherStr); return false; } int ProjectionParameterAssistant::GetPrjectionType(std::string & type) { std::string typeStr = type; std::transform(typeStr.begin(), typeStr.end(), typeStr.begin(), tolower); int rt = 1; if (typeStr == _PROJECTION_GAUSS_TITLE_LOWER) { m_para->projection = _PROJECTION_GAUSS; m_para->m_dScaleFactor = 1.0; } else if (typeStr == _PROJECTION_UTM_TITLE_LOWER) { m_para->projection = _PROJECTION_UTM; m_para->m_dScaleFactor = 0.9996; } else if (typeStr == "taper" || typeStr == _PROJECTION_LAMBER_TITLE_LOWER) m_para->projection = _PROJECTION_LAMBERT; else if (typeStr == _PROJECTION_MERCATOR_TITLE_LOWER) m_para->projection = _PROJECTION_MERCATOR; else if (typeStr == _PROJECTION_ALBERS_TITLE_LOWER) m_para->projection = _PROJECTION_ALBERS; else rt = 0; return rt; } int ProjectionParameterAssistant::GetIndexOfEllipsoid(std::string & ellipsoidStr) { std::string str = ellipsoidStr; std::transform(str.begin(), str.end(), str.begin(), tolower); auto ite = m_ellipsoidMap.find(str); if (ite == m_ellipsoidMap.end()) return -1; return (*ite).second; } void ProjectionParameterAssistant::GetPrjectionName(std::string & projNameOut) { if (m_para == 0) return; switch (m_para->projection) { case _PROJECTION_GAUSS: projNameOut = _PROJECTION_GAUSS_TITLE; break; case _PROJECTION_UTM: projNameOut = _PROJECTION_UTM_TITLE; break; case _PROJECTION_LAMBERT: projNameOut = "Taper"; break; case _PROJECTION_MERCATOR: projNameOut = _PROJECTION_MERCATOR_TITLE; break; case _PROJECTION_ALBERS: projNameOut = _PROJECTION_ALBERS_TITLE; break; default: break; } } bool ProjectionParameterAssistant::ProcessForGuass(std::string & otherStr) { //WD=%d ZN=%d CL=0 CT=0 std::string str(otherStr); KeyValueParser parser; if (parser.Parse((char *)str.c_str()) == false) return false; double w = 0; if (parser.GetValueStr("WD", w) == false) return false; double zone = 0; if (parser.GetValueStr("ZN", zone) == false) return false; double cl = 0; if (parser.GetValueStr("CL", cl) == false) return false; double ct = 0; if (parser.GetValueStr("CT", ct) == false) return false; m_para->w = w; m_para->zone = zone; m_para->m_dCustomCenterLongitude = cl; int ctInt = (int)ct; if (ctInt != 0 && ctInt != 1) return false; m_para->bCustomCenterLongitude = ctInt; return true; } bool ProjectionParameterAssistant::ProcessForLambert(std::string & otherStr) { //L0=%f B1=%f B2=%f BS=%f std::string str(otherStr); KeyValueParser parser; if (parser.Parse((char *)str.c_str()) == false) return false; double L0 = 0; if (parser.GetValueStr("L0", L0) == false) return false; double B1 = 0; if (parser.GetValueStr("B1", B1) == false) return false; double B2 = 0; if (parser.GetValueStr("B2", B2) == false) return false; double BS = 0; if (parser.GetValueStr("BS", BS) == false) return false; m_para->conic_OriginLongitude = L0; m_para->conic_b1 = B1; m_para->conic_b2 = B2; m_para->conic_OriginLatitude = BS; return true; } bool KeyValueParser::Parse(char * kvStr) { if (kvStr == 0) return false; char * p = kvStr; if (*p == '\0') return false; while (*p != '\0') //去掉字符串开头处的空格 { if (*p == ' ') { p++; } else break; } char * pStart = p; //Token起点 while (*p != '\0') { if (*p == ' ') { if (ParseToken(pStart, p - 1) == false) return false; //移除p后的空格 while (true) { p++; if (*p != ' ') { pStart = p; break; } if (*p == '\0') return true; } } if (*(p + 1) == 0) //到字符串结尾处了 { ParseToken(pStart, p); } p++; } return true; } bool KeyValueParser::GetValueStr(const char * key, double & v) { if (key == 0) return false; auto ite = m_map.find(key); if (ite == m_map.end()) return false; v = (*ite).second; return true; } bool KeyValueParser::ParseToken(char * s, char * e) { if (e <= s) return false; char * p1 = s; //得到等号之前的位子 while (p1 < e) { if (*p1 == '=') break; p1++; } if (p1 == e) //搜索完字符串 也没找到等号 return false; if (s == p1) return false; *p1 = '\0'; //截取key std::string key(s); if (key.empty()) return false; p1++; //跳过等号 if (p1 > e) return false; std::string valueStr; while (p1 <= e) { valueStr.push_back(*p1); p1++; } std::istringstream convert(valueStr); double v = 0; if (!(convert >> v)) { return false; } m_map[key] = v; return true; }