Como uso o produto escalar para obter um ângulo entre dois vetores?

16

Estou aprendendo a usar vetores normalizados em meus jogos.

Aprendi que, para conhecer o ângulo entre dois vetores, posso usar o produto escalar. Isso me dá um valor entre -1 e 1, em que

  • 1 significa que os vetores são paralelos e estão na mesma direção (o ângulo é de 180 graus).
  • -1 significa que eles são paralelos e estão voltados para direções opostas (ainda 180 graus).
  • 0 significa que o ângulo entre eles é de 90 graus.

Quero saber como converter o produto escalar de dois vetores, em um ângulo real em graus. Por exemplo, se o produto escalar de dois vetores for 0.28, qual é o ângulo correspondente entre 0 e 360 ​​graus?

user3150201
fonte
1
Observe que o uso pretendido do produto escalar funciona apenas quando os vetores iniciais são vetores unitários.
Sam Hocevar
@ SamHocevar Sim, foi o que eu quis dizer.
usar o seguinte comando
1
@ user3150201 A resposta de Alex está correta, mas você também deve considerar se precisa obter o ângulo real em graus. O único caso em que posso pensar onde isso é realmente necessário seria exibir algo em graus na interface do usuário. Caso contrário, provavelmente existem poucas aplicações em que você não poderia trabalhar diretamente com senos e co-senos.
TravisG

Respostas:

22

dot(A,B) = |A| * |B| * cos(angle)
que pode ser reorganizado para
angle = arccos(dot(A,B) / (|A|* |B|)).

Com esta fórmula, você pode encontrar o menor ângulo entre os dois vetores, que estará entre 0 e 180 graus. Se você precisar entre 0 e 360 ​​graus, essa pergunta pode ajudá-lo.


A propósito, o ângulo entre dois vetores paralelos apontando na mesma direção deve ser 0 graus, não 180.

Alex
fonte
+1 para "A propósito, o ângulo entre dois vetores paralelos apontando na mesma direção deve ser 0 graus, não 180".
Tara
8

Vou expandir um pouco o comentário do TravisG e dar outra resposta, aproveitando o fato de sua pergunta ter a tag "2D".

Você pode obter o ângulo entre dois vetores usando o produto de ponto, mas não pode obter o ângulo assinado entre dois vetores usando-o. Dito de outra forma, se você deseja transformar um personagem ao longo do tempo em direção a um ponto, o produto escalar indica quanto girar, mas não em qual direção. Há outra fórmula simples, no entanto, que é muito útil quando combinada com o produto escalar. Você não apenas tem

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

Você também pode ter outra fórmula (cujo nome eu inventei no politicamente correto):

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

onde se A = (a, b), B = (x, y), então pseudoCross (A, B) é definido como o terceiro componente do produto cruzado (a, b, 0) x (x, y, 0 ) Em outras palavras:

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

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

O ângulo total assinado é então angle=atanfull(-b*x+a*y,a*x+b*y)(as funções atanfull ou atan2 perdoam se você passar valores não normalizados). Se A e B são normalizados, isto é, se |A|=|B|=1são simplesmente:

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

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


Para uma explicação mais profunda, observe que as equações acima podem ser expressas pela equação da matriz:

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

Mas a e b pode ser expresso como a=cos(ang1), b=sin(ang1)por algum valor ang1(não angle). Portanto, a matriz à esquerda é uma matriz de rotação que gira o vetor (x, y) pela quantidade -ang1. Isso é equivalente a mudar para um quadro de referência onde o vetor unitário "A" é tratado como o vetor / eixo (1,0)! Então, apenas desenhando o círculo unitário / triângulo retângulo nesse quadro, você pode ver por que o vetor resultante desse produto é (cos (ângulo), sin (ângulo)).

Se você escrever (a, b) e (x, y) na forma polar, e aplicar as fórmulas de diferença de ângulo cos(l)*cos(m)+sin(l)*sin(m)=cos(l-m)esin(l)*cos(m)-cos(l)*sin(m)=sin(l-m) , você expressará novamente que os senos / cossenos são dados por este produto, pois (lm) = ângulo. Alternativamente, essas identidades podem ser usadas para ver por que o produto linear dado acima gira um vetor.

Todas essas identidades significam que você raramente precisa de ângulos. Como os ângulos podem ser estranhos - radiano / graus, convenções para seno / cosseno inverso, o fato de que eles se repetem a cada 2 * pi - isso pode realmente ser mais útil e economizar um monte de lógica "se (ang <180)" etc.


fonte