我用c#编程。我想使用轴承和范围使用旧纬度经度计算新的纬度经度。我用这个公式:
φ2= asin(sinφ1·cosδ+cosφ1·sinδ·cosθ)
λ2=λ1+ atan2(sinθ·sinδ·cosφ1,cosδ-sinφ1·sinφ2)
其中φ是纬度,λ是经度,θ是轴承(从北到顺时针),δ是角距离d / R; d是行进的距离,R是地球的半径
来自this site。
这是我的c#代码:
/// <summary>
///
/// </summary>
/// <param name="oldLat">old latitude (radian)</param>
/// <param name="oldLon">old langitude (radian)</param>
/// <param name="range">range</param>
/// <param name="bearing">(radian)</param>
/// <param name="earthRadius"></param>
/// <param name="newLat">new latitude (radian)</param>
/// <param name="newLon">new longitude (radian)</param>
public static void CalculateNewLatLon(
double oldLat, double oldLon,
double range, double bearing, double earthRadius,
out double newLat, out double newLon)
{
newLat = Math.Asin(Math.Sin(oldLat) * Math.Cos(range / earthRadius) + Math.Cos(oldLat) * Math.Sin(range / earthRadius) * Math.Cos(bearing));
newLon = oldLon + Math.Atan2(Math.Sin(bearing) * Math.Sin(range / earthRadius) * Math.Cos(oldLat), Math.Cos(range / earthRadius) - Math.Sin(oldLat) * Math.Sin(newLat));
}
/// <summary>
/// Calculate new latitude and longitude according to old latitude and longitude
/// Note: All values which are related to geography are in degree unites
/// </summary>
/// <param name="oldLatitudeDegree">old latitude degree</param>
/// <param name="oldLatitudeMinute">old latitude minute</param>
/// <param name="oldLatitudeSecond">old latitude second</param>
/// <param name="oldLongtitudeDegree">old longitude degree</param>
/// <param name="oldLongtitudeMinute">old longitude minute</param>
/// <param name="oldLongtitudeSecond">old longitude second</param>
/// <param name="range">range</param>
/// <param name="bearing">bearing of movement (degree)</param>
/// <param name="earthRadius">radius of earth</param>
/// <param name="newLatitudeDegree">new latitude degree</param>
/// <param name="newLatitudeMinute">new latitude minute</param>
/// <param name="newLatitudeSecond">new latitude second</param>
/// <param name="newLongtitudeDegree">new longitude degree</param>
/// <param name="newLongtitudeMinute">new longitude minute</param>
/// <param name="newLongtitudeSecond">new longitude second</param>
public static void CalculateNewLatLon(
double oldLatitudeDegree, double oldLatitudeMinute, double oldLatitudeSecond,
double oldLongtitudeDegree, double oldLongtitudeMinute, double oldLongtitudeSecond,
double range, double bearing, double earthRadius,
out double newLatitudeDegree, out double newLatitudeMinute, out double newLatitudeSecond,
out double newLongtitudeDegree, out double newLongtitudeMinute, out double newLongtitudeSecond)
{
// Convert geographian DEG, MIN, SEC latitude to decimal degree
double decimalOldLatitudeDegree = Util.Converter.DegMinSecToDeg(
oldLatitudeDegree, oldLatitudeMinute, oldLatitudeSecond);
// Convert geographian DEG, MIN, SEC longtitude to decimal degree
double decimalOldLongtitudeDegree = Util.Converter.DegMinSecToDeg(
oldLongtitudeDegree, oldLongtitudeMinute, oldLongtitudeSecond);
// Convert degree latitude to radian
double oldLatitudeRadian = Util.Converter.DegreeToRadian(decimalOldLatitudeDegree);
// Convert degree longtitude to radian
double oldLongtitudeRadian = Util.Converter.DegreeToRadian(decimalOldLongtitudeDegree);
bearing = Util.Converter.DegreeToRadian(bearing);
// Calculating new latitude and new longtitude
// according to old latitude, old longtitude,
// range, bearing and earth radius
double newLatitudeRadian, newLongtitudeRadian;
CalculateNewLatLon(
oldLatitudeRadian, oldLongtitudeRadian,
range, bearing, earthRadius,
out newLatitudeRadian, out newLongtitudeRadian);
// Convert radian latitude longtitude to degree
double decimalNewLatitudeDegree = Util.Converter.RadianToDegree(newLatitudeRadian);
double decimalNewLongtitudeDegree = Util.Converter.RadianToDegree(newLongtitudeRadian);
// Convert decimal latitude degree to geographian DEG, MIN, SEC
Util.Converter.DegToDegMinSec(decimalNewLatitudeDegree,
out newLatitudeDegree, out newLatitudeMinute, out newLatitudeSecond);
// Convert decimal latitude degree to geographian DEG, MIN, SEC
Util.Converter.DegToDegMinSec(decimalNewLongtitudeDegree,
out newLongtitudeDegree, out newLongtitudeMinute, out newLongtitudeSecond);
}
在范围= 96NM(海里= 1825米)时,我看到现实世界中的值与根据命名网站计算的值之间存在巨大差异,我的代码非常出色。
有什么问题?
Haversine公式有一个很大的错误?
或者我的代码写错了?
注意:所有其他转换方法都经过测试。