Як я можу використовувати крапковий продукт, щоб отримати кут між двома векторами?


16

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

Я дізнався, що для того, щоб знати кут між двома векторами, я можу використовувати крапковий продукт. Це дає мені значення від -1 до 1, де

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

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


1
Зауважте, що призначене для використання точкове виріб працює лише тоді, коли початкові вектори є одиничними векторами.
sam hocevar

@SamHocevar Так, саме це я мав на увазі.
користувач3150201


1
@ user3150201 Відповідь Алекса є правильною, але ви також повинні врахувати, чи потрібно взагалі отримувати фактичний кут у градусах. Єдиний випадок, коли я можу придумати, де це насправді необхідно, - це показати щось у градусах на інтерфейсі користувача. В іншому випадку, напевно, мало програм, де ви не могли працювати безпосередньо з синусами та косинусами.
TravisG

Відповіді:


22

dot(A,B) = |A| * |B| * cos(angle)
які можна переставити на
angle = arccos(dot(A,B) / (|A|* |B|)).

За допомогою цієї формули ви можете знайти найменший кут між двома векторами, який буде між 0 і 180 градусами. Якщо вам це потрібно від 0 до 360 градусів, це питання може вам допомогти.


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


+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 * пі - це насправді може бути кориснішим і заощадить вам купу логіки "if (ang <180)" тощо.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.