2009-12-10 101 views
96

给定围绕坐标的-PI-> PI范围内的2个角度,它们之间的2个角度中的最小值是多少?2角之间的最小差异

考虑到PI和-PI之间的差异不是2PI,而是零。

实施例:

想象一个圆圈,用2线从中心出来,还有那些线之间的2个角度,它们使在里面又名较小角度的角度,和所述角度他们在外面制造,又名大角度。两个角度加起来形成一个完整的圆。假设每个角度都可以在一定范围内,角度值越小,考虑到翻转

+2

在我明白你的意思之前,我读了3次。请添加一个例子,或者更好地解释... – Kobi 2009-12-10 06:12:04

+0

想象一个圆,从中心向外划出两条线,这两条线之间有两个角度,它们在内部形成的角度又称为较小的角度,以及它们形成的角度在外面,也就是更大的角度。两个角度加起来形成一个完整的圆。考虑到每个角度都可以在一定的范围内,考虑到翻转,角度值越小越好 – 2009-12-10 06:14:32

+0

[如何计算直线与横轴之间的角度?](https://stackoverflow.com/questions/7586063/how-to-calculation-the-angle-between-a-line-and-the-horizo​​ntal-axis) – 2017-07-09 20:33:49

回答

135

这使任何角度签署的角度:

a = targetA - sourceA 
a = (a + 180) % 360 - 180 

当心在许多语言中modulo操作返回的值与与红利相同的符号(如C,C++,C#,JavaScript,full list here)。这需要一个定制mod功能,像这样:

mod = (a, n) -> a - floor(a/n) * n 

或者说:

mod = (a, n) -> (a % n + n) % n 

如果角度在[-180,180]这也适用:

a = targetA - sourceA 
a += (a>180) ? -360 : (a<-180) ? 360 : 0 

在更详细方式:

a = targetA - sourceA 
a -= 360 if a > 180 
a += 360 if a < -180 
+0

更简单,更有意义的朗读,尽管实际上是同样的东西,第一个bti计算出角度,第二个部分确保它始终是2个可能角度中较小的一个 – 2011-10-25 11:48:29

+1

,尽管人们可能想要做一个%360,例如。如果我有角度0和目标角度721,正确的答案将是1,上面给出的答案将是361 – 2011-10-25 11:51:56

+0

是的,这是真实的和有意的,但绝对值得指出。在我的例子中,我先前从'atan2'得到了'targetA'和'sourceA',因此它们的绝对角度决不会大于360. – bennedich 2011-10-26 01:31:56

30

如果你的两个角度是x和y,那么它们之间的角度之一是abs(x - Y)。另一个角度是(2 * PI) - abs(x - y)。这样的最小的2角的值是:

min((2 * PI) - abs(x - y), abs(x - y)) 

这给你的角度的绝对值,它假定输入是归一化(即:范围[0, 2π)内)。

如果要保留角度的符号(即:方向),并且也接受范围[0, 2π)以外的角度,则可以概括上述内容。这里是广义的版本Python代码:

PI = math.pi 
TAU = 2*PI 
def smallestSignedAngleBetween(x, y): 
    a = (x - y) % TAU 
    b = (y - x) % TAU 
    return -a if a < b else b 

注意,%运营商不具有相同的行为在所有的语言,特别是当负值都参与其中,所以如果移植一些迹象的调整可能是必要的。

+0

测试套件失败https://gist.github.com/bradphelan/7fe21ad8ebfcb43696b8 – bradgonesurfing 2015-07-13 08:45:19

+1

@bradgonesurfing这是/是真的,但公平地说,你的测试检查了东西原始问题中没有指定,特别是非标准化的输入和标志保存。编辑答案中的第二个版本应该通过您的测试。 – 2015-07-23 19:20:31

105

x是目标角度。 y是源或起始角度:

atan2(sin(x-y), cos(x-y)) 

它返回带符号的增量角度。请注意,根据您的API,atan2()函数的参数顺序可能不同。

+3

这个工程。为什么? – ericsoco 2013-05-11 18:25:52

+8

'x-y'给你角度的不同,但它可能超出了期望的范围。想想这个角度定义单位圆上的一个点。该点的坐标是'(cos(x-y),sin(x-y))'。 'atan2'返回该点的角度(相当于'x-y'),除了它的范围是[-PI,PI]。 – Max 2013-09-02 16:17:55

+1

这通过测试套件https://gist.github.com/bradphelan/7fe21ad8ebfcb43696b8 – bradgonesurfing 2015-07-13 08:43:09

7

我升到提供签名回答的挑战:

def f(x,y): 
    import math 
    return min(y-x, y-x+2*math.pi, y-x-2*math.pi, key=abs) 
+1

啊...答案是顺便说一句Python函数。对不起,我暂时处于Python模式。希望没关系。 – 2010-01-05 16:20:46

+0

我会在楼上的代码中插入新的公式,看看会发生什么!(thankyou^_ ^) – 2010-01-05 17:25:42

+1

我很确定PeterB的回答也是正确的。和evilly hackish。 :) – 2010-01-05 18:04:17

5

Ari (与算法相反)解决方案:

angle = Pi - abs(abs(a1 - a2) - Pi); 
+0

测试套件失败https://gist.github.com/bradphelan/7fe21ad8ebfcb43696b8 – bradgonesurfing 2015-07-13 08:39:58

2

没有必要计算三角函数。在C语言中的简单代码:

#include <math.h> 
#define PIV2 M_PI+M_PI 
#define C360 360.0000000000000000000 
double difangrad(double x, double y) 
{ 
double arg; 

arg = fmod(y-x, PIV2); 
if (arg < 0) arg = arg + PIV2; 
if (arg > M_PI) arg = arg - PIV2; 

return (-arg); 
} 
double difangdeg(double x, double y) 
{ 
double arg; 
arg = fmod(y-x, C360); 
if (arg < 0) arg = arg + C360; 
if (arg > 180) arg = arg - C360; 
return (-arg); 
} 

让DIF = A - B,弧度

dif = difangrad(a,b); 

让DIF = A - B,以度

dif = difangdeg(a,b); 

difangdeg(180.000000 , -180.000000) = 0.000000 
difangdeg(-180.000000 , 180.000000) = -0.000000 
difangdeg(359.000000 , 1.000000) = -2.000000 
difangdeg(1.000000 , 359.000000) = 2.000000 

没有罪,没有COS,没有棕褐色,....只有几何!

+4

错误!由于您将PIV2定义为“M_PI + M_PI” ,而不是“(M_PI + M_PI)“,行'arg = arg - PIV2;'扩展为'arg = arg - M_PI + M_PI',所以什么都不做。 – canton7 2014-01-19 11:53:03