2010-04-03 15 views
12

Digamos que tengo dos vectores 2D, uno para una posición actual de objetos y otro para la posición anterior de objetos. ¿Cómo puedo calcular la dirección angular del viaje?¿Calcula el ángulo de dirección desde dos vectores?

Esta imagen podría ayudar a entender lo que busco:

(image) http://files.me.com/james.ingham/crcvmy

+0

¿Puedes explicar un poco más? ¿Esto es en el espacio 2D o 3D, puede dar un ejemplo de código y cómo se ven sus matrices? ¿Están estas matrices almacenando datos de rotación (probablemente debería ser un cuaternión) o están describiendo transformaciones? –

+0

http://en.wikipedia.org/wiki/Slope_formula? – Ross

+0

Gracias Ross, actualmente estoy intentando poner las respuestas en práctica. Te dejaré saber cómo me llevo en un segundo ... –

Respuesta

10

El vector de dirección de la marcha será la diferencia de los dos vectores de posición,

d = (x1, y1) - (x, y) = (x1 - x, y1 - y) 

Ahora cuando se pide el ángulo de dirección, que depende en qué dirección quieres medir el ángulo en contra. ¿Está contra el eje x? Ve con la respuesta de Radu. Contra un vector arbitrario? Ver la respuesta de justjeff.

Editar: Para obtener el ángulo contra el eje y:

tan (theta) = (x1 -x)/(y1 - y)   

la tangente del ángulo es la relación de la coordenada x del vector de diferencia para la coordenada y del vector de diferencia.

Así

theta = arctan[(x1 - x)/(y1 - y)] 

Dónde arctan significa tangente inversa. No debe confundirse con el recíproco de la tangente, lo que mucha gente hace, ya que ambos se denominan con frecuencia tan^-1. Y asegúrese de saber si está trabajando en grados o radianes.

+0

En realidad, es contra el eje Y que estoy buscando –

+0

@ james.ingham: espero que ayude. –

+0

Gracias Fue arctan lo que estaba buscando! :) –

2

Aún no sabe qué quiere decir con las matrices de rotación, pero este es un caso simple de conseguir un azimut de un vector de dirección.

La respuesta complicada:

Normalmente debería empacar un par de funciones de conversión A/utilidad con sus vectores 2D: una para convertir de X, Y (cartesianos) a Theta, R (coordenadas polares). También debería admitir operaciones básicas de vectores como adición, sustracción y producto escalar. Su respuesta en este caso sería:

double azimuth = (P2 - P1).ToPolarCoordinate().Azimuth; 

Dónde ToPolarCoordinate() y ToCarhtesianCoordinate() son dos funciones recíprocas cambiar de un tipo de vector a otro.

El sencillo:

double azimuth = acos ((x2-x1)/sqrt((x2-x1) * (x2-x1) + (y2-y1) * (y2-y1)); 
//then do a quadrant resolution based on the +/- sign of (y2-y1) and (x2-x1) 
if (x2-x1)>0 { 
    if (y2-y1)<0 { azimuth = Pi-azimuth; } //quadrant 2 
} else 
{ if (y2-y1)> 0 { azimuth = 2*Pi-azimuth;} //quadrant 4 
    else { azimuth = Pi + azimuth;} //quadrant 3 
} 
+0

Lo siento, actualicé la pregunta pero no el título con respecto a las cosas de la matriz ... –

9

Si está en C (u otro idioma que use el mismo conjunto de funciones), entonces probablemente esté buscando la función atan2(). A partir de su diagrama:

double theta = atan2(x1-x, y1-y); 

Este ángulo será desde el eje vertical, como se ha marcado, y se mide en radianes (unidad de ángulo propio de Dios).

5

Tenga cuidado al usar atan2 para evitar problemas de cuadrante y división por cero. Para eso está ahí.

float getAngle(CGPoint ptA, CGPoint ptOrigin, CGPoint ptB) 
{ 
    CGPoint A = makeVec(ptOrigin, ptA); 
    CGPoint B = makeVec(ptOrigin, ptB); 

    // angle with +ve x-axis, in the range (−π, π] 
    float thetaA = atan2(A.x, A.y); 
    float thetaB = atan2(B.x, B.y); 

    float thetaAB = thetaB - thetaA; 

    // get in range (−π, π] 
    while (thetaAB <= - M_PI) 
     thetaAB += 2 * M_PI; 

    while (thetaAB > M_PI) 
     thetaAB -= 2 * M_PI; 

    return thetaAB; 
} 

Sin embargo, si no se preocupan por si se trata de un + ve o -ve ángulo, sólo tiene que utilizar la regla del producto de punto (menos carga de la CPU):

float dotProduct(CGPoint p1, CGPoint p2) { return p1.x * p2.x + p1.y * p2.y; } 

float getAngle(CGPoint A, CGPoint O, CGPoint B) 
{ 
    CGPoint U = makeVec(O, A); 
    CGPoint V = makeVec(O, B); 

    float magU = vecGetMag(U); 
    float magV = vecGetMag(V); 
    float magUmagV = magU * magV; assert (ABS(magUmagV) > 0.00001); 

    // U.V = |U| |V| cos t 
    float cosT = dotProduct(U, V)/magUmagV; 
    float theta = acos(cosT); 
    return theta; 
} 

Tenga en cuenta que en cualquier código La sección anterior, si uno (o ambos) vectores tienen una longitud cercana a 0, esto va a fallar. Entonces quizás quieras atrapar eso de alguna manera.

Cuestiones relacionadas