29 votos

¿Cómo encontrar un ángulo en el rango (0, 360) entre 2 vectores?

Sé que el enfoque común para encontrar un ángulo es calcular el producto punto entre 2 vectores y luego calcular el arcocoseno de eso. Pero en esta solución solo puedo obtener un ángulo en el rango de (0, 180) grados. ¿Cuál sería la manera adecuada de obtener un ángulo en el rango de (0, 360)?

1 votos

¿Significa que estás buscando una fórmula matemática para algo similar a la función "atan2" en C++?

7 votos

Dos vectores forman dos ángulos que suman $360^\circ$. El "ángulo entre vectores" se define como el más pequeño de los dos, por lo tanto no mayor a $180^\circ. Aparentemente, a veces quieres el más grande en su lugar. Tendrás que aclarar tu definición de "ángulo entre vectores".

2 votos

Podrías verificar en qué cuadrantes estaban tus vectores originales para ver si necesitas sumarle los 180.

44voto

gagneet Puntos 4565

Estoy adaptando mi respuesta en Stack Overflow.

Caso 2D

Así como el producto punto es proporcional al coseno del ángulo, el determinante es proporcional a su seno. Y si conoces el coseno y el seno, entonces puedes calcular el ángulo. Muchos lenguajes de programación proporcionan una función atan2 para este propósito, por ejemplo:

dot = x1*x2 + y1*y2      # producto punto
det = x1*y2 - y1*x2      # determinante
angle = atan2(det, dot)  # atan2(y, x) o atan2(sin, cos)

Caso 3D

En 3D, dos vectores colocados arbitrariamente definen su propio eje de rotación, perpendicular a ambos. Ese eje de rotación no viene con una orientación fija, lo que significa que no puedes fijar de forma única la dirección del ángulo de rotación. Una convención común es hacer que los ángulos siempre sean positivos, y orientar el eje de tal manera que se ajuste a un ángulo positivo. En este caso, el producto punto de los vectores normalizados es suficiente para calcular ángulos.

Plano insertado en 3D

Un caso especial es cuando tus vectores no están colocados arbitrariamente, sino que se encuentran en un plano con un vector normal conocido $n$. Entonces, el eje de rotación estará en la dirección de $n$ también, y la orientación de $n$ fijará una orientación para ese eje. En este caso, puedes adaptar el cálculo 2D anterior, incluyendo $n$ en el determinante para hacer que su tamaño sea $3\times3$. Una condición para que esto funcione es que el vector normal $n$ tenga una longitud unitaria. De lo contrario, tendrás que normalizarlo. El determinante también se puede expresar como el producto triple:

$$\det(v_1,v_2,n) = n \cdot (v_1 \times v_2)$$

Esto podría ser más fácil de implementar en algunas APIs, y ofrece una perspectiva diferente sobre lo que está sucediendo aquí: El producto cruz es proporcional al seno del ángulo, y estará perpendicular al plano, por lo tanto será un múltiplo de $n$. El producto punto básicamente mide la longitud de ese vector, pero con el signo correcto adjunto.

2 votos

Esto no funcionará si tienes algún cero.

2 votos

@iLoveUnicorns: Un solo punto de coordenadas cero no será un problema, y un vector de cero completo tendrá un ángulo indefinido sin importar el método. ¿Qué tipo de problema tienes en mente?

2 votos

Vale la pena agregar que el ángulo que se obtiene es el ángulo del vector $(x2, y2)$ con respecto a $(x1, y1)$ -- como si $(x1, y1)$ fuera su eje de referencia para la rotación.

0voto

AgvaniaRekuva Puntos 111

Antes de leer esta respuesta - Imagina tu ángulo en un espacio 3D - puedes verlo desde el "frente" y desde la "parte de atrás" (el frente y la parte de atrás están definidos por ti). El ángulo desde el frente será lo opuesto al ángulo que ves desde la parte de atrás. Por lo tanto, no tiene sentido real un valor en un rango mayor que $[0,180]$.

Si aún quieres seguir leyendo, disfruta

En el caso 3D, tus dos vectores estarían en algún plano (el plano del cual puedes obtener su normal a partir del producto cruz de los dos vectores). Obtener un ángulo de $[0,180]$ grados es posible por supuesto calculando $arccos(\frac{\vec{a}*\vec{b}}{|\vec{a}| *|\vec{b}|})$.

Creo que lo que puedes hacer es fijar el eje Z, de manera que los dos vectores solo difieran en X y Y. Luego resuelves un problema de geometría 2D. Deberías ser capaz de fijar el eje Z dividiendo los dos vectores por su componente Z. Dado que la componente Z es solo un escalar, las direcciones de los vectores seguirán siendo las mismas (aunque la tendencia podría cambiar si este escalar es negativo). Debes recordar si ambos escalares eran positivos, ambos negativos o uno positivo y otro negativo. En el último caso, ¡tus resultados finales se invertirán!

Si la componente Z de los dos vectores es $0$, entonces este paso puede (y de hecho debe) omitirse. Sin embargo, si solo uno de ellos tiene $0$ en su componente Z, entonces probablemente sea imposible calcular el ángulo muy preciso, pero aún puedes calcular una aproximación, dividiendo el otro vector por un número muy grande.

Teniendo eso, puedes restar el vector $\vec{a}$ de ambos vectores $\vec{a}$ y $\vec{b}$ y luego agregar el vector $(1, 0, 0)$ a ambos. Así, el vector $\vec{a}$ será $(1, 0, 0)$, mientras que el vector $\vec{b}$ será $(b_x, b_y, 0)$.

Ahora, si $b_y$ es positivo, entonces tu ángulo es $arccos(\frac{\vec{a}*\vec{b}}{|\vec{a}| *|\vec{b}|})$. De lo contrario, es $360 - arccos(\frac{\vec{a}*\vec{b}}{|\vec{a}| *|\vec{b}|})$. ¡Recuerda usar el resultado opuesto si solo uno de los valores Z originales era negativo, como se describió anteriormente!

0 votos

Esto parece estar tomando el vector de diferencia en el plano z = 1 y luego conmutando el ángulo de ese vector contra el plano y = 0. Excepto que hay este vector añadido (1,0,0) por lo que no es realmente el vector de diferencia tampoco. La relación con el ángulo entre las líneas originales me parece bastante estrecha, ya que los pasos individuales no lo conservan. Voto negativo, lo siento. El primer párrafo está bien sin embargo.

-3voto

cypressious Puntos 1696

Escribo la fórmula como la escribí en excel. (xa, ya, xb, yb colocados en las celdas a2, b2, c2, d2).

angle(vector.a, vector.b)

\=(180/pi())* abs(pi()/2*((1+sign(a2))* (1-sign(b2^2))-(1+sign(c2))* (1-sign(d2^2)))

+pi()/4*((2+sign(a2))*sign(b2)-(2+sign(c2))*sign(d2))

+sign(a2*b2)*atan((abs(a2)-abs(b2))/(abs(a2)+abs(b2)))

-sign(c2*d2)*atan((abs(c2)-abs(d2))/(abs(c2)+abs(d2)))

La fórmula da el ángulo de dos vectores a y b de 0 a 360 grados,

en dirección de la izquierda para cualquier valor de las coordenadas de los vectores.

Para xa=ya=0 y o xb=yb=0 el resultado es indefinido.

1 votos

¿Puedes formatear tus ecuaciones?

1 votos

Por favor, edite esto

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X