21
\$\begingroup\$

I am learning to use normalized vectors in my games.

I've learned that in order to know the angle between two vectors, I can use the dot product. This gives me a value between -1 and 1, where

  • 1 means the vectors are parallel and facing the same direction (the angle is 180 degrees).
  • -1 means they are parallel and facing opposite directions (still 180 degrees).
  • 0 means the angle between them is 90 degrees.

I want to know how to convert the dot product of two vectors, to an actual angle in degrees. For example, if the dot product of two vectors is 0.28, what is the corresponding angle, between 0 and 360 degrees?

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Note that your intended use of the dot product only works when the initial vectors are unit vectors. \$\endgroup\$ Commented Jan 28, 2014 at 10:59
  • \$\begingroup\$ @SamHocevar Yes, that's what I meant. \$\endgroup\$ Commented Jan 28, 2014 at 11:27
  • \$\begingroup\$ possible duplicate of How can I calculate the angle between two 2D vectors? \$\endgroup\$
    – Almo
    Commented Jan 28, 2014 at 16:29
  • 1
    \$\begingroup\$ @user3150201 Alex' answer is correct, but you should also consider whether you need to get the actual angle in degrees at all. The only case where I can think off where this is really necessary would be to display something in degrees on the UI. Otherwise, there are probably few applications where you couldn't work directly with sines and cosines. \$\endgroup\$
    – TravisG
    Commented Jan 28, 2014 at 23:07

2 Answers 2

29
\$\begingroup\$

dot(A,B) = |A| * |B| * cos(angle)
which can be rearranged to
angle = arccos(dot(A,B) / (|A|* |B|)).

With this formula, you can find the smallest angle between the two vectors, which will be between 0 and 180 degrees. If you need it between 0 and 360 degrees this question may help you.


By the way, the angle between two parallel vectors pointing in the same direction should be 0 degrees, not 180.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ +1 for "By the way, the angle between two parallel vectors pointing in the same direction should be 0 degrees, not 180." \$\endgroup\$
    – Tara
    Commented Apr 26, 2016 at 7:33
10
\$\begingroup\$

I'll expand a bit on TravisG's comment and give another answer, making use of the fact that your question had the "2D" tag.

You can get the angle between two vectors using the dot product, but you can't get the signed angle between two vectors using it. Put another way, if you want to turn a character over time towards a point, the dot product will get you how much to turn but not which direction. There is another simple formula, however, which is very useful when combined with the dot product. Not only do you have

dot(A,B) = |A| * |B| * cos(angle)

You can also have another formula (whose name I made up for political correctness):

pseudoCross(A,B) = |A| * |B| * sin(angle)

where if A=(a,b), B=(x,y), then pseudoCross(A,B) is defined to be the third component of the cross product (a,b,0)x(x,y,0). In other words:

a*x+b*y = |A| * |B| * cos(angle)

-b*x+a*y = |A| * |B| * sin(angle)

The full signed angle is then angle=atanfull(-b*x+a*y,a*x+b*y) (atanfull or atan2 functions forgive you if you pass in non-normalized values). If A and B are normalized, that is, if |A|=|B|=1, these are simply:

a*x+b*y = cos(angle)

-b*x+a*y = sin(angle)


For a deeper explanation, note that the equations above can be expressed by the matrix equation:

[ a,b]   [x]   [cos(angle)]
[-b,a] * [y] = [sin(angle)]

But a and b can be expressed as a=cos(ang1), b=sin(ang1), for some value ang1 (not angle). Therefore, the matrix on the left is a rotation matrix which rotates the vector (x,y) by the amount -ang1. This is equivalent to switching into a frame of reference where the unit vector "A" is treated as the vector/axis (1,0)! So then just by drawing the unit circle/right triangle in this frame, you can see why the resulting vector of that product is (cos(angle),sin(angle)).

If you write (a,b) and (x,y) in polar form, and apply the angle difference formulas cos(l)*cos(m)+sin(l)*sin(m)=cos(l-m) and sin(l)*cos(m)-cos(l)*sin(m)=sin(l-m), you re-express that the sines/cosines are given by this product, since (l-m)=angle. Alternatively, those identities could be used to see why the linear product given above rotates a vector.

All these identities mean that you rarely need angles. Because angles can be weird - radian/degrees, conventions for inverse sine/cosine, the fact that they repeat every 2*pi - this can actually be more useful and save you a bunch of "if(ang<180)" etc logic.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .