7
votes

I want to calculate the angle between 2 vectors V = [Vx Vy Vz] and B = [Bx By Bz]. is this formula correct?

VdotB = (Vx*Bx + Vy*By + Vz*Bz)

 Angle = acosd (VdotB / norm(V)*norm(B))

and is there any other way to calculate it?

My question is not for normalizing the vectors or make it easier. I am asking about how to get the angle between this two vectors

5
Seems to be more of a math question than a programming question.Dennis Jaheruddin
Depending on your language, you should add parentheses to make sure the product is evaluated before the division. If evaluated from left to right, this wouldn't be correct.Teepeemm

5 Answers

16
votes

Based on this link, this seems to be the most stable solution:

atan2(norm(cross(a,b)), dot(a,b))
2
votes

There are a lot of options:

a1 = atan2(norm(cross(v1,v2)), dot(v1,v2))
a2 = acos(dot(v1, v2) / (norm(v1) * norm(v2)))
a3 = acos(dot(v1 / norm(v1), v2 / norm(v2)))
a4 = subspace(v1,v2)

All formulas from this mathworks thread. It is said that a3 is the most stable, but I don't know why.

For multiple vectors stored on the columns of a matrix, one can calculate the angles using this code:

% Calculate the angle between V (d,N) and v1 (d,1)
% d = dimensions. N = number of vectors
% atan2(norm(cross(V,v2)), dot(V,v2))
c = bsxfun(@cross,V,v2);
d = sum(bsxfun(@times,V,v2),1);%dot
angles = atan2(sqrt(sum(c.^2,1)),d)*180/pi;
0
votes

You can compute VdotB much faster and for vectors of arbitrary length using the dot operator, namely:

VdotB = sum(V(:).*B(:));

Additionally, as mentioned in the comments, matlab has the dot function to compute inner products directly.

Besides that, the formula is what it is so what you are doing is correct.

0
votes

This function should return the angle in radians.

function [ alpharad ] = anglevec( veca, vecb )
% Calculate angle between two vectors
alpharad = acos(dot(veca, vecb) / sqrt( dot(veca, veca) * dot(vecb, vecb)));
end

anglevec([1 1 0],[0 1 0])/(2 * pi/360) 
>> 45.00
0
votes

The solution of Dennis Jaheruddin is excellent for 3D vectors, for higher dimensional vectors I would suggest to use:

acos(min(max(dot(a,b)/sqrt(dot(a,a)*dot(b,b)),-1),1))

This fixes numerical issues which could bring the argument of acos just above 1 or below -1. It is, however, still problematic when one of the vectors is a null-vector. This method also only requires 3*N+1 multiplications and 1 sqrt. It, however also requires 2 comparisons which the atan method does not need.