坐标转换源代码,C++/C, 极为精确地大地坐标系转地心坐标系,地心坐标系转站心坐标系

坐标转换源代码,C++/C, 极为精确地大地坐标系转地心坐标系,地心坐标系转站心坐标系
摘自http://blog.sina.com.cn/s/blog_4e426d410101ahlt.html

//WGS84地理坐标系参变量

struct CRDGEODETIC
{
double latitude;
double longitude;
double altitude;
};
 
//空间笛卡尔坐标系坐标点
struct CRDCARTESIAN
{
double x;
double y;
double z;
};
 
 
//最精确的坐标转换办法 ,空间大地坐标系向空间直角坐标系的转换

CRDCARTESIAN Coordcovert::BLH_to_XYZ (CRDGEODETIC pos_BLH)//大地--->球心
{
double a=6378137;//a为椭球的长半轴:a=6378.137km
double b=6356752.3141;//b为椭球的短半轴:a=6356.7523141km
double H=pos_BLH.altitude+a;
double e=sqrt(1-pow(b ,2)/pow(a ,2)); //e为椭球的第一偏心率
// double e=sqrt(0.006693421622966); //克拉索夫斯基椭球
// double e=sqrt(0.006694384999588); //1975年国际椭球
// double e=sqrt(0.0066943799013); //WGS-84椭球
CRDCARTESIAN pos_XYZ;
double m=M_PI/180;//经度维度需要转换成弧度.
double B=pos_BLH.latitude*m;
double L=pos_BLH.longitude*m;
double W=sqrt(1-pow(e ,2)*pow(sin(B) ,2));
double N=a/W; //N为椭球的卯酉圈曲率半径
pos_XYZ.x=(N+H)*cos(B)*cos(L);
pos_XYZ.y=(N+H)*cos(B)*sin(L);
pos_XYZ.z=(N*(1-pow(e ,2))+H)*sin(B);
return pos_XYZ;
}
CRDGEODETIC Coordcovert::XYZ_to_BHL (CRDCARTESIAN pos_XYZ)//球心--->大地
{
double v0=pos_XYZ.z/sqrt(pow(pos_XYZ.x ,2)+pow(pos_XYZ.y ,2));
double a=6378137;//a为椭球的长半轴:a=6378.137km
double b=6356752;
double e=sqrt(1-pow(b ,2)/pow(a ,2)); //e为椭球的第一偏心率
// double e=sqrt(0.006693421622966); //克拉索夫斯基椭球
// double e=sqrt(0.006694384999588); //1975年国际椭球
// double e=sqrt(0.0066943799013); //WGS-84椭球
// double W=sqrt(1-pow(e ,2)*pow(sin(B) ,2));
double N=0 ; //N为椭球的卯酉圈曲率半径
double B1=atan(v0) ,B2=0;
double H=0;
while(qAbs(B2-B1)>1E-5)
{
N = a/sqrt(1-pow(e ,2)*pow(sin(B1) ,2));
H = pos_XYZ.z/sin(B1)-N*(1-pow(e ,2));
B2 = atan(pos_XYZ.z*(N+H)/sqrt((pow(pos_XYZ.x ,2)+pow(pos_XYZ.y ,2))*(N*(1-pow(e ,2))+H)));
B1=B2;
}
double m=M_PI/180;
CRDGEODETIC pos_BLH;
pos_BLH.latitude=B1/m;
pos_BLH.longitude=atan(pos_XYZ.y/pos_XYZ.x)/m;
pos_BLH.altitude=H-a;
return pos_BLH;
}
CRDCARTESIAN Coordcovert::XYZ_to_xyz (CRDCARTESIAN pos_XYZ , CRDGEODETIC Center)//球心--->站心
{
CRDCARTESIAN pos_xyz ,tmp_XYZ;
CRDCARTESIAN Center_XYZ = BLH_to_XYZ (Center);
tmp_XYZ.x = pos_XYZ.x-Center_XYZ.x;
tmp_XYZ.y = pos_XYZ.y-Center_XYZ.y;
tmp_XYZ.z = pos_XYZ.z-Center_XYZ.z;
double m=M_PI/180;
pos_xyz.x = -sin(Center.latitude*m)*cos(Center.longitude*m)*tmp_XYZ.x-sin(Center.latitude*m)*sin(Center.longitude*m)*tmp_XYZ.y
+ cos(Center.latitude*m)*tmp_XYZ.z;
pos_xyz.y = -sin(Center.longitude*m)*tmp_XYZ.x+cos(Center.longitude*m)*tmp_XYZ.y;
pos_xyz.z = cos(Center.latitude*m)*cos(Center.longitude*m)*tmp_XYZ.x+cos(Center.latitude*m)*sin(Center.longitude*m)*tmp_XYZ.y
+ sin(Center.latitude*m)*tmp_XYZ.z - a;
return pos_xyz;
}
CRDCARTESIAN Coordcovert::xyz_to_XYZ (CRDCARTESIAN pos_xyz , CRDGEODETIC Center)//站心--->球心
{
double a=6378137;//a为椭球的长半轴:a=6378.137km
double b=6356752.3141;//b为椭球的短半轴:a=6356.7523141km
double H0=Center.altitude+a;
double e=sqrt(1-pow(b ,2)/pow(a ,2)); //e为椭球的第一偏心率
// double e=sqrt(0.006693421622966); //克拉索夫斯基椭球
// double e=sqrt(0.006694384999588); //1975年国际椭球
// double e=sqrt(0.0066943799013); //WGS-84椭球
double m=M_PI/180;//经度维度需要转换成弧度.
double B0=Center.latitude*m;
double L0=Center.longitude*m;
double W=sqrt(1-pow(e ,2)*pow(sin(B0) ,2));
double N0=a/W; //N为椭球的卯酉圈曲率半径
CRDCARTESIAN pos_XYZ;
pos_XYZ.x = (N0+H0)*cos(B0)*cos(L0)
-sin(B0)*cos(L0)*pos_xyz.x - sin(L0)*pos_xyz.y + cos(B0)*cos(L0)*pos_xyz.z;
pos_XYZ.y = (N0+H0)*cos(B0)*sin(L0)
-sin(B0)*sin(L0)*pos_xyz.x - cos(L0)*pos_xyz.y + cos(B0)*sin(L0)*pos_xyz.z;
pos_XYZ.z = (N0*(1-pow(e ,2))+H0)*sin(B0)
-cos(B0)*pos_xyz.x + sin(B0)*pos_xyz.z;
return pos_XYZ;
}
分享:
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
坐标系地心坐标系都是地理坐标系的一种,其中站坐标系是以某个固定站点为原点建立的坐标系,而地心坐标系是以地球质为原点建立的坐标系。因此,站坐标系地心坐标系之间的转换需要知道站点的经纬度和海拔高度等信息。 以下是C++实现站坐标系转地心坐标系的示例代码: ```c++ #include <iostream> #include <cmath> using namespace std; const double pi = 3.14159265358979323846; const double a = 6378137.0; // 赤道半径 const double f = 1 / 298.257223563; // 扁率 // 计算子午圈曲率半径 double Rm(double lat) { double sin_lat = sin(lat * pi / 180.0); return a * (1 - f) / pow(1 - f * pow(sin_lat, 2), 1.5); } // 计算卯酉圈曲率半径 double Rn(double lat) { double sin_lat = sin(lat * pi / 180.0); return a / sqrt(1 - f * pow(sin_lat, 2)); } // 站坐标系转地心坐标系 void station2earth(double lon0, double lat0, double h0, double x, double y, double z, double& lon, double& lat, double& h) { double sin_lat0 = sin(lat0 * pi / 180.0); double cos_lat0 = cos(lat0 * pi / 180.0); double sin_lon0 = sin(lon0 * pi / 180.0); double cos_lon0 = cos(lon0 * pi / 180.0); // 计算站坐标系地心坐标系的旋转矩阵 double R[3][3] = { {-sin_lat0 * cos_lon0, -sin_lat0 * sin_lon0, cos_lat0}, {-sin_lon0, cos_lon0, 0}, {-cos_lat0 * cos_lon0, -cos_lat0 * sin_lon0, -sin_lat0} }; // 计算站坐标系地心坐标系的平移向量 double T[3] = { (Rm(lat0) + h0) * cos_lat0 * cos_lon0, (Rm(lat0) + h0) * cos_lat0 * sin_lon0, (Rn(lat0) / (1 - pow(f, 2)) + h0) * sin_lat0 }; // 矩阵乘法 double p[3] = {x, y, z}; double q[3] = {0}; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { q[i] += R[i][j] * p[j]; } q[i] += T[i]; } // 计算地心坐标系的经纬度和海拔高度 double r = sqrt(pow(q[0], 2) + pow(q[1], 2) + pow(q[2], 2)); double sin_lat = q[2] / r; lat = asin(sin_lat) * 180.0 / pi; double cos_lat = cos(lat * pi / 180.0); double sin_lon = q[1] / (r * cos_lat); double cos_lon = q[0] / (r * cos_lat); lon = atan2(sin_lon, cos_lon) * 180.0 / pi; h = r - a / sqrt(1 - f * pow(sin_lat, 2)); } int main() { double lon0 = 116.3975; // 北京市经度 double lat0 = 39.9086; // 北京市纬度 double h0 = 43; // 北京市海拔高度,单位为米 double x = 1000; // 站坐标系X坐标,单位为米 double y = 2000; // 站坐标系Y坐标,单位为米 double z = 3000; // 站坐标系Z坐标,单位为米 double lon, lat, h; station2earth(lon0, lat0, h0, x, y, z, lon, lat, h); cout << "经度:" << lon << ",纬度:" << lat << ",海拔高度:" << h << endl; return 0; } ``` 在上述示例代码中,函数`Rm`和`Rn`分别用于计算子午圈曲率半径和卯酉圈曲率半径,这两个函数都是基于WGS84椭球体模型的计算公式。函数`station2earth`用于将站坐标系中的点`(x, y, z)`转换为地心坐标系中的点`(lon, lat, h)`,其中`lon`表示经度,`lat`表示纬度,`h`表示海拔高度。在函数中,首先计算站坐标系地心坐标系的旋转矩阵和平移向量,然后将旋转矩阵和平移向量应用到点`(x, y, z)`上,得到点`(q[0], q[1], q[2])`,最后根据点`(q[0], q[1], q[2])`计算地心坐标系的经纬度和海拔高度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值