Measure angles between two vectors solely counter - clockwise
14 views (last 30 days)
Show older comments
Harvey Rael
on 17 Jul 2018
Edited: Roberto Enrique
on 12 Jan 2024
Hi,
I have two vectors and I want to measure the angle between them. The first one lies solely along the positive x-axis, and the second one varies in a circle. When the angle between the two gets greater than 180 degrees, MATLAB starts to measure the angle clockwise, but I would like it to continue to measure the angle counter clockwise. (e.g, after 180, measure 190, 200 etc.. instead of 170, 160 etc..). Any workarounds? Stuff like atan2 doesn't work. Thanks in advance!
2 Comments
Jan
on 17 Jul 2018
Matlab does not measure anything. But you can write some Matlab commands to calculate the angle. Of course atan2 does exactly, what is mathematically defined. But if you want to consider the sign in addition - consider the sign in addition.
Do you mean the 2D case, or are the vectors in 3D? In the latter case, "clockwise" or "counterclockwise" is not well defined, because it depends on the direction of view. Then please define this explicitly, because it is neither obvious nor uniquely defined in a mathematical sense.
The best idea is to post two example inputs and outputs together with the current code you use.
Adam Danz
on 17 Jul 2018
Yeah, some examples will be helpful. A solution might be to use a conditional that detects cw or ccw outputs based on the sign of the angle and corrects for the undesired direction (assuming 2D).
if theta < 0
theta = 180 + (theta + 180);
end
or
if theta > 0
theta = -180 - (180-theta);
end
Accepted Answer
David Goodmanson
on 17 Jul 2018
Edited: David Goodmanson
on 17 Jul 2018
Hi Harvey,
It looks like you want the angle in degrees. For two dimensions, where the second vector has components x,y:
theta = mod(atan2d(y,x)+360,360)
4 Comments
David Goodmanson
on 17 Jul 2018
Going around clockwise from just below the negative x axis, the range of atan2d is continuous from -180 to 180. You want to add 360 to the result in Quadrants III and IV and leave Quadrants I and II alone.
Quadrants III, IV Quadrants I, II
atan2d -180 -> 0 0 -> 180
add 360 180 -> 360 ok 360 -> 540 no
mod(...,360) 180 -> 360 still ok 0 -> 180 ok
since mod subtracts (multiples of) 360 from anything larger than 360.
More Answers (2)
theodore panagos
on 10 Jan 2019
The formula gives the angle from positive x-axis to 360 degrees counter clockwise:
f(x,y)=180-90*(1+sign(x))* (1-sign(y^2))-45*(2+sign(x)) *sign(y)
-(180/pi())*sign(x*y)*atan((abs(x)-abs(y))/(abs(x)+abs(y)))
x=x2-x1 and y=y2-y1 .
0 Comments
Jan
on 17 Jul 2018
Edited: Jan
on 17 Jul 2018
In the 3D case:
function A = AngleIn3D(V1, V2, View)
% Input: V1, V2, View: [N x 3] vectors, each one can be [1 x 3] also.
% The angle between the vectors V1 and V2 is calculated
% The View defines the view direction to define the sign of the angle
%
% Method: atan2(norm(N1 x N2), DOT(N1, N2))
% W. Kahan suggested in "Mindeless.pdf":
% 2 * atan(norm(x*norm(y) - norm(x)*y) / norm(x * norm(y) + norm(x) * y))
N1 = V1 ./ sqrt(sum(V2 .* V2, 2)); % >= R2016b: arithmetic expanding!
N2 = V2 ./ sqrt(sum(V2 .* V2, 2)); % >= R2016b: arithmetic expanding!
% Calculate dot and cross product of vectors:
N1dotN2 = N1(:, 1) .* N2(:, 1) + N1(:, 2) .* N2(:, 2) + N1(:, 3) .* N2(:, 3);
N1xN2 = [(N1(:, 2) .* N2(:, 3) - N1(:, 3) .* N2(:, 2)), ...
(N1(:, 3) .* N2(:, 1) - N1(:, 1) .* N2(:, 3)), ...
(N1(:, 1) .* N2(:, 2) - N1(:, 2) .* N2(:, 1))];
% Angle between N1xN2 and view vector:
LXo = N1xN2(:, 1) .* View(:, 1) + N1xN2(:, 2) .* View(:, 2) + ...
N1xN2(:, 3) .* View(:, 3);
signLXo = sign(LXo);
% Care about anti-parallel N1 and N2:
antiN1N2 = (N1dotN2 < -0.999999999999993); % -1 + 3 * EPS
if any(antiN1N2)
antiN1N2 = and(antiN1N2, isfinite(N1dotN2)); % Catch N1dotN2=-Inf
signLXo(antiN1N2) = 1.0;
end
normN1xN2 = N1xN2 ./ sqrt(sum(N1xN2 .* N1xN2), 2);
Angle = signLXo .* atan2(normN1xN2, N1dotN2);
end
Now for the 2D case, set the 3rd component to 0 and use [0,0,1] as View direction. If you want the 2D case only, the above can be simplified massively.
function A = AngleIn2D(V1, V2)
% Input: V1, V2: [N x 3] vectors, each one can be [1 x 3] also.
% The angle between the vectors V1 and V2 is calculated
%
% Method: atan2(norm(N1 x N2), DOT(N1, N2))
% W. Kahan suggested in "Mindeless.pdf":
% 2 * atan(norm(x*norm(y) - norm(x)*y) / norm(x * norm(y) + norm(x) * y))
N1 = V1 ./ sqrt(sum(V2 .* V2, 2)); % >= R2016b: arithmetic expanding!
N2 = V2 ./ sqrt(sum(V2 .* V2, 2)); % >= R2016b: arithmetic expanding!
% Calculate dot and cross product of vectors:
N1dotN2 = N1(:, 1) .* N2(:, 1) + N1(:, 2) .* N2(:, 2);
N1xN2 = (N1(:, 1) .* N2(:, 2) - N1(:, 2) .* N2(:, 1));
% Angle between N1xN2 and view vector:
signLXo = sign(N1xN2);
% Care about anti-parallel N1 and N2:
antiN1N2 = (N1dotN2 < -0.999999999999993); % -1 + 3 * EPS
if any(antiN1N2)
antiN1N2 = and(antiN1N2, isfinite(N1dotN2)); % Catch N1dotN2=-Inf
signLXo(antiN1N2) = 1.0;
end
normN1xN2 = abs(N1xN2);
Angle = signLXo .* atan2(normN1xN2, N1dotN2);
end
!UNTESTED CODE!
2 Comments
Roberto Enrique
on 12 Jan 2024
Edited: Roberto Enrique
on 12 Jan 2024
Hi! Jan, thank you for the code.
For 3D case i define V1=[0 0 0;1 1 1], V2=[1 1 1;2 3 4] and run the code as follows and the given errors
>> A = AngleIn3D(V1, V2, 1)
Index in position 2 exceeds array bounds. Index must not exceed 1.
Error in AngleIn3D (line 18)
LXo = N1xN2(:, 1) .* View(:, 1) + N1xN2(:, 2) .* View(:, 2) + N1xN2(:, 3) .* View(:, 3);
>> A = AngleIn3D(V1, V2, [1 0 0])
Error using sqrt
Too many input arguments.
Error in AngleIn3D (line 27)
normN1xN2 = N1xN2 ./ sqrt(sum(N1xN2 .* N1xN2), 2);
>> A = AngleIn3D(V1, V2, [0 0 0])
Error using sqrt
Too many input arguments.
Error in AngleIn3D (line 27)
normN1xN2 = N1xN2 ./ sqrt(sum(N1xN2 .* N1xN2), 2);
>> A = AngleIn3D(V1, V2, [1 1 1])
Error using sqrt
Too many input arguments.
Error in AngleIn3D (line 27)
normN1xN2 = N1xN2 ./ sqrt(sum(N1xN2 .* N1xN2), 2);
Could you help to solve this?
Thank you, sorry for my broken english
See Also
Categories
Find more on Matrix Indexing in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!