Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Signed angle between two vectors without a reference plane

(In three dimensions) I'm looking for a way to compute the signed angle between two vectors, given no information other than those vectors. As answered in this question, it is simple enough to compute the signed angle given the normal of a plane to which the vectors are perpendicular. But I can find no way to do this without that value. It's obvious that the cross product of two vectors produces such a normal, but I've run into the following contradiction using the answer above:

signed_angle(x_dir, y_dir) == 90
signed_angle(y_dir, x_dir) == 90

where I would expect the second result to be negative. This is due to the fact that the cross product cross(x_dir, y_dir) is in the opposite direction of cross(y_dir, x_dir), given the following psuedocode with normalized input:

signed_angle(Va, Vb)
    magnitude = acos(dot(Va, Vb))
    axis = cross(Va, Vb)
    dir = dot(Vb, cross(axis, Va))
    if dir < 0 then
        magnitude = -magnitude
    endif
    return magnitude

I don't believe dir will ever be negative above.

I've seen the same problem with the suggested atan2 solution.

I'm looking for a way to make:

signed_angle(a, b) == -signed_angle(b, a)
like image 488
metatheorem Avatar asked Apr 13 '12 01:04

metatheorem


People also ask

What is a signed angle?

Calculates the signed angle between vectors from and to in relation to axis . The angle returned is the angle of rotation from the first vector to the second, when treating these first two vector inputs as directions. These two vectors also define the plane of rotation, meaning they are parallel to the plane.

What is the angle between two vectors?

The angle between two vectors will be deferred by a single point, which is called as the shortest angle at which we have to turn around one of the vectors to the position of co-directional with another vector.


1 Answers

The relevant mathematical formulas:

  dot_product(a,b) == length(a) * length(b) * cos(angle)
  length(cross_product(a,b)) == length(a) * length(b) * sin(angle)

For a robust angle between 3-D vectors, your actual computation should be:

  s = length(cross_product(a,b))
  c = dot_product(a,b)
  angle = atan2(s, c)

If you use acos(c) alone, you will get severe precision problems for cases when the angle is small. Computing s and using atan2() gives you a robust result for all possible cases.

Since s is always nonnegative, the resulting angle will range from 0 to pi. There will always be an equivalent negative angle (angle - 2*pi), but there is no geometric reason to prefer it.

like image 149
comingstorm Avatar answered Sep 29 '22 08:09

comingstorm