ECEF坐标系转经纬度 wgs84 - 方法提炼
本文提供坐标系转换算法,根据某前端算法修改完善为C#语言支持。
最近在项目中遇到空间坐标转换问题,现提供相关算法C#支持。
源代码
相关代码如下:
using System;
namespace ConsoleApp1
{
/// <summary>
/// ECEF坐标系转换经纬度 wgs84
/// 方法提炼
/// </summary>
internal class Program
{
private static void Main(string[] args)
{
double[] ret = XYZ2LLA(new double[]
{
3333,4444,1500
});
Console.WriteLine(string.Format("LON-:{0}\r\nLAT-:{1}\r\nALT-:{2}\r\n", ret[0], ret[1], ret[2]));
Console.Read();
}
private static double EARTH_1 = 6378.137;
private static double Temp_1 = EARTH_1 * (1.0 - (1.0 / 298.257223563));
private static double Eccsq = 1 - Math.Pow(Temp_1, 2) / Math.Pow(EARTH_1, 2);
private static double Dtr = Math.PI / 180.0;
/// <summary>
/// ECEF坐标系转经纬度 wgs84
/// 输入-千米、千米、千米
/// 输出-经、纬、千米
/// </summary>
/// <param name="xvec"></param>
/// <returns></returns>
private static double[] XYZ2LLA(double[] xvec)
{
double flatgc, flatn, dlat, rp, x, y, z, p, tangd, rn, clat, slat, flat, flon, altkm;
x = xvec[0];
y = xvec[1];
z = xvec[2];
rp = Math.Sqrt(Math.Pow(x, 2) + Math.Pow(y, 2) + Math.Pow(z, 2));
flatgc = Math.Asin(z / rp) / Dtr;
flon = ((Math.Abs(x) + Math.Abs(y)) < 1.0e-10) ? 0.0 : Math.Atan2(y, x) / Dtr;
flon = (flon < 0.0) ? flon + 360.0 : flon;
p = Math.Sqrt(Math.Pow(x, 2) + Math.Pow(y, 2));
if (p < 1.0e-10)
{
flat = ((z < 0.0)) ? -90.0 : 90.0;
altkm = rp - Radcur(flat)[0];
}
else
{
altkm = rp - Radcur(flatgc)[0];
flat = Gc2gd(flatgc, altkm);
rn = Radcur(flat)[1];
for (double kount = 0; kount < 5; kount++)
{
slat = Math.Sin(Dtr * flat);
tangd = (z + rn * Eccsq * slat) / p;
flatn = Math.Atan(tangd) / Dtr;
dlat = flatn - flat;
flat = flatn;
clat = Math.Cos(Dtr * flat);
rn = Radcur(flat)[1];
altkm = (p / clat) - rn;
if (Math.Abs(dlat) < 1.0e-12)
{
break;
}
}
}
return new double[] { flat, flon, altkm };
}
private static double Gc2gd(double flatgci, double altkmi)
{
double[] rrnrm = Radcur(flatgci);
double ratio = 1 - Math.Pow(Math.Sqrt(Eccsq), 2) * rrnrm[1] / (rrnrm[1] + altkmi);
double tlat = Math.Tan(Dtr * flatgci) / ratio;
rrnrm = Radcur((1 / Dtr) * Math.Atan(tlat));
ratio = 1 - Math.Pow(Math.Sqrt(Eccsq), 2) * rrnrm[1] / (rrnrm[1] + altkmi);
tlat = Math.Tan(Dtr * flatgci) / ratio;
return (1 / Dtr) * Math.Atan(tlat);
}
private static double[] Radcur(double lati)
{
double slat, dsq, rn, rho, z;
slat = Math.Sin(Dtr * lati);
dsq = 1.0 - Eccsq * Math.Pow(slat, 2);
rn = EARTH_1 / Math.Sqrt(dsq);
rho = rn * Math.Cos(Dtr * lati);
z = (1.0 - Eccsq) * rn * slat;
return (new double[] { Math.Sqrt(Math.Pow(rho, 2) + Math.Pow(z, 2)), rn, rn * (1.0 - Eccsq) / dsq });
}
}
}
2019年11月25日
Dawn