Reputation: 4077
I want to the calculate radian anticlock wise angle (0-2*pi) from start vector to end vector. For example , start vector: {10,0}, end vector: {-10,-10}, want to get the angle {pi * 5/4}, but the result is {pi * 3/4}.
How to adjust to anticlose wise angle?
def get_vector_angle({x, y}, {x1, y1}) do
:math.acos(
(x * x1 + y * y1) /
(:math.sqrt(x * x + y * y) * :math.sqrt(x1 * x1 + y1 * y1))
)
end
The following is before erlang code, it can work but too long and complex.(angle: by milli degree)
vector_angle({X_a,Y_a},{X_b,Y_b})->
B =case {X_b,Y_b} of
{0,0} ->
0;
_ ->
get_x_direction(0,0,X_b,Y_b)
end,
C = case {X_a,Y_a} of
{0,0} ->
0;
_ ->
get_x_direction(0,0,X_a,Y_a)
end,
case (A = (B - C )/1000) > 360 of
true ->
A - 360;
false ->
case A < 0 of
true ->
A + 360;
false ->
A
end
end.
get_x_direction({0,0})->
0;
get_x_direction({X_b,Y_b})->
get_x_direction(0,0,X_b,Y_b).
get_x_direction({X,Y},{X_b,Y_b})->
get_x_direction(X,Y,X_b,Y_b).
get_x_direction(A_x,Original_y,A_y,Target_y) when (A_x == A_y orelse A_y - A_x == 0.0)
andalso Original_y > Target_y ->
270000;
get_x_direction(A_x,Original_y,A_y ,Target_y) when (A_x == A_y orelse A_y - A_x == 0.0)
andalso Original_y < Target_y ->
90000;
get_x_direction(A,Original_y,A,Target_y) when Original_y == Target_y ->
throw(?MSG_HANOCH_DIRECTION_DATA_ERROR);
get_x_direction(Original_x,Original_y,Target_x,Target_y) when Target_y == Original_y ->
case Target_x > Original_x of
true ->
0;
false ->
180000
end;
get_x_direction(Original_x,Original_y,Target_x,Target_y)->
B = round(math:atan((Target_y - Original_y)/(Target_x - Original_x))
* ?PI_CONVERT_2),
C = case (Target_x - Original_x) < 0 of
true ->
B + 180000;
false ->
B
end,
case C < 0 of
true->
C + 360000;
false ->
C
end.
Upvotes: 0
Views: 238
Reputation: 51
The formula you use calculate the smallest angle between the two vectors. Which will be between 0 and pi. So 3/4*pi is correct.
If you wanna get the "larger" angle, you can just subtract the found one from 2pi.
I'm not sure what you mean by differentiate between the start and end vector. Will the angle you want to find always be the "counterclockwise" one?
Alright :) To determine the angle you can use that the dot product relates to cos and the determinant relates to sine, of the angle between the vectors. Where:
dot({x,y}, {x1, y1}) = x * x1 + y * y1
det({x,y}, {x1, y1}) = x * y1 - x1 * y
Then you calculate the angle with artan2:
angle = atan2( dot(), det() )
If the angle is negative then add 2*pi and you'll find the counterclockwise one.
Just make sure that the first input vector in the determinant is your starting vector.
Upvotes: 1
Reputation: 1945
You can use the concept of argument from complex numbers. The argument of a complex number is the anticlockwise angle the complex number makes with the positive horizontal axis.
To calculate the argument of a vector :
arg(v) = arctan(y/x)
arg(v) = pi - arctan(|y/x|)
arg(v) = pi + arctan(|y/x|)
arg(v) = - arctan(|y/x|)
Now to find the anticlockwise angle between two vectors : |arg(v1) - arg(v2)|
Upvotes: 1
Reputation: 2802
Because cosine is a repeating function most implementations of arccosine return values between 0 and pi. Take the degrees of 170 and 190. They both produce a cosine of -.98481. You will need to determine which quadrant you're in to find the angle you're after. If you use sine along with cosine you can check the signs to figure out where you are. Taking that same example as before, the value of sine for 170 and 190 are .17453 and -.17453 respectively.
A simpler approach is to use atan2
which already takes into account quadrant. There are a few ways to do it with atan2
such as atan2(y1,x1) - atan2(y,x)
or atan2(x*y1 - y*x1, x*x1 + y*y1)
, for your example both of these will return -2.35619 radians or -135 degrees. Since it's negative add 2 pi and you get 5/4 pi.
Upvotes: 1