How can I find the angle between two vectors, including directional information?

Hello, I am a graduate student, and I am working on a script that tracks the position of animals during a courtship. I have position data in the form of XY coordinates from two points on each animal's body taken from top down filming. I use these two points to create a vector that defines the animal's orientation. My script needs to calculate the angle between these two vectors, but also include directional information - IE, go from -180 through 0 to 180 degrees, depending on where the vectors are placed (see image).
This is the code that I currently have. It gives me the desired angle (I believe), but is NOT directional. 60 degrees to either side spits out as 60 degrees no matter which it is.
angle_maleToFemale_radians = acos(dot(maleFemaleVector,femaleVector)/(norm(maleFemaleVector)*norm(femaleVector))); angle_maleToFemale_degrees(index) = radtodeg(angle_maleToFemale_radians); angle_maleToFemale_degrees(index) = 180 - angle_maleToFemale_degrees(index);

1 Comment

based on above equation, the angle between two vectors in the range of 0 to 2pi can be found using atan2(Y,X), as described by others in the earlier comments.

Sign in to comment.

 Accepted Answer

If v1 = [x1,y1] and v2 = [x2,y2] are the components of two vectors, then
a = atan2d(x1*y2-y1*x2,x1*x2+y1*y2);
gives the angle in degrees between the vectors as measured in a counterclockwise direction from v1 to v2. If that angle would exceed 180 degrees, then the angle is measured in the clockwise direction but given a negative value. In other words, the output of 'atan2d' always ranges from -180 to +180 degrees.
One further observation: Besides the greater range of 'atan2d' as compared with 'acosd', the former does not suffer the inaccuracies that occur with 'acosd' for angles near zero and 180 degrees.

14 Comments

Atan2d appears to be the right solution. However, I dont understand the vector notation you used - I have my vectors as v1 = [x1 y1] - [x2 y2] and v2 = [x3 y3] - [x4 y4]. Can you explain a bit more?
Where you have v1 = [x1 y1] - [x2 y2], my x1 is your x1-x2 and my y1 is your y1-y2. Where you have v2 = [x3 y3] - [x4 y4], your x3-x4 is my x2 and your y3-y4 is my y2. In other words, my x,y values are the x and y components of the vectors between the points.
Sorry to bother you again, but I am having trouble implementing your solution. While it appears to work for certain parts of my data, others give erroneous results. I've made another picture showing possible vectors I encountered:
In general, I would like to get the angle between vector p2p1 and vector p1p3. The pictures shows multiple possible positions of p3 relative to p1. The solution you gave works as desired when p3 is at p3a, giving a negative angle of the right size (-77 degrees). However, when p3 is at p3d, it outputs a large positive angle (+150 degrees), as opposed to the desired large negative angle.
The code I am using is as follows (adapted to the diagram):
v1 = p2 - p1;
x1 = v1(1);
y1 = v1(2);
v2 = p1 - p3;
x2 = v2(1);
y2 = v2(2);
angle = atan2d(x1*y2-y1*2,x1*x2+y1*y2);
Thank you again for your help!
Nevermind - a user on another forum gave an great working answer:
v1 = p1 - p2;
x1 = v1(1);
y1 = v1(2);
v2 = p3 - p1;
x2 = v2(1);
y2 = v2(2);
angle = atan2d(y1,x1) - atan2d(y2,x2)
if abs(angle) > 180
angle = angle - 360*sign(angle)
end
There are two ways in which the formulas you have used are not in accordance with accepted practices in vector analysis. First, if you consider that a vector points from point A to point B, then the vector is expressed as PB-PA. You have the opposite. As it turns out, that alone would not affect the answer, however. Secondly, the angle between vectors is considered as measured from the first vector counterclockwise to the second vector with the convention that if the angle goes beyond 180, then 360 is to be subtracted from it, making it negative. To be compatible with the diagram you showed, that would make the vector from P1 to P3 the first vector and that from P2 to P1 the second vector. Unfortunately the formula I gave you is for the opposite order. That will affect your results.
Here is code that corresponds to the diagram you have shown. I use va to denote the first vector and vb the second one.
va = p3-p1; % <-- Consider this the first vector
vb = p1-p2; % <-- and this the second vector
a = atan2d(va(1)*vb(2)-va(2)*vb(1),va(1)*vb(1)+va(2)*vb(2));
Note that the expression "va(1)*vb(2)-va(2)*vb(1)" is the z-component of the cross product of vectors va (first) by vb (second) where the z-axis is pointing upward from your diagram. This corresponds to writing the expression
atan2d( cross(va,vb) , dot(va,vb) )
where again we understand that this refers to the z-component of the cross product and that the two vectors lie in the x-y plane. This should help you generalize this method for any 2D diagram you might create.
(End of lecture in vector analysis)
Been looking for a while for an answer to a similar question. This is really helpful. Thank you Roger
May I know what are p1,p2,p3 here. Please mention the points clearly in the figure?
This is very useful. An great approach to get the relative +- angles between two vectors easily. Thank you.
If I want to know the angle in between 0 to 360 in 3D space, then what should I do? I have used atan2d function, but it gives answer in between 0 to 180.
How about for two 3D vectors: (x1,y1,z1) and (x2,y2,z2)?
To recap the answer I posted here, the MATLAB formula would be:
atan2(dot([n1,n2,n3],cross([x1,y1,z1],[x2,y2,z2])),dot([x1,y1,z1],[x2,y2,z2]))
where [n1, n2, n3] is a unit normal vector to the plane spanning the two vectors, pointing in the direction corresponding to rotation from the first vector to the second according to the right-hand rule.
Executed formula and works like charm! Thank you math! Thank you Roger Stafford!

Sign in to comment.

More Answers (2)

You can use subspace function.
A = [x1,y1,z1];
B = [x2,y2,z2];
Angle = subspace(A',B')
%transposed! they must be column vectors

Categories

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!