Angle Between Two Vectors?

How do I get the angle between two vectors with the same origin?

The two ways I know (using 'acos' and 'atan2') return some confusing results.

How do I convert those results to the range of 0 - 2 pi (or 0 - 360 degrees, or whatever)?

Thanks.

Are you working out the individual angles of the lines from their origin, then trying to do some arithmetic on those values? If so then that would explain your issues. An easier solution is the dot product.

For two vectors, A and B:

A . B = |A||B|cos(angle between A and B)

|A| is the length of A, so you can find that with Pythagoras.

So, if you have A = (ax, ay) and B = (bx, by) then:

angle between = acos( ((ax * bx) + (ay * by)) / (sqrt(ax*ax + ay*ay) * sqrt(bx*bx + by*by))

If you use the acos from math.h then the result will be in the range -pi/2 to pi/2. Be careful though — it'll always give you the smallest angle between the vectors, so if two vectors start with the same orientation and then one stays still and the other rotates then the angle between them will go up from 0 to pi/2, then down again from pi/2 to -pi/2, then up from -pi/2 to 0.

If you want a full -pi to pi then you need to do a further check to decide if the two vectors are both pointing "the same way". Imagine one vector is lying exactly on the x-axis pointing right. Then you want to decide whether the other is pointing right or left.

You can do that using the dot product too — check whether ((ax * bx) + (ay * by)) is negative or positive and add or subtract pi from your result depending on its sign and which angle you want to measure.

E.g. (untested, written adhoc)

1 | float get_angle_between_in_radians(float ax, float ay, float bx, float by) |

2 | { |

3 | float dotproduct, lengtha, lengthb, result; |

4 | |

5 | dotproduct = (ax * bx) + (ay * by); |

6 | lengtha = sqrt(ax * ax + ay * ay); |

7 | lengthb = sqrt(bx * bx + by * by); |

8 | |

9 | result = acos( dotproduct / (lengtha * lengthb) ); |

10 | |

11 | if(dotproduct < 0) |

12 | { |

13 | if(result > 0) |

14 | result += M_PI; |

15 | else |

16 | result -= M_PI; |

17 | } |

18 | return result; |

19 | } |

There's lots on the web about the dot product, and it's something that's very easy to understand the properties of, even if it takes you a while to really see why it all works...

Oh! Should have thought about it myself!

I'm stupid.

Thanks, Thomas.

[EDIT]

Your code doesn't actually work because 'atan' returns values in range of 0 - pi, but thanks for the idea with the dot product and angle signs.

This works like it should:

Hi,

I'm not that mathematical, but I have a full code list for finding the angle between 2 points, don't know if this is the same as vectors but I'll post it here just in case it is for you to use if you want it

1 | #include <allegro.h> |

2 | #include <math.h> |

3 | |

4 | #define PI 3.1415926535 |

5 | |

6 | #define WHITE makecol(255,255,255) |

7 | |

8 | //define function prototype |

9 | double get_angle(int x1,int y1,int x2, int y2); |

10 | |

11 | int main() |

12 | { |

13 | allegro_init(); |

14 | |

15 | set_gfx_mode(GFX_SAFE, 640, 480, 0, 0); |

16 | |

17 | install_keyboard(); |

18 | |

19 | //variables for calculating angle |

20 | double ang1; |

21 | double ang2; |

22 | |

23 | //first x,y co-ords |

24 | int x1=150; |

25 | int y1=150; |

26 | |

27 | //second x,y co-ords |

28 | int x2=100; |

29 | int y2=100; |

30 | |

31 | ang1=get_angle(x1,y1,x2,y2); |

32 | |

33 | //Add or subtract 180 degrees to ang1 to get the angle for ang2 |

34 | if(ang1<=180) ang2=ang1+180; |

35 | else ang2=ang1-180; |

36 | |

37 | textprintf(screen,font,10,10,WHITE,"Point 1 = %d , %d (x: horizontal [+ = right], y: vertical [+ = up])",x1,y1); |

38 | textprintf(screen,font,10,25,WHITE,"Point 2 = %d , %d",x2,y2); |

39 | |

40 | if(ang1==-1) |

41 | { |

42 | textprintf(screen,font,10,40,WHITE,"%s","The Points are the same!"); |

43 | } |

44 | else |

45 | { |

46 | textprintf(screen,font,10,40,WHITE,"The Angle from Point 2 to Point 1 is %f degrees",ang1); |

47 | textprintf(screen,font,10,55,WHITE,"The Angle from Point 1 to Point 2 is %f degrees",ang2); |

48 | } |

49 | |

50 | while(! key[KEY_ESC]); |

51 | allegro_exit(); |

52 | return 0; |

53 | } |

54 | |

55 | END_OF_MAIN(); |

56 | |

57 | |

58 | double get_angle(int x1,int y1,int x2, int y2) |

59 | { |

60 | double opp; |

61 | double adj; |

62 | double ang1; |

63 | |

64 | //calculate vector differences |

65 | opp=y1-y2; |

66 | adj=x1-x2; |

67 | |

68 | if(x1==x2 && y1==y2) return(-1); |

69 | |

70 | //trig function to calculate angle |

71 | if(adj==0) // to catch vertical co-ord to prevent division by 0 |

72 | { |

73 | if(opp>=0) |

74 | { |

75 | return(0); |

76 | } |

77 | else |

78 | { |

79 | return(180); |

80 | } |

81 | } |

82 | else |

83 | { |

84 | ang1=(atan(opp/adj))*180/PI; |

85 | //the angle calculated will range from +90 degrees to -90 degrees |

86 | //so the angle needs to be adjusted if point x1 is less or greater then x2 |

87 | if(x1>=x2) |

88 | { |

89 | ang1=90-ang1; |

90 | } |

91 | else |

92 | { |

93 | ang1=270-ang1; |

94 | } |

95 | } |

96 | return(ang1); |

97 | } |