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.
552 lines
13 KiB
C++
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;
|
|
}
|