【问题标题】:How do I calculate the Azimuth (angle to north) between two WGS84 coordinates如何计算两个 WGS84 坐标之间的方位角(向北的角度)
【发布时间】:2010-10-13 03:43:58
【问题描述】:

我有两个 WGS84 坐标,以度为单位的纬度和经度。这些点相当接近,例如相距仅一米。

有没有简单的方法可以计算出这些点之间连线的方位角,也就是向北的角度?

天真的方法是假设一个笛卡尔坐标系(因为这些点非常靠近)然后使用

sin(a) = abs(L2-L1) / sqrt(sqr(L2-L1) + sqr(B2-B1))

a = 方位角 L1, L2 = 经度 B1, B2 = 纬度

随着坐标远离赤道,误差会更大,因为两个经度之间的距离变得越来越小于两个纬度之间的距离(保持不变)。

我发现了一些非常复杂的公式,我真的不想实现它们,因为它们对于那些靠得很近的点来说似乎有点矫枉过正,我不需要非常高的精度(两位小数就足够了,一个可能就可以了要么因为还有其他因素会降低精度,比如 GPS 返回的那个)。

也许我可以根据纬度确定一个近似的纵向校正因子,然后使用这样的东西:

sin(a) = abs(L2*f-L1*f) / sqrt(sqr(L2*f-L1*f) + sqr(B2-B1))

其中 f 是校正因子

有什么提示吗?

(我不想为此使用任何库,尤其是那些需要运行时许可证的库。任何 MPLed Delphi 源都很棒。)

【问题讨论】:

  • 对于它的价值,您正在寻找的术语是“标题”。

标签: delphi geolocation geospatial


【解决方案1】:

你在文中引用的公式是计算两点之间的大圆距离。以下是我计算点之间角度的方法:

uses Math, ...;
...

const
  cNO_ANGLE=-999;

...

function getAngleBetweenPoints(X1,Y1,X2,Y2:double):double;
var
  dx,dy:double;
begin
  dx := X2 - X1;
  dy := Y2 - Y1;

  if (dx > 0) then  result := (Pi*0.5) - ArcTan(dy/dx)   else
  if (dx < 0) then  result := (Pi*1.5) - ArcTan(dy/dx)   else
  if (dy > 0) then  result := 0                          else
  if (dy < 0) then  result := Pi                         else
                    result := cNO_ANGLE; // the 2 points are equal

  result := RadToDeg(result);
end;
  • 记得处理2点相等的情况(检查结果是否等于cNO_ANGLE,或者修改函数抛出异常);

  • 此功能假定您在平坦的表面上。你提到的距离很短,这一切都很好,但如果你要计算世界各地城市之间的航向,你可能想研究一下地球形状的东西;

  • 最好为这个函数提供已经映射到平面的坐标。不过,您可以将 WGS84 Latitude 直接输入 Y(并将 lon 输入 X)以获得粗略的近似值。

【讨论】:

  • 很好的解决方案!我把它翻译成 C# 来代替我之前的答案。
  • @Martin Beckett:是的,atan2 对Atan2(dy;dx) 也是如此,但是当然负的 dx 会返回一个负值,必须将其添加到 360。必须处理 0分开。
【解决方案2】:

这里是 C# 解决方案。测试了 0、45、90、135、180、225、270 和 315 角度。

编辑我用 Wouter 解决方案的 C# 翻译替换了我之前丑陋的解决方案:

public double GetAzimuth(LatLng destination)
{
    var longitudinalDifference = destination.Lng - this.Lng;
    var latitudinalDifference = destination.Lat - this.Lat;
    var azimuth = (Math.PI * .5d) - Math.Atan(latitudinalDifference / longitudinalDifference);
    if (longitudinalDifference > 0) return azimuth;
    else if (longitudinalDifference < 0) return azimuth + Math.PI;
    else if (latitudinalDifference < 0) return Math.PI;
    return 0d;
}
public double GetDegreesAzimuth(LatLng destination)
{
    return RadiansToDegreesConversionFactor * GetAzimuth(destination);
}

【讨论】:

  • 最好使用 Math.Atan2 而不是 Math.Atan 来避免除法,尤其是避免除以零。额外的好处是它给出了一个范围为 -π .. +π 的答案,从而避免了你在最后所做的更正。
【解决方案3】:

我找到了这个链接

http://williams.best.vwh.net/avform.htm

在答案中给出

Lat/Lon + Distance + Heading --> Lat/Lon

这看起来很有希望,尤其是在接近尾声时给出的平坦地球近似值。

【讨论】:

    【解决方案4】:

    这仅适用于小的差异。否则你不能只是“纬度差异/纵向差异”。

    【讨论】:

      【解决方案5】:

      我建议实施基于经度的校正因子。我实施了一次类似的例程,以返回特定地点 x 英里内的所有地理编码记录,并遇到了类似的问题。不幸的是,我没有代码了,而且似乎不记得我是如何得到更正号码的,但你在正确的轨道上。

      【讨论】:

        【解决方案6】:

        有人测试过吗?它不会返回正确的答案

        此功能假定您在平坦的表面上。你提到的距离很短,这一切都很好,但如果你要计算世界各地城市之间的航向,你可能想研究一下地球形状的东西; em>

        你的平坦地球与此无关。正如你所说,这个错误是因为你正在计算一个点的初始方位角。除非你直奔电线杆,否则你与电线杆的关系会随着距离而改变。无论如何,上述程序不会返回正确的结果。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-08-04
          • 1970-01-01
          • 2011-12-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多