前言
osgearth_srstest示例,主要涉及到两个坐标系转换,wgs84→egm96 wgs84→plate-carre
wgs84:World Geodetic System 1984,是为GPS全球定位系统使用而建立的坐标系统。导航系统、GPS系统,都在使用此坐标。
egm96:EGM9模型是美国bai推出的一种适用于全球范围,并综合利用现有全球大量重力数据所计算出来的高精度大地水准面模型。但是因其发布年代较早并且缺乏中国地区重力数据所以高程转换精度较低,难以满足工程测量需要。而近年来由美国NGA重力场研发小组发布了EGM2008大地水准面模型,改善了这一情况。
plate-carre:简易圆柱投影是一种等距圆柱投影,其标准纬线位于赤道处。 经纬线的格网从东到西并从极点到极点形成完美的方形。(此链接实为宝藏,对于不理解各种坐标和投影关系的小伙伴,特别有帮助)
// cmd 命令框 输入以下代码:
osgearth_srstestd.exe
执行结果
Convert geodetic Z to EGM96: transform succeed for texst #output[0]: 0, 0, 1.5258789076710854715202e-07
Convert geodetic Z to EGM96: output doesn't match for test #1; expected Z=0, got Z=-0.0100004577636738645196601
Convert geodetic Z to EGM96: transform succeed for texst #output[2]: 180, 0, 3.814697251414145284798e-07
Convert geodetic Z to EGM96: transform succeed for texst #output[3]: -90, 0, -0.00999979019165042615213679
Convert geodetic Z to EGM96: output doesn't match for test #4; expected Z=0, got Z=44.06999969482421875
result = -20037508.3427892476320267, -10018754.1713946219533682, 0
result = -20037508.3427892476320267, 10018754.1713946219533682, 0
result = 20037508.3427892476320267, -10018754.1713946219533682, 0
result = 20037508.3427892476320267, 10018754.1713946219533682, 0
result = 10018754.1713946238160133, 3339584.72379820747300982, 1000
根据执行结果猜测:第一种转换是为了验证两种坐标系获取的同一位置高程值是否相同。
第二种转换,猜测是将椭球投影后,在平面上,获取XY的位置,Z值意义不大。毕竟投影后就不关心高程值了。
代码分析
#include <osgEarth/SpatialReference>
#include <osgEarth/StringUtils>
#include <osgEarth/Profile>
#include <iostream>
bool eq(const double& a, const double& b, double e =1e-6) {
return fabs(a - b) <= e;
}
bool eq(const osg::Vec3d& a, const osg::Vec3d& b, double e =1e-6) {
return fabs(a.x() - b.x()) <= e && fabs(a.y() - b.y()) <= e && fabs(a.z() - b.z()) <= e;
}
int fail(const std::string& test, const std::string& msg) {
std::cout << test << ": " << msg << std::endl;
return -1;
}
int
main(int argc, char** argv)
{
using namespace osgEarth;
std::string test;
// Vertical datum tests.
// Reference: http://earth-info.nga.mil/GandG/wgs84/gravitymod/egm96/intpt.html
{
// wgs84坐标 转换到 EGM96坐标。这是两个不同的坐标系统。
// 在osgearth中,还有epsg:4326 plate-carre
test = "Convert geodetic Z to EGM96";
const SpatialReference* wgs84 = SpatialReference::get("wgs84");
const SpatialReference* wgs84_egm96 = SpatialReference::get("wgs84", "egm96");
osg::Vec3d input[5] = {
osg::Vec3d( 0, 0, 17.16),// 赤道上的点
osg::Vec3d( 90, 0, -63.24),
osg::Vec3d(180, 0, 21.15),
osg::Vec3d(-90, 0, -4.29),
osg::Vec3d(90,30,10)// 一般值测试
};
osg::Vec3d output;
for (int i = 0; i<5; ++i) {
osg::Vec3d output;
if (!wgs84->transform(input[i], wgs84_egm96, output))
std::cout << test << ": transform failed for texst #" << i << std::endl;
else if (!eq(output.z(), 0.0, 0.01)) { // 判断转换后的值,高度z是否为0
std::cout << test << ": output doesn't match for test #" << i << "; expected Z=0, got Z=" << output.z() << std::endl;
}
else
{
// 转换成功
std::cout << test << ": transform succeed for texst #output[" << i <<"]: "<<
std::setprecision(24) << output.x() << ", " << output.y() << ", " << output.z() << std::endl;
}
}
}
std::cout << std::endl;
// Plate Carre EQC Test.
{
// plate-carre: WGS84 projected flat (X=longitude, Y=latitude),WGS84投影平面
test = "Plate Carre EQC Test";
const SpatialReference* wgs84 = SpatialReference::get("wgs84");
const SpatialReference* pceqc = SpatialReference::get("plate-carre");// 二维坐标
osg::Vec3d input[5] = {
osg::Vec3d(-180, -90, 0),// 极值测试
osg::Vec3d(-180, +90, 0),
osg::Vec3d( 180, -90, 0),
osg::Vec3d( 180, +90, 0),
osg::Vec3d(90,30,1000)// 一般值测试
};
osg::Vec3d output;
for (int i = 0; i<5; ++i) {
osg::Vec3d output;
if (!wgs84->transform(input[i], pceqc, output)) {
std::cout << test << ": transform failed for test #" << i << std::endl;
}
else {
std::cout << "result = " << std::setprecision(24) << output.x() << ", " << output.y() << ", " << output.z() << std::endl;
}
}
}
return 0;
}