寻找向量之间的有向角

38

如何从向量a到b中找到带符号的角度theta?

是的,我知道theta = arccos((a.b)/(|a||b|))。

然而,它不包含符号(即它不能区分顺时针或逆时针旋转)。

我需要找到一个能告诉我从a到b旋转的最小角度的方法。正号表示从+x轴旋转到+y轴,反之,负号表示从+x轴旋转到-y轴。

assert angle((1,0),(0,1)) == pi/2.
assert angle((0,1),(1,0)) == -pi/2.
2个回答

75

你想要使用的通常称为“垂线点积”,即找到与其中一个向量垂直的向量,然后找到它与另一个向量的点积。

if(a.x*b.y - a.y*b.x < 0)
    angle = -angle;

你也可以这样做:

angle = atan2( a.x*b.y - a.y*b.x, a.x*b.x + a.y*b.y );

3
角度将在-π和π弧度之间,包括两端。 - Derek Ledbetter
1
兄弟,这就是我需要的!在二维中完美地工作,谢谢! - Gustavo Maciel
5
所有其他重复的问题都应该链接到这个问题和答案;这个问题的文档非常稀少(甚至没有维基百科文章)。 - bright-star
4
你能详细说明第二个版本是如何工作的吗?特别是你传递给 atan2 的计算。 - Tara
2
@Tara 第一个参数是行列式,第二个参数是点积。另请参见此答案 - Roi Danton
显示剩余5条评论

38

如果你的数学库中有 atan2() 函数:

signed_angle = atan2(b.y,b.x) - atan2(a.y,a.x)

9
a=(-1,1)和b=(-1,-1),答案应该是pi/2。你需要检查绝对值是否大于pi,如果是,则加上或减去2*pi。 - Derek Ledbetter
@Derek 很好的发现。实际上,在实施解决方案时我自己也发现了这个问题。 - Cerin
1
这并不是很适合计算机图形学的例子,因为如果我有a = {-1, 0}和b = {0,1},它会混淆-pi和pi。 - user2083364
在角度制中,这个答案的结果应该是[-180, 180),但有时我会发现结果像:358.5。 Derek Ledbetter的答案很好用。 - Helin Wang

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