8

我需要一种算法来确定一个角度是否在另一个角度的一定度数内。

我的第一个想法是(a-x < b) && (a+x > b),但是当它必须使用从 -179 到 180 的角度时它会失败。

在上图中,夹角必须位于的区域(绿色)包含在负侧和正侧之间。如何确定角度(红线)是否在该区域内?

4

5 回答 5

6

试试这个公式:

360-(|a-b|)%360<x || (|a-b|)%360<x

或者,在 PHP 中

<?php

$b = 10;
$angle1 = -179;
$angle2 = 180;

$diff = $angle1 - $angle2;
if(abs($diff % 360) <= $b || (360-abs($diff % 360))<=$b) {
  echo "yes";
} else {
  echo "no";
}

?>
于 2009-10-17T02:55:45.103 回答
2

正如马塞尔正确指出的那样,对负数取模可能存在问题。另外,355度和5度有什么区别?它可能被计算为 350 度,但 10 度可能是人们所期望的。我们做出以下假设:

  1. 我们想要其他两个角度之间的最小正角度0 <= diff <= 180
  2. 我们正在度数工作。如果是弧度,用 360 代替2*PI;
  3. 角度可以是正数或负数 可以-360 < x < 360在 x 是输入角度的范围之外,并且
  4. 输入角度的顺序或差异的方向无关紧要。

输入:角度 a 和 b。所以算法很简单:

  1. 将 a 和 b 标准化为0 <= x < 360;
  2. 计算两个法线角之间的最短角。

第一步,要将角度转换为所需范围,有两种可能性:

  • x >= 0: 正常 = x % 360
  • x < 0: 正常 = (-x / 360 + 1) * 360 + x

第二个旨在消除对负模运算的解释差异的任何歧义。因此,举一个 x = -400 的工作示例:

  -x / 360 + 1
= -(-400) / 360 + 1
= 400 / 360 + 1
= 1 + 1
= 2

然后

normal = 2 * 360 + (-400)
       = 320

因此对于输入 10 和 -400,法线角度为 10 和 320。

现在我们计算它们之间的最短角度。作为一个健全的检查,这两个角度的总和必须是 360。在这种情况下,可能性是 50 和 310(画出来,你会看到这个)。要解决这些问题:

normal1 = min(normal(a), normal(b))
normal2 = max(normal(a), normal(b))
angle1 = normal2 - normal1
angle2 = 360 + normal1 - normal2

所以对于我们的例子:

normal1 = min(320, 10) = 10
normal2 = max(320, 10) = 320
angle1 = normal2 - normal1 = 320 - 10 = 310
angle2 = 360 + normal1 - normal2 = 360 + 10 - 320 = 50

你会注意到normal1 + normal2 = 360(如果你愿意,你甚至可以证明会是这种情况)。

最后:

diff = min(normal1, normal2)

或者在我们的例子中是 50。

于 2009-10-17T02:54:01.597 回答
2

您还可以使用点积:

cos(a)*cos(b) + sin(a)*sin(b) >= cos(x)
于 2009-10-17T03:38:41.257 回答
1

对于半径 1,线端点之间的距离是 2sin((ab/2)。所以扔掉 2,因为您只对比较感兴趣,并将 sin(x/2) 与 sin((ab)/ 进行比较2). trig 函数负责所有的包装。

于 2009-12-10T05:41:32.763 回答
0

c++ 实现:

float diff = fabsf(angle1 - angle2);
bool isInRange = fmodf(diff, 360.0f) <= ANGLE_RANGE ||
                 360.0f - fmodf(diff, 360.0f) <= ANGLE_RANGE;
于 2014-01-01T23:31:51.250 回答