Finding Signed Angle Between Vectors
Asked Answered
C

2

40

How would you find the signed angle theta from vector a to b?

And yes, I know that theta = arccos((a.b)/(|a||b|)).

However, this does not contain a sign (i.e. it doesn't distinguish between a clockwise or counterclockwise rotation).

I need something that can tell me the minimum angle to rotate from a to b. A positive sign indicates a rotation from +x-axis towards +y-axis. Conversely, a negative sign indicates a rotation from +x-axis towards -y-axis.

assert angle((1,0),(0,1)) == pi/2.
assert angle((0,1),(1,0)) == -pi/2.
Crossways answered 27/1, 2010 at 20:34 Comment(0)
D
38

If you have an atan2() function in your math library of choice:

signed_angle = atan2(b.y,b.x) - atan2(a.y,a.x)
Digit answered 27/1, 2010 at 20:44 Comment(4)
What about a = (-1,1) and b = (-1,-1), where the answer should be pi/2? You should check if the absolute value is bigger than pi, and then add or subtract 2*pi if it is.Offhand
@Derek Good catch. I actually discovered this myself while implementing the solution.Crossways
it is not very appropriate for example for computer graphics because it confuse -pi and pi if I have a = {-1, 0} and b = {0, 1}.Garlic
In degree, the result of this answer should be [-180, 180), but some time I discover result like: 358.5. Derek Ledbetter's answer works fine.Atul
O
78

What you want to use is often called the “perp dot product”, that is, find the vector perpendicular to one of the vectors, and then find the dot product with the other vector.

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

You can also do this:

angle = atan2( a.x*b.y - a.y*b.x, a.x*b.x + a.y*b.y );
Offhand answered 27/1, 2010 at 21:44 Comment(10)
do you know whether the second equation always return angles less than 180º?Main
The angle will be between -pi and pi radians, inclusive.Offhand
great that solves the issue when a = (-1,1) and b = (-1,-1) pointed aboveMain
Man, this was all that I needed! Works flawlessy in 2d, thanks!Anastomosis
All other duplicate questions should link to this question and this answer; this is so sparsely documented (doesn't even have a wikipedia article)Arachne
And how would that look like in 3d?Effy
Can you elaborate how the 2nd version works? Specifically the calculations you pass into atan2.Ileanaileane
@Ileanaileane The first parameter is the determinant, the second one the dot product. See also this answer.Tyner
@RoiDanton Thank you!Ileanaileane
didn't produce the correct angle between -Pi and Pi for me, but this answer didLx
D
38

If you have an atan2() function in your math library of choice:

signed_angle = atan2(b.y,b.x) - atan2(a.y,a.x)
Digit answered 27/1, 2010 at 20:44 Comment(4)
What about a = (-1,1) and b = (-1,-1), where the answer should be pi/2? You should check if the absolute value is bigger than pi, and then add or subtract 2*pi if it is.Offhand
@Derek Good catch. I actually discovered this myself while implementing the solution.Crossways
it is not very appropriate for example for computer graphics because it confuse -pi and pi if I have a = {-1, 0} and b = {0, 1}.Garlic
In degree, the result of this answer should be [-180, 180), but some time I discover result like: 358.5. Derek Ledbetter's answer works fine.Atul

© 2022 - 2024 — McMap. All rights reserved.