¿Cómo uso el producto punto para obtener un ángulo entre dos vectores?

16

Estoy aprendiendo a usar vectores normalizados en mis juegos.

Aprendí que para conocer el ángulo entre dos vectores, puedo usar el producto punto. Esto me da un valor entre -1 y 1, donde

  • 1 significa que los vectores son paralelos y están orientados en la misma dirección (el ángulo es de 180 grados).
  • -1 significa que son paralelas y se enfrentan a direcciones opuestas (todavía 180 grados).
  • 0 significa que el ángulo entre ellos es de 90 grados.

Quiero saber cómo convertir el producto escalar de dos vectores, a un ángulo real en grados. Por ejemplo, si el producto escalar de dos vectores es 0.28, ¿cuál es el ángulo correspondiente, entre 0 y 360 grados?

usuario3150201
fuente
1
Tenga en cuenta que su uso previsto del producto punto solo funciona cuando los vectores iniciales son vectores unitarios.
sam hocevar
@SamHocevar Sí, a eso me refería.
user3150201
1
@ user3150201 La respuesta de Alex es correcta, pero también debe considerar si necesita obtener el ángulo real en grados. El único caso en el que puedo pensar dónde es realmente necesario sería mostrar algo en grados en la interfaz de usuario. De lo contrario, probablemente haya pocas aplicaciones en las que no pueda trabajar directamente con senos y cosenos.
TravisG

Respuestas:

22

dot(A,B) = |A| * |B| * cos(angle)
que se puede reorganizar a
angle = arccos(dot(A,B) / (|A|* |B|)).

Con esta fórmula, puede encontrar el ángulo más pequeño entre los dos vectores, que estará entre 0 y 180 grados. Si lo necesita entre 0 y 360 grados, esta pregunta puede ayudarlo.


Por cierto, el ángulo entre dos vectores paralelos que apuntan en la misma dirección debería ser 0 grados, no 180.

Alex
fuente
+1 para "Por cierto, el ángulo entre dos vectores paralelos que apuntan en la misma dirección debe ser 0 grados, no 180".
Tara
8

Ampliaré un poco el comentario de TravisG y daré otra respuesta, haciendo uso del hecho de que su pregunta tenía la etiqueta "2D".

Puede obtener el ángulo entre dos vectores usando el producto de puntos, pero no puede obtener el ángulo firmado entre dos vectores que lo usan. Dicho de otra manera, si quieres girar un personaje con el tiempo hacia un punto, el producto punto te dará cuánto girar pero no en qué dirección. Sin embargo, existe otra fórmula simple que es muy útil cuando se combina con el producto de puntos. No solo tienes

dot(A,B) = |A| * |B| * cos(angle)

También puede tener otra fórmula (cuyo nombre inventé para la corrección política):

pseudoCross(A,B) = |A| * |B| * sin(angle)

donde si A = (a, b), B = (x, y), entonces pseudoCross (A, B) se define como el tercer componente del producto cruzado (a, b, 0) x (x, y, 0 ) En otras palabras:

a*x+b*y = |A| * |B| * cos(angle)

-b*x+a*y = |A| * |B| * sin(angle)

El ángulo con signo completo es entonces angle=atanfull(-b*x+a*y,a*x+b*y)(las funciones atanfull o atan2 lo perdonan si pasa valores no normalizados). Si A y B están normalizados, es decir, si |A|=|B|=1, estos son simplemente:

a*x+b*y = cos(angle)

-b*x+a*y = sin(angle)


Para una explicación más profunda, tenga en cuenta que las ecuaciones anteriores se pueden expresar mediante la ecuación matricial:

[ a,b]   [x]   [cos(angle)]
[-b,a] * [y] = [sin(angle)]

Sin embargo, a y b pueden expresarse como a=cos(ang1), b=sin(ang1)por algún valor ang1(no angle). Por lo tanto, la matriz de la izquierda es una matriz de rotación que gira el vector (x, y) en la cantidad -ang1. ¡Esto es equivalente a cambiar a un marco de referencia donde el vector unitario "A" se trata como el vector / eje (1,0)! Entonces, simplemente dibujando el círculo unitario / triángulo rectángulo en este marco, puede ver por qué el vector resultante de ese producto es (cos (ángulo), sin (ángulo)).

Si escribe (a, b) y (x, y) en forma polar, y aplica las fórmulas de diferencia de ángulo cos(l)*cos(m)+sin(l)*sin(m)=cos(l-m)y sin(l)*cos(m)-cos(l)*sin(m)=sin(l-m), vuelve a expresar que los senos / cosenos están dados por este producto, ya que (lm) = ángulo. Alternativamente, esas identidades podrían usarse para ver por qué el producto lineal dado anteriormente rota un vector.

Todas estas identidades significan que rara vez necesitas ángulos. Debido a que los ángulos pueden ser extraños (radianes / grados, convenciones para seno / coseno inverso), el hecho de que se repitan cada 2 * pi, esto en realidad puede ser más útil y le ahorrará un montón de lógica "if (ang <180)", etc.


fuente