How to find an angle in range(0, 360) between 2 vectors?

$\begingroup$

I know that the common approach in order to find an angle is to calculate the dot product between 2 vectors and then calculate arcus cos of it. But in this solution I can get an angle only in the range(0, 180) degrees. What would be the proper way to get an angle in range of (0, 360)?

$\endgroup$ 3

3 Answers

$\begingroup$

I'm adapting my answer on Stack Overflow.

2D case

Just like the dot product is proportional to the cosine of the angle, the determinant is proprortional to its sine. And if you know the cosine and the sine, then you can compute the angle. Many programming languages provide a function atan2 for this purpose, e.g.:

dot = x1*x2 + y1*y2 # dot product
det = x1*y2 - y1*x2 # determinant
angle = atan2(det, dot) # atan2(y, x) or atan2(sin, cos)

3D case

In 3D, two arbitrarily placed vectors define their own axis of rotation, perpendicular to both. That axis of rotation does not come with a fixed orientation, which means that you cannot uniquely fix the direction of the angle of rotation either. One common convention is to let angles be always positive, and to orient the axis in such a way that it fits a positive angle. In this case, the dot product of the normalized vectors is enough to compute angles.

Plane embedded in 3D

One special case is the case where your vectors are not placed arbitrarily, but lie within a plane with a known normal vector $n$. Then the axis of rotation will be in direction $n$ as well, and the orientation of $n$ will fix an orientation for that axis. In this case, you can adapt the 2D computation above, including $n$ into the determinant to make its size $3\times3$. One condition for this to work is that the normal vector $n$ has unit length. If not, you'll have to normalize it. The determinant could also be expressed as the triple product:

$$\det(v_1,v_2,n) = n \cdot (v_1 \times v_2)$$

This might be easier to implement in some APIs, and gives a different perspective on what's going on here: The cross product is proportional to the sine of the angle, and will lie perpendicular to the plane, hence be a multiple of $n$. The dot product will therefore basically measure the length of that vector, but with the correct sign attached to it.

$\endgroup$ 4 $\begingroup$

Before reading this answer - Imagine your angle in a 3D space - you can look at it from the "front" and from the "back" (front and back are defined by you). The angle from the front will be the opposite of the angle that you see from the back. So there is no real sense in a value in a range larger than $[0,180]$.

If you still want to read more, enjoy

In the 3D case, your two vectors would be on some plane (the plane that you can get its normal from the cross-product of the two vectors). Getting a $[0,180]$ degrees angle is of course possible by computing $arccos(\frac{\vec{a}*\vec{b}}{|\vec{a}| *|\vec{b}|})$.

I think that what you can do, is to fix the Z axis, such that the two vectors will only differ in X and Y. Then you solve a 2D geometry problem. You should be able to fix the Z axis by dividing the two vectors by their Z component. Since the Z component is just a scalar, the vector directions will remain the same (the trend might change though, if this scalar is negative). You should remember whether these two scalars were both positive, both negative or one positive and one negative. In the last case, you're final results will be flipped!

If the Z component of the two vectors is $0$, then this step can (and actually must) be skipped. However, if only one of them has $0$ in its Z component, then it is probably impossible to compute the very precise angle, but you can still compute an approximation, by dividing the other vector by a very large number.

Having that, you can reduce vector $\vec{a}$ from both vectors $\vec{a}$ and $\vec{b}$ and then add the vector $(1, 0, 0)$ to both. Thus, vector $\vec{a}$ will be $(1, 0, 0)$, while vector $\vec{b}$ will be $(b_x, b_y, 0)$.

Now, if $b_y$ is positive, than your angle is $arccos(\frac{\vec{a}*\vec{b}}{|\vec{a}| *|\vec{b}|})$. Else, it is $360 - arccos(\frac{\vec{a}*\vec{b}}{|\vec{a}| *|\vec{b}|})$. Remember to use the opposite result if only one of the original Z values was negative, as described above!

$\endgroup$ 1 $\begingroup$

I write the formula like I wrote in excel . (xa,ya,xb,yb put in the cells a2,b2,c2,d2).

angle(vector.a,vector.b)

=(180/pi())* abs(pi()/2*((1+sign(a2))* (1-sign(b2^2))-(1+sign(c2))* (1-sign(d2^2)))

+pi()/4*((2+sign(a2))*sign(b2)-(2+sign(c2))*sign(d2))

+sign(a2*b2)*atan((abs(a2)-abs(b2))/(abs(a2)+abs(b2)))

-sign(c2*d2)*atan((abs(c2)-abs(d2))/(abs(c2)+abs(d2))))

The formula is giving the angle of two vectors a and b from 0 to 360 degrees,

in left wise direction for any value of the vectors coordinates.

For xa=ya=0 and or xb=yb=0 the result is undefined.

$\endgroup$ 2

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like