You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kev/Drawer/Module/GeoSigmaDraw/ProjectionParameterAssistan...

552 lines
13 KiB
C++

#include "stdafx.h"
#include "ProjectionParameterAssistant.h"
#include <ProjectionLib/ProjectionParameter.h>
#include <map>
#include <sstream>
#include <algorithm>
#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<std::string, double> 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;
}