我需要一种算法来确定一个角度是否与另一个角度相差一定角度。我的第一个想法是
(a-x < b) && (a+x > b)
,但当它必须处理从-179到180的角度时,它会失败。在上图中,角度必须在绿色区域内,该区域(绿色)在负侧和正侧之间环绕。我如何确定角度(红线)是否落在此区域内?(a-x < b) && (a+x > b)
,但当它必须处理从-179到180的角度时,它会失败。在上图中,角度必须在绿色区域内,该区域(绿色)在负侧和正侧之间环绕。我如何确定角度(红线)是否落在此区域内?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";
}
?>
0 <= diff <= 180
;2*PI
;-360 < x < 360
,其中x是输入角度;输入:角度a和b。因此,算法很简单:
0 <= x < 360
;对于第一步,将角度转换为所需范围,有两种可能性:
x >= 0
:normal = x % 360x < 0
:normal = (-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。
你也可以使用点积:
cos(a)*cos(b) + sin(a)*sin(b) >= cos(x)
对于半径为1的情况,线段端点之间的距离为2sin((a-b/2))。因此,忽略掉2,因为你只关心比较,然后将sin(x/2)与sin((a-b)/2)进行比较。三角函数会处理所有的包裹问题。
c++ 实现:
float diff = fabsf(angle1 - angle2);
bool isInRange = fmodf(diff, 360.0f) <= ANGLE_RANGE ||
360.0f - fmodf(diff, 360.0f) <= ANGLE_RANGE;