math - seno - Usando atan2 para encontrar el ángulo entre dos vectores
calcular el seno del angulo entre dos vectores (7)
Entiendo que:
atan2(vector.y, vector.x)
= el ángulo entre el vector y el eje X.
Pero quería saber cómo obtener el ángulo entre dos vectores usando atan2. Entonces encontré esta solución:
atan2(vector1.y - vector2.y, vector1.x - vector2.x)
Mi pregunta es muy simple:
¿Producirán las dos fórmulas siguientes el mismo número?
atan2(vector1.y - vector2.y, vector1.x - vector2.x)
atan2(vector2.y - vector1.y, vector2.x - vector1.x)
Si no, ¿cómo sé qué vector es lo primero en las restas?
Gracias
Como complemento a la respuesta de @ martin-r, se debe tener en cuenta que es posible usar la fórmula de suma / diferencia para los tantenos de arco.
angle = atan2(vec2.y, vec2.x) - atan2(vec1.y, vec1.x);
angle = -atan2(vec1.x * vec2.y - vec1.y * vec2.x, dot(vec1, vec2))
where dot = vec1.x * vec2.x + vec1.y * vec2.y
- Advertencia 1 : asegúrate de que el ángulo permanezca dentro de -pi ... + pi
- Advertencia 2 : ten cuidado cuando los vectores se estén volviendo muy similares, podrías extinguirte en el primer argumento, lo que llevaría a inexactitudes numéricas
Creo que se publicó una fórmula mejor aquí: http://www.mathworks.com/matlabcentral/answers/16243-angle-between-two-vectors-in-3d
angle = atan2(norm(cross(a,b)), dot(a,b))
Entonces esta fórmula funciona en 2 o 3 dimensiones. Para 2 dimensiones, esta fórmula simplifica a la indicada anteriormente.
La forma correcta de hacerlo es encontrar el seno del ángulo usando el producto cruzado, y el coseno del ángulo usando el producto Atan2()
y combinar los dos con la función Atan2()
.
En C#
esto es
public struct Vector2
{
public double X, Y;
/// <summary>
/// Returns the angle between two vectos
/// </summary>
public static double GetAngle(Vector2 A, Vector2 B)
{
// |A·B| = |A| |B| COS(θ)
// |A×B| = |A| |B| SIN(θ)
return Math.Atan2(Cross(A,B), Dot(A,B));
}
public double Magnitude { get { return Math.Sqrt(Dot(this,this)); } }
public static double Dot(Vector2 A, Vector2 B)
{
return A.X*B.X+A.Y*B.Y;
}
public static double Cross(Vector2 A, Vector2 B)
{
return A.X*B.Y-A.Y*B.X;
}
}
class Program
{
static void Main(string[] args)
{
Vector2 A=new Vector2() { X=5.45, Y=1.12};
Vector2 B=new Vector2() { X=-3.86, Y=4.32 };
double angle=Vector2.GetAngle(A, B) * 180/Math.PI;
// angle = 120.16850967865749
}
}
Vea el caso de prueba arriba en GeoGebra.
Nadie señaló que si tiene un solo vector y desea encontrar el ángulo del vector desde el eje X, puede aprovechar el hecho de que el argumento de atan2 () es en realidad la pendiente de la línea, o (delta) Y / delta X). Entonces, si conoce la pendiente, puede hacer lo siguiente:
dado:
A = ángulo del vector / línea que desea determinar (desde el eje X).
m = pendiente firmada del vector / línea.
entonces:
A = atan2 (m, 1)
¡Muy útil!
No tiene que usar atan2 para calcular el ángulo entre dos vectores. Si solo quieres la forma más rápida, puedes usar dot(v1, v2)=|v1|*|v2|*cos A
para obtener
A = Math.acos( dot(v1, v2)/(v1.length()*v2.length()) );
Si te preocupa la precisión para ángulos pequeños, debes usar esto:
ángulo = 2 * atan2 (|| || b || a - || a || b ||, || || b || a + || a || b ||)
Donde "||" significa valor absoluto, AKA "longitud del vector". Ver https://math.stackexchange.com/questions/1143354/numerically-stable-method-for-angle-between-3d-vectors/1782769
Sin embargo, eso tiene la desventaja de que en dos dimensiones, pierde el signo del ángulo.
atan2(vector1.y - vector2.y, vector1.x - vector2.x)
es el ángulo entre el vector de diferencia (que conecta vector2 y vector1) y el eje x, que problably no es lo que usted quiso decir.
El ángulo (dirigido) de vector1 a vector2 se puede calcular como
angle = atan2(vector2.y, vector2.x) - atan2(vector1.y, vector1.x);
y es posible que desee normalizarlo en el rango 0 .. 2 * Pi
:
if (angle < 0) angle += 2 * M_PI;