Comment utiliser le produit scalaire pour obtenir un angle entre deux vecteurs?

16

J'apprends à utiliser des vecteurs normalisés dans mes jeux.

J'ai appris que pour connaître l'angle entre deux vecteurs, je peux utiliser le produit scalaire. Cela me donne une valeur entre -1 et 1, où

  • 1 signifie que les vecteurs sont parallèles et font face à la même direction (l'angle est de 180 degrés).
  • -1 signifie qu'ils sont parallèles et font face à des directions opposées (toujours à 180 degrés).
  • 0 signifie que l'angle entre eux est de 90 degrés.

Je veux savoir comment convertir le produit scalaire de deux vecteurs, en un angle réel en degrés. Par exemple, si le produit scalaire de deux vecteurs est 0.28, quel est l'angle correspondant, entre 0 et 360 degrés?

user3150201
la source
1
Notez que votre utilisation prévue du produit scalaire ne fonctionne que lorsque les vecteurs initiaux sont des vecteurs unitaires.
sam hocevar
@SamHocevar Oui, c'est ce que je voulais dire.
user3150201
1
@ user3150201 La réponse d'Alex est correcte, mais vous devez également vous demander si vous devez obtenir l'angle réel en degrés. Le seul cas où je peux penser où cela est vraiment nécessaire serait d'afficher quelque chose en degrés sur l'interface utilisateur. Sinon, il y a probablement peu d'applications où vous ne pourriez pas travailler directement avec des sinus et des cosinus.
TravisG

Réponses:

22

dot(A,B) = |A| * |B| * cos(angle)
qui peut être réorganisé
angle = arccos(dot(A,B) / (|A|* |B|)).

Avec cette formule, vous pouvez trouver le plus petit angle entre les deux vecteurs, qui sera compris entre 0 et 180 degrés. Si vous en avez besoin entre 0 et 360 degrés, cette question peut vous aider.


Soit dit en passant, l'angle entre deux vecteurs parallèles pointant dans la même direction devrait être de 0 degré et non de 180.

Alex
la source
+1 pour "Soit dit en passant, l'angle entre deux vecteurs parallèles pointant dans la même direction devrait être de 0 degré, pas 180."
Tara
8

Je vais développer un peu le commentaire de TravisG et donner une autre réponse, en utilisant le fait que votre question avait la balise "2D".

Vous pouvez obtenir l'angle entre deux vecteurs en utilisant le produit scalaire, mais vous ne pouvez pas obtenir l' angle signé entre deux vecteurs en l'utilisant. Autrement dit, si vous voulez tourner un personnage au fil du temps vers un point, le produit scalaire vous indiquera la distance à tourner mais pas dans quelle direction. Il existe cependant une autre formule simple qui est très utile lorsqu'elle est combinée avec le produit scalaire. Non seulement vous avez

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

Vous pouvez également avoir une autre formule (dont j'ai inventé le nom pour le politiquement correct):

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

où si A = (a, b), B = (x, y), alors pseudoCross (A, B) est défini comme étant le troisième composant du produit croisé (a, b, 0) x (x, y, 0 ). En d'autres termes:

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

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

L'angle complet signé est alors angle=atanfull(-b*x+a*y,a*x+b*y)(les fonctions atanfull ou atan2 vous pardonnent si vous passez des valeurs non normalisées). Si A et B sont normalisés, c'est-à-dire si |A|=|B|=1ce sont simplement:

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

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


Pour une explication plus approfondie, notez que les équations ci-dessus peuvent être exprimées par l'équation matricielle:

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

Mais a et b peuvent être exprimés en a=cos(ang1), b=sin(ang1)pour une certaine valeur ang1(non angle). Par conséquent, la matrice de gauche est une matrice de rotation qui fait tourner le vecteur (x, y) de la quantité -ang1. Cela équivaut à basculer dans un cadre de référence où le vecteur unitaire "A" est traité comme le vecteur / axe (1,0)! Donc, juste en dessinant le cercle unitaire / triangle rectangle dans ce cadre, vous pouvez voir pourquoi le vecteur résultant de ce produit est (cos (angle), sin (angle)).

Si vous écrivez (a, b) et (x, y) sous forme polaire, et appliquez les formules de différence d'angle cos(l)*cos(m)+sin(l)*sin(m)=cos(l-m)et sin(l)*cos(m)-cos(l)*sin(m)=sin(l-m), vous ré-exprimez que les sinus / cosinus sont donnés par ce produit, puisque (lm) = angle. Alternativement, ces identités pourraient être utilisées pour voir pourquoi le produit linéaire donné ci-dessus fait tourner un vecteur.

Toutes ces identités signifient que vous avez rarement besoin d'angles. Parce que les angles peuvent être étranges - radian / degrés, conventions pour sinus / cosinus inverse, le fait qu'ils se répètent tous les 2 * pi - cela peut en fait être plus utile et vous faire économiser un tas de logique "if (ang <180)", etc.


la source