2012-04-13 14 views
11

(en tres dimensiones) Estoy buscando una forma de calcular el ángulo entre dos vectores firmado, dado ninguna información distinta de esos vectores. Como se responde en this question, es bastante simple calcular el ángulo firmado dada la normalidad de un plano en el que los vectores son perpendiculares. Pero no puedo encontrar la forma de hacerlo sin ese valor. Es obvio que el producto vectorial de dos vectores produce una normal de este tipo, pero me he encontrado con la siguiente contradicción usando la respuesta anterior:ángulo entre dos vectores Firmado y sin un plano de referencia

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

donde yo esperaría que el segundo resultado sea negativo. Esto es debido al hecho de que el producto cruzado cross(x_dir, y_dir) es en la dirección opuesta de cross(y_dir, x_dir), dada la siguiente psuedocode con entrada normalizada:

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 

no creo dir será nunca negativo anteriormente.

que he visto el mismo problema con la solución sugerida atan2.

Busco una manera de hacer:

signed_angle(a, b) == -signed_angle(b, a) 
+1

no es esto: http://www.jtaylor1142001.net/calcjat/Solutions/VDotProduct/VDPTheta3D.htm ¿qué estás buscando? – Jack

+0

El enlace del comentario anterior no funciona – ephere

Respuesta

1

Gracias a todos.Después de revisar los comentarios aquí y mirar hacia atrás en lo que estaba tratando de hacer, me di cuenta de que puedo lograr lo que tengo que hacer con la fórmula estándar dada para un ángulo firmado. Acabo de colgar en la prueba de unidad para mi función de ángulo firmado.

Como referencia, introduzco el ángulo resultante en una función de rotación. No pude explicar el hecho de que esto usará naturalmente el mismo eje que en signed_angle (el producto cruzado de los vectores de entrada), y la dirección correcta de rotación seguirá desde cada dirección que ese eje esté enfrentando.

Más pocas palabras, ambos de estos sólo deben "hacer lo correcto" y giran en direcciones diferentes:

rotate(cross(Va, Vb), signed_angle(Va, Vb), point) 
rotate(cross(Vb, Va), signed_angle(Vb, Va), point) 

Donde el primer argumento es el eje de rotación y el segundo es la cantidad de girar.

3

ángulo entre dos vectores Firmado y sin un plano de referencia

angle = acos(dotproduct(normalized(a), normalized(b))); 

signed_angle (a, b) == -signed_angle (b, a)

creo que eso es imposible sin algún tipo de vector de referencia.

+0

Estaba pensando en ello un poco más, y esto es correcto. El signo del ángulo depende del eje de rotación que utilice como referencia. Y, por supuesto, hay dos ejes diferentes, uno en la dirección del producto transversal y otro en la dirección opuesta. –

+0

@JeffE: Sí, y si bien puede encontrar el eje "rotativo" mediante el uso de productos cruzados, no puede determinar en qué dirección se estaba enfrentando inicialmente, en vectores de intercambio 'a cross b' o en' b cross a' -, y obtendrás el eje orientado en dirección opuesta. Como resultado, es imposible determinar si el ángulo de rotación está dentro del rango de 0..pi o si está dentro del rango pi..pi * 2. – SigTerm

-2

Si lo que quieres es un resultado consistente, entonces cualquier forma arbitraria de elegir entre un × b y b × un para su normal, va a hacer. ¿Quizás elegir el que es lexicográficamente más pequeño?

(Pero es posible que desee para explicar cuál es el problema en realidad se está tratando de resolver:. Tal vez hay una solución que no implique el cálculo de un ángulo firmado consistente entre arbitrarias 3-vectores)

18

Las fórmulas matemáticas relevantes:

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

Para un ángulo entre los vectores robusta en 3-D, el cálculo real debe ser:

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

Si utiliza acos(c) solo, obtendrá severos problemas de precisión para los casos cuando el ángulo es pequeño. Calcular s y usar atan2() le da un resultado robusto para todos los casos posibles.

Desde s siempre es no negativo, el ángulo resultante se cubre de 0 a pi. Siempre habrá un ángulo negativo equivalente (angle - 2*pi), pero no hay una razón geométrica para preferirlo.

+0

Gracias, lo guardaré sobre acos. Supongo que es obvio cuando visualizas la función. – metatheorem

+0

Advertencia: esta función es conmutativa, y no debe ser: el ángulo desde la dirección + x (1 0 0) hasta la dirección + y (0 1 0) debe ser + 90 °. Viceversa, de + y a + x, debe ser -90 °. Pero con esta función, 'f (x, y) == f (y, x)'. No puede notar la diferencia ya que 's' no es negativo, y ese producto cruzado es lo único que podría haberle informado acerca de la dirección entre los dos. –

+0

Si fuera en 2 dimensiones, sería anti-conmutativo. Sin embargo, en 3 dimensiones, es (y debería ser) conmutativa, porque, en 3 dimensiones, necesita un tercer vector para determinar la quiralidad. Sin un tercer vector para discriminar entre ángulos positivos y negativos para los dos primeros, no tiene una razón geométrica para preferir una dirección sobre la otra. – comingstorm

Cuestiones relacionadas