经纬度字符串解析器和格式化器






4.58/5 (11投票s)
2006年9月21日
4分钟阅读

84520

1345
一个用于经纬度值的类,可以将字符串解析为双精度数,或者将双精度数格式化为字符串。
引言
CLongLatString
类用于解析经度或纬度的多种表示形式,将其转换为 double
类型,或者将表示地理坐标的 double
类型格式化为美观的地理坐标字符串。
背景
地球被划分为经纬度地理网格线。经度测量从英国格林威治向东和向西的角度距离。纬度测量从赤道向北和向南的角度距离。等经度线在两极汇聚,而等纬度线是环绕地球的平行线。这只是众多地理坐标系统中的一种,但它是迄今为止最通用和最被理解的系统。
这些坐标通常以半球(N、S、E、W)、度、分和秒来表示。有些人使用十进制度,度分,或度分秒的组合。有些人用正负号代替半球(东为正)。此外,许多分隔符和放置方式使格式更加复杂,有些省略了分隔符,通常最后一项是小数,而前面的项是整数,有些则将所有数据连在一起以节省空间,而半球项可以位于坐标中的任何位置。
各种地理坐标格式的一些示例
45:26:46N, 65:56:55W
45:26:46.302N, 65:56:55.903W
45°26’21"N, 65°58’36"W
45N26 21, 65W58 36
45.446195N, 65.948862W
45.446195, -65.948862
N45° 26.7717’, W65° 56.93172’
使用代码
我认为,这个类具有相当强大的自动解析数据并提取数值的能力。例如,这允许您为每个地理坐标提供一个编辑框,而不是一个用于半球的组合框和单独的度、分、秒输入字段。
CLongLatString
类处理这些各种经纬度格式,以便可以轻松地处理和转换为双精度值,用于其他地理方法。该对象为每个值维护一个双精度数和一个字符串。保留字符串是因为有时需要保留原始数据,以保持精度。您可以像使用 printf 风格的值(例如 `%C, %c, %H %h %D, %d, %M, %m, %S, and %s` 作为参数)将 CTime
从 time_t
格式化一样,从双精度数输出字符串值。
CLongLatString
不处理成对的坐标 - 每个对象最好单独处理一个值,以指示它是经度还是纬度。因此,如果您使用纯双精度数初始化数据,则还必须指明该值是经度还是纬度,才能获得有意义的结果。
有大量的构造函数和一个复制构造函数。您可以根据需要使用字符串或双精度数进行初始化。还有转换运算符和赋值运算符,因此您可以轻松地转换为双精度数或标准字符串。
CLongLatString llstrLat1("45N54.2356"); CLongLatString llstrLat2("-45.98739874", LL_LATITUDE); CLongLatString llstrLat5(-45.98739874, LL_LATITUDE); CLongLatString llstrLat7("N", "45", "34", "33"); CLongLatString llstrLat8("N455698735", "HDDMMmmmmm");
如果您要使用双精度数或包含文本双精度数的字符串的赋值运算符,则必须初始化该对象以告知它是经度还是纬度。
CLongLatString llstrLat(LL_LATITUDE); llstrLat = -5.877789; std::string str = llstrLat.Format("%Dd%M\’%S\"%H"); cout << str.c_str() << endl; // Output - 5d52’40"S llstrLat = -5.997789; // Can be reused - still a latitude str = llstrLat.Format("%Dd%M\’%S\"%H"); cout << str.c_str() << endl;
或者一个更复杂的例子
std::string str = llstrLat.Format("%H%02D %.5m"); // Output - S05 52.66734
输出格式
%H - hemisphere - single character of N,S,E,W
%C - integer co-ordinate, may be negative or positive
%c - decimal co-ordinate, the entire co-ordinate,
may be negative or positive
%D - integer degrees, always positive
%M - integer degrees, always positive
%S - integer seconds, always positive, rounded
%d - decimal degrees, always positive
%m - decimal minutes, always positive
%s - decimal seconds, always positive
%% - for %
可以使用标准的 printf 格式,例如 %03D
为整数度创建带有前导零的三位空间,或者 %.5m
将小数分钟写出五位。大写标识符使用与十进制(整数)格式相同的 printf 标识符,而小写标识符使用浮点格式。所有其他标志都将起作用,因为整个子字符串将传递给 snprintf C 函数。
有用于整数形式和十进制形式的每个项的整数 Get...()
方法。如果您需要为每个项单独提取字符串形式,可以重用 Format()
方法。
例如
CLongLatString llstrLat(-5.9879875, LL_LATITUDE); std::string strHemi = llstrLat.Format("%H"); std::string strDeg = llstrLat.Format("%02D"); std::string strMin = llstrLat.Format("%02M"); std::string strSec = llstrLat.Format("%05.2s");
输入格式
输入格式有所不同,只能用于固定长度的情况(例如,"HDD MM.mmmmm" 用于 "N45 04.25764"),并且仅在格式非常混乱且连在一起时使用。对于大多数情况,度、分、秒由任何空格或大多数分隔符分隔,未指定的默认输入格式应该有效。 H
表示半球的位置,大写字母表示小数点左边的数字部分,小写字母表示小数点右边的数字。
例如
std::string strInputFormat = "HDDMMmmmmm"; CLongLatString llstrLat1("N650490807", strInputFormat); CLongLatString llstrLat2; llstrLat2.Set("N450490807", strInputFormat); llstrLat2.Set("N45°04.0807\’"); // No input format needed if there are enough delimiters
一个注意事项 - 不要将指数表示法输入字符串 - 它会将 "E" 误解为 East(东)并损坏结果。务必在使用 atof()
对参数进行转换后再将其传递给构造函数或 Set 方法。
这就讲完了。您可以查看头文件中提供的方法,其中也重复了一些格式规范,这些方法都附带一行注释说明。如果存在任何科学准确性问题或严重错误,请告诉我。