查找一个角度与另一个角度是否在 X 度范围内

发布于 2024-08-07 20:32:18 字数 243 浏览 6 评论 0原文

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

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

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

I need an algorithm to figure out if one angle is within a certain amount of degrees from another angle.

My first thought was (a-x < b) && (a+x > b), but it fails when it has to work with angles that wrap around from -179 to 180.

In the diagram above, the region (green) that the angle must be between wraps between the negative and positive sides. How can I determine whether the angle (the red line) falls inside this region?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

快乐很简单 2024-08-14 20:32:18

尝试这个公式:

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";
}

?>

try this formula:

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

Or, in 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";
}

?>
玩心态 2024-08-14 20:32:18

正如马塞尔正确指出的那样,负数取模可能存在问题。另外,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 0 <= x 360;
  2. 计算两个法线角之间的最短角。

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

  • x >= 0:Normal = 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。

As Marcel rightly points out, modulo on negative numbers is potentially problematic. Also, what is the difference between 355 and 5 degrees? It might be worked out to be 350 degrees but 10 degrees is probably what people are expecting. We make the following assumptions:

  1. we want the smallest positive angle between two other angles so 0 <= diff <= 180;
  2. we are working in degrees. If radians, substitute 360 for 2*PI;
  3. angles can be positive or negative can be outside the range -360 < x < 360 where x is an input angle and
  4. order of input angles or the direction of the difference is irrelevant.

Inputs: angles a and b. So the algorithm is simply:

  1. Normalize a and b to 0 <= x < 360;
  2. Compute the shortest angle between the two normal angles.

For the first step, to convert the angle to the desired range, there are two possibilities:

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

The second is designed to remove any ambiguity on the difference in interpretation of negative modulus operations. So to give a worked example for x = -400:

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

then

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

so for inputs 10 and -400 the normal angles are 10 and 320.

Now we calculate the shortest angle between them. As a sanity check, the sum of those two angles must be 360. In this case the possibilities are 50 and 310 (draw it and you'll see this). To work these out:

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

So for our example:

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

You'll note normal1 + normal2 = 360 (and you can even prove this will be the case if you like).

Lastly:

diff = min(normal1, normal2)

or 50 in our case.

手心的温暖 2024-08-14 20:32:18

您还可以使用点积:

cos(a)*cos(b) + sin(a)*sin(b) >= cos(x)

You can also use a dot product:

cos(a)*cos(b) + sin(a)*sin(b) >= cos(x)
今天小雨转甜 2024-08-14 20:32:18

对于半径为 1 的情况,直线端点之间的距离为 2sin((ab/2)。因此丢弃 2,因为您只对比较感兴趣,并将 sin(x/2) 与 sin((ab)/ 2). 三角函数负责所有的包装。

For a radius of 1, the distance between the line endpoints is 2sin((a-b/2). So throw away the 2 since you are only interested in a comparison, and compare sin(x/2) with sin((a-b)/2). The trig functions take care of all the wrapping.

转瞬即逝 2024-08-14 20:32:18

C++实现:

float diff = fabsf(angle1 - angle2);
bool isInRange = fmodf(diff, 360.0f) <= ANGLE_RANGE ||
                 360.0f - fmodf(diff, 360.0f) <= ANGLE_RANGE;

c++ implementation:

float diff = fabsf(angle1 - angle2);
bool isInRange = fmodf(diff, 360.0f) <= ANGLE_RANGE ||
                 360.0f - fmodf(diff, 360.0f) <= ANGLE_RANGE;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文