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
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
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
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 个评论
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
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 .
0 个评论
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 个评论
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 Center 和 File Exchange 中查找有关 Matrix Indexing 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!