Measure angles between two vectors solely counter - clockwise

16 次查看(过去 30 天)
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 个评论
Jan
Jan 2018-7-17
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
Adam Danz 2018-7-17
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

请先登录,再进行评论。

采纳的回答

David Goodmanson
David Goodmanson 2018-7-17
编辑:David Goodmanson 2018-7-17
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 个评论
Harvey Rael
Harvey Rael 2018-7-17
just did there yes! Sorry to be so quick to dismiss, didn't understand your answer. Not quite sure about the code, but happy to read the literature now I know it works! Thanks for your help!
David Goodmanson
David Goodmanson 2018-7-17
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.

请先登录,再进行评论。

更多回答(2 个)

theodore panagos
theodore panagos 2019-1-10
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 .

Jan
Jan 2018-7-17
编辑:Jan 2018-7-17
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 个评论
Harvey Rael
Harvey Rael 2018-7-17
编辑:Harvey Rael 2018-7-17
Cheers guys - So a few clarifications:
It is the 2-D case. An Example would be :
v1 is ALWAYS [1,0]; and a couple of examples of v2 would be [-1,0]; and [0,-1]; In the first case, the measured angle between the two (using the dot product formula) would output 180 degrees. In the second case, MATLAB spits out 90 degress, even though from the positive x - axis engineering convention is to measure positively counter clockwise (ergo, a positive value would be 270 degress) and negatively clockwise (ergo, -90). MATLAB has chosen to only give out positive values of the angle (90), ignoring convention, which is understandeable as it is a software. My question is if there's a work around for that.
Roberto Enrique
Roberto Enrique 2024-1-12
编辑:Roberto Enrique 2024-1-12
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

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 Matrix Indexing 的更多信息

产品


版本

R2018a

Community Treasure Hunt

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

Start Hunting!

Translated by