Как использовать точечное произведение, чтобы получить угол между двумя векторами?

16

Я учусь использовать нормализованные векторы в моих играх.

Я узнал, что для того, чтобы узнать угол между двумя векторами, я могу использовать скалярное произведение. Это дает мне значение от -1 до 1, где

  • 1 означает, что векторы параллельны и направлены в одном направлении (угол составляет 180 градусов).
  • -1 означает, что они параллельны и обращены в разные стороны (еще 180 градусов).
  • 0 означает, что угол между ними составляет 90 градусов.

Я хочу знать, как преобразовать скалярное произведение двух векторов в фактический угол в градусах. Например, если скалярное произведение двух векторов равно 0.28какому соответствующему углу от 0 до 360 градусов?

user3150201
источник
1
Обратите внимание, что предполагаемое использование точечного произведения работает только тогда, когда начальные векторы являются единичными векторами.
Сэм Хоцевар
@ SamHocevar Да, это то, что я имел в виду.
user3150201
1
@ user3150201 Алекс ответ правильный, но вы должны также подумать, нужно ли вообще получать фактический угол в градусах. Единственный случай, когда я могу подумать, где это действительно необходимо, - это отображать что-то в градусах на интерфейсе пользователя. В противном случае, вероятно, есть несколько приложений, в которых вы не могли бы работать напрямую с синусами и косинусами.
TravisG

Ответы:

22

dot(A,B) = |A| * |B| * cos(angle)
который может быть переставлен в
angle = arccos(dot(A,B) / (|A|* |B|)).

С помощью этой формулы вы можете найти наименьший угол между двумя векторами, который будет между 0 и 180 градусами. Если вам нужно от 0 до 360 градусов, этот вопрос может вам помочь.


Кстати, угол между двумя параллельными векторами, указывающими в одном направлении, должен быть 0 градусов, а не 180.

Alex
источник
+1 за "Кстати, угол между двумя параллельными векторами, указывающими в одном направлении, должен быть 0 градусов, а не 180".
Тара
8

Я немного расширю комментарий TravisG и дам другой ответ, используя тот факт, что ваш вопрос имеет тег «2D».

Вы можете получить угол между двумя векторами , используя скалярное произведение, но вы не можете получить подписанный угла между двумя векторами , используя его. Иными словами, если вы хотите со временем повернуть персонажа к точке, точечный продукт даст вам, сколько повернуть, а не в каком направлении. Однако есть еще одна простая формула, которая очень полезна в сочетании с точечным произведением. Не только у вас есть

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

У вас также может быть другая формула (имя которой я придумал для политкорректности):

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

где, если A = (a, b), B = (x, y), то псевдокросс (A, B) определяется как третий компонент кросс-произведения (a, b, 0) x (x, y, 0 ). Другими словами:

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

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

Тогда полный угол со angle=atanfull(-b*x+a*y,a*x+b*y)знаком равен (функции atanfull или atan2 простят вас, если вы передаете ненормализованные значения). Если A и B нормализованы, то есть, если |A|=|B|=1это просто:

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

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


Для более глубокого объяснения обратите внимание, что приведенные выше уравнения могут быть выражены матричным уравнением:

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

Но и Ь может быть выражен как a=cos(ang1), b=sin(ang1)для некоторого значения ang1(не angle). Следовательно, матрица слева является матрицей вращения, которая поворачивает вектор (x, y) на величину -ang1. Это эквивалентно переходу в систему отсчета, где единичный вектор «А» рассматривается как вектор / ось (1,0)! Итак, просто нарисовав единичную окружность / прямоугольный треугольник в этом кадре, вы можете увидеть, почему результирующий вектор этого произведения равен (cos (угол), sin (угол)).

Если вы напишите (a, b) и (x, y) в полярной форме и примените формулы разности углов, cos(l)*cos(m)+sin(l)*sin(m)=cos(l-m)и sin(l)*cos(m)-cos(l)*sin(m)=sin(l-m)вы повторно выразите, что синус / косинус задаются этим продуктом, поскольку (lm) = угол. Альтернативно, эти тождества могут быть использованы, чтобы понять, почему приведенное выше линейное произведение вращает вектор.

Все эти идентичности означают, что вам редко нужны углы. Поскольку углы могут быть странными - радианы / градусы, условные обозначения для обратных синусов / косинусов, тот факт, что они повторяются каждые 2 * пи - это может быть более полезным и сэкономить вам кучу логики «если (анг <180)» и т. Д.


источник