Come posso usare il prodotto punto per ottenere un angolo tra due vettori?


16

Sto imparando ad usare vettori normalizzati nei miei giochi.

Ho imparato che per conoscere l'angolo tra due vettori, posso usare il prodotto punto. Questo mi dà un valore tra -1 e 1, dove

  • 1 indica che i vettori sono paralleli e rivolti nella stessa direzione (l'angolo è di 180 gradi).
  • -1 significa che sono paralleli e rivolti in direzioni opposte (ancora 180 gradi).
  • 0 significa che l'angolo tra loro è di 90 gradi.

Voglio sapere come convertire il prodotto punto di due vettori, in un angolo reale in gradi. Ad esempio, se il prodotto punto di due vettori è 0.28, qual è l'angolo corrispondente, tra 0 e 360 ​​gradi?


1
Si noti che l'uso previsto del prodotto punto funziona solo quando i vettori iniziali sono vettori unità.
Sam Hocevar,

@SamHocevar Sì, questo è ciò che intendevo.
user3150201,


1
@utente3150201 La risposta di Alex è corretta, ma dovresti anche considerare se è necessario ottenere l'angolo effettivo in gradi. L'unico caso in cui riesco a pensare dove sia veramente necessario sarebbe quello di visualizzare qualcosa in gradi sull'interfaccia utente. Altrimenti, ci sono probabilmente poche applicazioni in cui non è possibile lavorare direttamente con seno e coseno.
TravisG,

Risposte:


22

dot(A,B) = |A| * |B| * cos(angle)
che può essere riorganizzato in
angle = arccos(dot(A,B) / (|A|* |B|)).

Con questa formula, puoi trovare l'angolo più piccolo tra i due vettori, che sarà tra 0 e 180 gradi. Se ne hai bisogno tra 0 e 360 ​​gradi questa domanda può aiutarti.


A proposito, l'angolo tra due vettori paralleli che puntano nella stessa direzione dovrebbe essere 0 gradi, non 180.


+1 per "A proposito, l'angolo tra due vettori paralleli che puntano nella stessa direzione dovrebbe essere 0 gradi, non 180."
Tara,

8

Espanderò un po 'il commento di TravisG e darò un'altra risposta, sfruttando il fatto che la tua domanda avesse il tag "2D".

È possibile ottenere l'angolo tra due vettori che utilizzano il prodotto scalare, ma non è possibile ottenere il sottoscritto angolo tra due vettori usarlo. Detto in altro modo, se vuoi trasformare un personaggio nel tempo verso un punto, il prodotto punto ti farà capire quanto girare ma non in quale direzione. Esiste un'altra formula semplice, che è molto utile se combinata con il prodotto punto. Non solo hai

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

Puoi anche avere un'altra formula (il cui nome ho inventato per correttezza politica):

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

dove se A = (a, b), B = (x, y), allora pseudoCross (A, B) è definito come il terzo componente del prodotto incrociato (a, b, 0) x (x, y, 0 ). In altre parole:

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

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

L'angolo con angle=atanfull(-b*x+a*y,a*x+b*y)segno completo è quindi (le funzioni atanfull o atan2 ti perdonano se passi valori non normalizzati). Se A e B sono normalizzati, ovvero se |A|=|B|=1questi sono semplicemente:

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

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


Per una spiegazione più profonda, nota che le equazioni sopra possono essere espresse dall'equazione di matrice:

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

Ma A e B possono essere espresse come a=cos(ang1), b=sin(ang1)ad un certo valore ang1(non angle). Pertanto, la matrice a sinistra è una matrice di rotazione che ruota il vettore (x, y) della quantità -ang1. Ciò equivale a passare a un quadro di riferimento in cui il vettore di unità "A" viene trattato come vettore / asse (1,0)! Quindi, semplicemente disegnando il cerchio unitario / triangolo rettangolo in questa cornice, puoi vedere perché il vettore risultante di quel prodotto è (cos (angolo), sin (angolo)).

Se si scrive (a, b) e (x, y) in forma polare, e si applicano le formule di differenza d'angolo cos(l)*cos(m)+sin(l)*sin(m)=cos(l-m)e sin(l)*cos(m)-cos(l)*sin(m)=sin(l-m), si re-esprime che i seni / coseni sono dati da questo prodotto, poiché (lm) = angolo. In alternativa, tali identità potrebbero essere utilizzate per capire perché il prodotto lineare sopra indicato ruota un vettore.

Tutte queste identità significano che raramente hai bisogno di angoli. Poiché gli angoli possono essere strani - radianti / gradi, convenzioni per seno / coseno inversi, il fatto che si ripetano ogni 2 * pi - questo può effettivamente essere più utile e risparmiare un sacco di logica "if (ang <180)" ecc.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.