代码之家  ›  专栏  ›  技术社区  ›  dummzeuch Stijn Sanders

如何计算两个WGS84坐标之间的方位角(向北的角度)

  •  10
  • dummzeuch Stijn Sanders  · 技术社区  · 16 年前

    我有两个wgs84坐标,经纬度。这些点距离相当近,例如只有一米远。

    有没有一个简单的方法来计算这些点之间的线的方位角,也就是到北方的角度?

    幼稚的方法是假设一个笛卡尔坐标系(因为这些点非常接近),然后只使用

    sin(a)=abs(l2-l1)/sqrt(sqr(l2-l1)+sqr(b2-b1)

    方位角 l1,l2=经度 b1,b2=纬度

    由于两个纵向度数之间的距离越来越小于两个纬度度数之间的距离(保持不变),因此当坐标远离赤道时,误差将更大。

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

    也许我可以根据纬度确定一个近似的纵向修正系数,并使用如下公式:

    sin(a)=abs(l2*f-l1*f)/sqrt(sqr(l2*f-l1*f)+sqr(b2-b1)

    其中f是修正系数

    有什么暗示吗?

    (我不想为此使用任何库,尤其是不需要运行时许可证的库。任何一个简单的Delphi源都是很好的。)

    6 回复  |  直到 6 年前
        1
  •  10
  •   Wouter van Nifterick Andrey    16 年前

    本文中引用的公式是计算两点之间的大圆距离。以下是我如何计算点之间的角度:

    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;
    
    • 记住处理两点相等的情况(检查结果是否等于cno_角,或者修改函数以抛出异常);

    • 这个函数假设你在一个平面上。对于你提到的小距离,这一切都很好,但是如果你要计算世界各地城市之间的航向,你可能会想研究一些具有地球形状的东西;

    • 最好为该函数提供已经映射到平面的坐标。你可以直接把wgs84纬度输入y(把lon输入x),得到一个粗略的近似值。

        2
  •  5
  •   Jader Dias    15 年前

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

    编辑 我把以前的难看的解决方案换成了“沃特的解决方案:

    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);
    }
    
        3
  •  3
  •   Community CDub    8 年前

    我找到了这个链接

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

    在答案中给出

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

    这看起来很有希望,尤其是在接近尾端的平面地球近似值。

        4
  •  2
  •   Yosy    15 年前

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

        5
  •  0
  •   skamradt    16 年前

    我建议实现一个基于经度的修正系数。我执行了一次模拟程序,返回特定地点X英里内的所有地理编码记录,并遇到了模拟问题。不幸的是,我已经没有代码了,似乎无法回忆起我是如何到达修正数的,但你走的是正确的轨道。

        6
  •  0
  •   Meta Mussel    6 年前

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

    这个函数假设你在一个平面上。对于你提到的小距离,这一切都很好,但是如果你要计算世界各地城市之间的航向,你可能会想研究一些具有地球形状的东西;

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