Calculer l'angle de direction à partir de deux vecteurs?
Question
Dire que j'ai deux vecteurs 2D, l'un pour une position actuelle des objets et l'autre pour que les objets position précédente. Comment puis-je travailler la direction angulaire de Voyage?
Cette image peut aider à comprendre ce que je suis après:
La solution
Le vecteur de direction de Voyage sera la différence des deux vecteurs de position,
d = (x1, y1) - (x, y) = (x1 - x, y1 - y)
Maintenant, quand vous demandez l'angle de direction, cela dépend dans quelle direction vous voulez mesurer l'angle contre. Est-ce contre l'axe x? Aller avec la réponse de Radu. Contre un vecteur arbitraire? Voir la réponse justjeff.
Edit: Pour obtenir l'angle contre l'axe y:
tan (theta) = (x1 -x)/(y1 - y)
la tangente de l'angle est le rapport de la coordonnée x du vecteur de différence à la coordonnée y du vecteur de différence.
theta = arctan[(x1 - x)/(y1 - y)]
Où arctan moyens de tangente inverse. À ne pas confondre avec l'inverse de la tangente, que beaucoup de gens le font, car ils sont tous les deux souvent tan ^ -1 notée. Et assurez-vous de savoir si vous travaillez en degrés ou radians.
Autres conseils
Si vous êtes en C (ou autre langue qui utilise le même jeu de fonction), alors vous êtes probablement pour la fonction atan2()
. A partir de votre schéma:
double theta = atan2(x1-x, y1-y);
Cet angle sera de l'axe vertical, comme vous avez marqué, et sera mesurée dans radians (propre unité d'angle de Dieu).
Veillez à utiliser atan2 pour éviter les problèmes de quadrant et division par zéro. C'est ce qu'il est là pour cela.
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;
}
Cependant, si vous ne se soucient pas que ce soit un + ve ou angle -ve, il suffit d'utiliser la règle de produit scalaire (moins de charge 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;
}
Notez que dans une des sections de code ci-dessus, si un des vecteurs (ou les deux) sont proches de 0 longueur cela va à l'échec. Donc, vous voudrez peut-être piège en quelque sorte.
Toujours pas sûr ce que vous entendez par des matrices de rotation, mais c'est un cas simple d'obtenir un azimut à partir d'un vecteur de direction.
La réponse complexe:
Normalement, vous devez emballer quelques fonctions de conversion / utilitaires avec vos vecteurs 2D: l'un pour convertir X, Y (cartésienne) à Theta, R (Les coordonnées polaires). Vous devez également prendre en charge les opérations de vecteur de base comme l'addition, et soustractions produit scalaire. Votre réponse dans ce cas serait:
double azimuth = (P2 - P1).ToPolarCoordinate().Azimuth;
Où ToPolarCoordinate () et ToCarhtesianCoordinate () sont deux fonctions inverses de commutation d'un type de vecteur à un autre.
Le simple:
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
}