C#中的轴承计算
Bearing calculation in C#
我想计算 2 GPS 位置之间的方位,我愚弄了 this page 对我的算法的建议:
public static double Bearing(IPointGps pt1, IPointGps pt2)
{
double x = Math.Cos(pt1.Latitude) * Math.Sin(pt2.Latitude) - Math.Sin(pt1.Latitude) * Math.Cos(pt2.Latitude) * Math.Cos(pt2.Longitude - pt1.Longitude);
double y = Math.Sin(pt2.Longitude - pt1.Longitude) * Math.Cos(pt2.Latitude);
// Math.Atan2 can return negative value, 0 <= output value < 2*PI expected
return (Math.Atan2(y, x) + Math.PI * 2)%(Math.PI * 2);
}
然后我使用这种方法以度为单位转换我的值
public static double RadiansToDegrees(double angle)
{
return (angle * 180.0) / Math.PI;
}
我有以下测试样本:
- Point1(纬度,经度)= 43.6373638888888888888888888888889,1.357622222222222222222222222222222
- Point2(经纬度)= 43.615644444444444444444444444444,1.380225
- 预期方位 = 323°
然而,我获得了 315.5° (5.5062235835910762 rad) 的方位角。如果我计算预期的弧度值,我得到 5.637413 这毫无疑问我的问题出在我的轴承方法上。
我已经使用 .Net Math 包(包括 Cos、Sin、Tan 和 ATan 方法)实现了其他计算方法,并且我的单元测试以 1e-12 精度通过。我错过了什么?
PS:我还尝试重新实现 Atan2 方法,以防它不够精确。我得到了完全相同的结果
编辑:我的纬度和经度是双倍的,如下界面
public interface IPointGps
{
double Latitude { get; }
double Longitude { get; }
}
看起来你的纬度和经度变量是浮点数(单精度)。如果是这种情况,那么您将面临精度错误。
Math.Sin()
和所有类似的方法都需要以弧度为单位的参数,但你的纬度和经度是以度为单位的。在计算方位角之前,您必须将 IPointGps 转换为弧度,或者修改方位角计算,例如:
public static double Bearing(IPointGps pt1, IPointGps pt2)
{
double x = Math.Cos(DegreesToRadians(pt1.Latitude)) * Math.Sin(DegreesToRadians(pt2.Latitude)) - Math.Sin(DegreesToRadians(pt1.Latitude)) * Math.Cos(DegreesToRadians(pt2.Latitude)) * Math.Cos(DegreesToRadians(pt2.Longitude - pt1.Longitude));
double y = Math.Sin(DegreesToRadians(pt2.Longitude - pt1.Longitude)) * Math.Cos(DegreesToRadians(pt2.Latitude));
// Math.Atan2 can return negative value, 0 <= output value < 2*PI expected
return (Math.Atan2(y, x) + Math.PI * 2) % (Math.PI * 2);
}
public static double DegreesToRadians(double angle)
{
return angle * Math.PI / 180.0d;
}
returns轴承5.637716736134105
.
我想计算 2 GPS 位置之间的方位,我愚弄了 this page 对我的算法的建议:
public static double Bearing(IPointGps pt1, IPointGps pt2)
{
double x = Math.Cos(pt1.Latitude) * Math.Sin(pt2.Latitude) - Math.Sin(pt1.Latitude) * Math.Cos(pt2.Latitude) * Math.Cos(pt2.Longitude - pt1.Longitude);
double y = Math.Sin(pt2.Longitude - pt1.Longitude) * Math.Cos(pt2.Latitude);
// Math.Atan2 can return negative value, 0 <= output value < 2*PI expected
return (Math.Atan2(y, x) + Math.PI * 2)%(Math.PI * 2);
}
然后我使用这种方法以度为单位转换我的值
public static double RadiansToDegrees(double angle)
{
return (angle * 180.0) / Math.PI;
}
我有以下测试样本:
- Point1(纬度,经度)= 43.6373638888888888888888888888889,1.357622222222222222222222222222222
- Point2(经纬度)= 43.615644444444444444444444444444,1.380225
- 预期方位 = 323°
然而,我获得了 315.5° (5.5062235835910762 rad) 的方位角。如果我计算预期的弧度值,我得到 5.637413 这毫无疑问我的问题出在我的轴承方法上。
我已经使用 .Net Math 包(包括 Cos、Sin、Tan 和 ATan 方法)实现了其他计算方法,并且我的单元测试以 1e-12 精度通过。我错过了什么?
PS:我还尝试重新实现 Atan2 方法,以防它不够精确。我得到了完全相同的结果
编辑:我的纬度和经度是双倍的,如下界面
public interface IPointGps
{
double Latitude { get; }
double Longitude { get; }
}
看起来你的纬度和经度变量是浮点数(单精度)。如果是这种情况,那么您将面临精度错误。
Math.Sin()
和所有类似的方法都需要以弧度为单位的参数,但你的纬度和经度是以度为单位的。在计算方位角之前,您必须将 IPointGps 转换为弧度,或者修改方位角计算,例如:
public static double Bearing(IPointGps pt1, IPointGps pt2)
{
double x = Math.Cos(DegreesToRadians(pt1.Latitude)) * Math.Sin(DegreesToRadians(pt2.Latitude)) - Math.Sin(DegreesToRadians(pt1.Latitude)) * Math.Cos(DegreesToRadians(pt2.Latitude)) * Math.Cos(DegreesToRadians(pt2.Longitude - pt1.Longitude));
double y = Math.Sin(DegreesToRadians(pt2.Longitude - pt1.Longitude)) * Math.Cos(DegreesToRadians(pt2.Latitude));
// Math.Atan2 can return negative value, 0 <= output value < 2*PI expected
return (Math.Atan2(y, x) + Math.PI * 2) % (Math.PI * 2);
}
public static double DegreesToRadians(double angle)
{
return angle * Math.PI / 180.0d;
}
returns轴承5.637716736134105
.