xyz、BLH 、ENU坐标
时间: 2023-10-02 17:11:37 浏览: 760
XYZ、BLH和ENU都是地理坐标系统的表示方式。它们分别代表不同的坐标系和表示方法。
- XYZ坐标系(也称为笛卡尔坐标系)使用直角坐标系来表示位置。它通过三个数值来描述一个点的位置,分别是X、Y和Z坐标。通常,X和Y代表平面上的水平位置,Z代表垂直位置。
- BLH坐标系(也称为大地坐标系)使用经度(B)、纬度(L)和高程(H)来表示位置。经度表示地球上一个点的东西方向位置,纬度表示南北方向位置,高程表示相对于参考椭球体的高度。
- ENU坐标系(即东北天坐标系)是基于局部笛卡尔坐标系的一种表示方法。它以一个参考点为原点,建立了一个平面坐标系,其中东方向为X轴,北方向为Y轴,天方向为Z轴。在这个坐标系中,点的位置可以用东北天三个方向的距离来表示。
这三种坐标系统在不同的应用场景中有各自的优势和用途。具体使用哪种坐标系取决于具体的需求和使用场景。
相关问题
XYZ,BLH,ENU坐标系统互相转化C++分头文件,主函数,测试函数
以下是XYZ、BLH、ENU坐标系统互相转换的C++代码,分为头文件、主函数和测试函数三部分。
**头文件:**
```cpp
#ifndef COORDINATECONVERTER_H
#define COORDINATECONVERTER_H
#include <cmath>
// 常数定义
const double PI = 3.14159265358979323846;
const double a = 6378137.0; // WGS84椭球长半轴
const double b = 6356752.3142; // WGS84椭球短半轴
// 坐标类型定义
struct XYZCoord {
double x;
double y;
double z;
};
struct BLHCoord {
double B;
double L;
double H;
};
struct ENUCoord {
double E;
double N;
double U;
};
// 坐标转换函数声明
XYZCoord BLHtoXYZ(const BLHCoord& blh);
BLHCoord XYZtoBLH(const XYZCoord& xyz);
ENUCoord XYZtoENU(const XYZCoord& xyz, const BLHCoord& ref_blh);
XYZCoord ENUtoXYZ(const ENUCoord& enu, const BLHCoord& ref_blh);
#endif // COORDINATECONVERTER_H
```
**主函数:**
```cpp
#include <iostream>
#include "CoordinateConverter.h"
using namespace std;
int main()
{
// 测试数据定义
BLHCoord blh;
blh.B = 31.2304;
blh.L = 121.4737;
blh.H = 10.0;
XYZCoord xyz = BLHtoXYZ(blh);
ENUCoord enu1;
enu1.E = 1.0;
enu1.N = 0.0;
enu1.U = 0.0;
ENUCoord enu2;
enu2.E = 0.0;
enu2.N = 1.0;
enu2.U = 0.0;
BLHCoord ref_blh;
ref_blh.B = 31.2304;
ref_blh.L = 121.4737;
ref_blh.H = 10.0;
XYZCoord xyz2 = ENUtoXYZ(enu1, ref_blh);
BLHCoord blh2 = XYZtoBLH(xyz2);
ENUCoord enu3 = XYZtoENU(xyz2, ref_blh);
// 输出测试结果
cout << "BLH: " << blh.B << ", " << blh.L << ", " << blh.H << endl;
cout << "XYZ: " << xyz.x << ", " << xyz.y << ", " << xyz.z << endl;
cout << "XYZ2: " << xyz2.x << ", " << xyz2.y << ", " << xyz2.z << endl;
cout << "BLH2: " << blh2.B << ", " << blh2.L << ", " << blh2.H << endl;
cout << "ENU3: " << enu3.E << ", " << enu3.N << ", " << enu3.U << endl;
return 0;
}
```
**测试函数:**
```cpp
#include "CoordinateConverter.h"
// BLH转XYZ
XYZCoord BLHtoXYZ(const BLHCoord& blh)
{
XYZCoord xyz;
double N = a / sqrt(1 - pow(e, 2) * pow(sin(blh.B), 2));
xyz.x = (N + blh.H) * cos(blh.B) * cos(blh.L);
xyz.y = (N + blh.H) * cos(blh.B) * sin(blh.L);
xyz.z = (N * (1 - pow(e, 2)) + blh.H) * sin(blh.B);
return xyz;
}
// XYZ转BLH
BLHCoord XYZtoBLH(const XYZCoord& xyz)
{
BLHCoord blh;
double p = sqrt(pow(xyz.x, 2) + pow(xyz.y, 2));
double theta = atan((xyz.z * a) / (p * b));
double B = atan((xyz.z + pow(e2 * b * sin(theta), 3)) / (p - pow(e2 * a * cos(theta), 3)));
double L = atan2(xyz.y, xyz.x);
double N = a / sqrt(1 - pow(e, 2) * pow(sin(B), 2));
double H = (p / cos(B)) - N;
blh.B = B;
blh.L = L;
blh.H = H;
return blh;
}
// XYZ转ENU
ENUCoord XYZtoENU(const XYZCoord& xyz, const BLHCoord& ref_blh)
{
ENUCoord enu;
double sinB = sin(ref_blh.B);
double cosB = cos(ref_blh.B);
double sinL = sin(ref_blh.L);
double cosL = cos(ref_blh.L);
double dx = xyz.x - BLHtoXYZ(ref_blh).x;
double dy = xyz.y - BLHtoXYZ(ref_blh).y;
double dz = xyz.z - BLHtoXYZ(ref_blh).z;
enu.E = -sinL * dx + cosL * dy;
enu.N = -sinB * cosL * dx - sinB * sinL * dy + cosB * dz;
enu.U = cosB * cosL * dx + cosB * sinL * dy + sinB * dz;
return enu;
}
// ENU转XYZ
XYZCoord ENUtoXYZ(const ENUCoord& enu, const BLHCoord& ref_blh)
{
XYZCoord xyz;
double sinB = sin(ref_blh.B);
double cosB = cos(ref_blh.B);
double sinL = sin(ref_blh.L);
double cosL = cos(ref_blh.L);
xyz.x = BLHtoXYZ(ref_blh).x - sinL * enu.E - sinB * cosL * enu.N + cosB * cosL * enu.U;
xyz.y = BLHtoXYZ(ref_blh).y + cosL * enu.E - sinB * sinL * enu.N + cosB * sinL * enu.U;
xyz.z = BLHtoXYZ(ref_blh).z + cosB * enu.N + sinB * enu.U;
return xyz;
}
```
注意:以上代码中的公式计算可能存在精度问题,如果需要更高精度的计算可以使用其他库或算法。
使用BDCS参考椭球模型XYZ,BLH,ENU坐标系统互相转化,具备XYZ坐标的减法和求模,C++分头文件,主函数,测试函数
以下是参考椭球模型XYZ,BLH,ENU坐标系统互相转化的C++代码:
头文件 `coordinates.h`:
```c++
#ifndef COORDINATES_H
#define COORDINATES_H
#include <math.h>
const double PI = 3.14159265358979323846;
const double a = 6378137.0; // WGS-84椭球长半轴
const double b = 6356752.3142; // WGS-84椭球短半轴
const double e = sqrt(1.0 - (b * b) / (a * a)); // WGS-84椭球第一偏心率
const double ep = sqrt((a * a) / (b * b) - 1.0); // WGS-84椭球第二偏心率
// BLH坐标系结构体
struct BLH
{
double B; // 纬度,单位:弧度
double L; // 经度,单位:弧度
double H; // 高程,单位:米
};
// XYZ坐标系结构体
struct XYZ
{
double X;
double Y;
double Z;
};
// ENU坐标系结构体
struct ENU
{
double E;
double N;
double U;
};
// 弧度转角度
double rad2deg(double rad);
// 角度转弧度
double deg2rad(double deg);
// 计算子午圈半径
double getRn(double B);
// 计算卯酉圈半径
double getRm(double B);
// BLH坐标系转XYZ坐标系
XYZ BLH2XYZ(BLH blh);
// XYZ坐标系转BLH坐标系
BLH XYZ2BLH(XYZ xyz);
// XYZ坐标系减法
XYZ XYZminus(XYZ xyz1, XYZ xyz2);
// XYZ坐标系求模
double XYZmod(XYZ xyz);
// BLH坐标系转ENU坐标系
ENU BLH2ENU(BLH blh1, BLH blh2);
#endif // COORDINATES_H
```
`coordinates.cpp` 实现了上述头文件中定义的各个函数:
```c++
#include "coordinates.h"
// 弧度转角度
double rad2deg(double rad)
{
return rad * 180.0 / PI;
}
// 角度转弧度
double deg2rad(double deg)
{
return deg * PI / 180.0;
}
// 计算子午圈半径
double getRn(double B)
{
return a / sqrt(1.0 - e * e * sin(B) * sin(B));
}
// 计算卯酉圈半径
double getRm(double B)
{
return a * (1.0 - e * e) / pow(1.0 - e * e * sin(B) * sin(B), 1.5);
}
// BLH坐标系转XYZ坐标系
XYZ BLH2XYZ(BLH blh)
{
XYZ xyz;
double N = getRn(blh.B);
xyz.X = (N + blh.H) * cos(blh.B) * cos(blh.L);
xyz.Y = (N + blh.H) * cos(blh.B) * sin(blh.L);
xyz.Z = (N * (1 - e * e) + blh.H) * sin(blh.B);
return xyz;
}
// XYZ坐标系转BLH坐标系
BLH XYZ2BLH(XYZ xyz)
{
BLH blh;
double B0 = atan2(xyz.Z, sqrt(xyz.X * xyz.X + xyz.Y * xyz.Y));
double H = 0.0;
double N;
do
{
N = getRn(B0);
H = sqrt(xyz.X * xyz.X + xyz.Y * xyz.Y) / cos(B0) - N;
B0 = atan2(xyz.Z, sqrt(xyz.X * xyz.X + xyz.Y * xyz.Y) * (1.0 - e * e * N / (N + H)));
} while (fabs(H) > 1e-6); // 迭代计算高程
blh.B = B0;
blh.L = atan2(xyz.Y, xyz.X);
blh.H = H;
return blh;
}
// XYZ坐标系减法
XYZ XYZminus(XYZ xyz1, XYZ xyz2)
{
XYZ xyz;
xyz.X = xyz1.X - xyz2.X;
xyz.Y = xyz1.Y - xyz2.Y;
xyz.Z = xyz1.Z - xyz2.Z;
return xyz;
}
// XYZ坐标系求模
double XYZmod(XYZ xyz)
{
return sqrt(xyz.X * xyz.X + xyz.Y * xyz.Y + xyz.Z * xyz.Z);
}
// BLH坐标系转ENU坐标系
ENU BLH2ENU(BLH blh1, BLH blh2)
{
XYZ xyz1 = BLH2XYZ(blh1);
XYZ xyz2 = BLH2XYZ(blh2);
XYZ dxyz = XYZminus(xyz2, xyz1);
double B = blh1.B;
double L = blh1.L;
ENU enu;
enu.E = -sin(L) * dxyz.X + cos(L) * dxyz.Y;
enu.N = -sin(B) * cos(L) * dxyz.X - sin(B) * sin(L) * dxyz.Y + cos(B) * dxyz.Z;
enu.U = cos(B) * cos(L) * dxyz.X + cos(B) * sin(L) * dxyz.Y + sin(B) * dxyz.Z;
return enu;
}
```
`main.cpp` 中包含主函数和测试函数:
```c++
#include "coordinates.h"
#include <iostream>
using namespace std;
int main()
{
BLH blh1 = { deg2rad(39.986244), deg2rad(116.304717), 50.0 };
BLH blh2 = { deg2rad(39.986501), deg2rad(116.305184), 60.0 };
XYZ xyz1 = BLH2XYZ(blh1);
XYZ xyz2 = BLH2XYZ(blh2);
XYZ dxyz = XYZminus(xyz2, xyz1);
double dist = XYZmod(dxyz);
ENU enu = BLH2ENU(blh1, blh2);
cout << "xyz1: (" << xyz1.X << ", " << xyz1.Y << ", " << xyz1.Z << ")" << endl;
cout << "xyz2: (" << xyz2.X << ", " << xyz2.Y << ", " << xyz2.Z << ")" << endl;
cout << "dxyz: (" << dxyz.X << ", " << dxyz.Y << ", " << dxyz.Z << ")" << endl;
cout << "dist: " << dist << " meters" << endl;
cout << "enu: (" << enu.E << ", " << enu.N << ", " << enu.U << ")" << endl;
return 0;
}
```
测试函数中计算了两个 BLH 坐标系点的距离,转化为 XYZ 坐标系后计算差值和模长,同时计算了这两个点在 ENU 坐标系中的坐标。
阅读全文