寻找两个方位角之间的夹角。

11
给定两个方向角,如何找到它们之间的最小角度?
例如,如果一个方向角为340度,第二个方向角为10度,则最小角度将为30度。
我附上一张图片来说明我的意思。我尝试将一个方向角减去另一个方向角,但由于圆形的环绕效应,这种方法行不通。我还尝试使用负度数(180-359为-180到0),但在计算正负数之间的角度时,这种方法会出现问题。
我相信一定有一种更简单的方法,而不是使用大量if语句。
感谢您的帮助。 Adam
顺便说一下,这是一个导航问题,所以圆的半径未知。

模运算符在这里会非常有帮助。 - Hovercraft Full Of Eels
6个回答

19

我最终使用了在这个留言板上找到的以下公式,因为我需要根据方向(顺时针或逆时针)对结果进行符号化。 它对正在发生的事情有很好的解释。

((((bearing - heading) % 360) + 540) % 360) - 180

如果 |bearing - heading| <= 360 =: Bound,则初始的%360是不必要的。如果Bound更大,还可以将360的倍数添加到540。 - user66081

12
float getDifference(float a1, float a2) {
    return Math.min((a1-a2)<0?a1-a2+360:a1-a2, (a2-a1)<0?a2-a1+360:a2-a1)
}

谢谢,那很管用。我一直在尝试解决这个问题6个小时了! - Adam Davies
2
等价于:Math.min((a1 - a2 + 360) % 360, (a2 - a1 + 360) % 360)(对于其他语言,如不支持浮点数的 %,请使用 fmodIEERemainder 等函数)。 - Tim Sylvester
太棒了,你让我的一天都变得美好了。 - FerDensetsu

7

关于什么:

angle = Math.abs(a1-a2);
if (angle > 180)
    angle = 360 - angle;

你提到了一个关于正负数的问题,也许我没有考虑到什么...

我相信你的答案和我的是等价的,只不过可能更容易理解一些。另一个选项看起来像是我们已经得到的两个选项之间的交叉,即 Math.min(Math.abs(a1-a2), 360 - Math.abs(a1-a2)); - Rob Watts
它们在本质上是等价的,因为它们都是正确和有效的。在我看来,你的实现将问题视为OP算法正确性的问题,而我则认为这是格式化已经正确的值的问题。这两种方法都是看待问题的有效方式,我认为在方法上有足够的差异,两者都具有价值。 - femtoRgon

2

为了导航,你可能想知道b1在b2的左边还是右边,因此这里有一个漂亮的函数。(假设0不是使用情况)

function isLeftOf(b1, b2) { return b1.x < b2.x; }
function isBearing1LeftOrRightOfBearing2 (b1, b2) {
  if (Math.sign(((b1 - b2 + 540) % 360) - 180) > 0) {
    return 'left'
  } else {
    return 'right'
  }
}

1
如果需要角度方向,则这将起作用:
    int maxBearing = Math.max(bearing0, bearing1);
    int minBearing = Math.min(bearing0, bearing1);
    int firstDir = maxBearing - minBearing;  
    int secondDir = minBearing + 360 - maxBearing;  
    int diff = Math.min(firstDir, secondDir);

    boolean anticlock_dir = false;

    int anticlock = bearing1 + diff;
    if (anticlock >= 360)
        anticlock = anticlock - 360;

    if (anticlock ==  bearing0)
        anticlock_dir = true;

1

你需要考虑双向的差异。

public static double bearingDiff(double a, double b) {
    double maxBearing = Math.max(a, b);
    double minBearing = Math.min(a, b);
    double antiClockwiseDiff = maxBearing - minBearing;
    double clockwiseDiff = minBearing + 360 - maxBearing;
    return Math.min(antiClockwiseDiff, clockwiseDiff);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接