Подскажите, вот у меня 2 вектора. я ищу угол между ними.
Правильна ли последовательность действий:
// Vector 1
V1x = 20;
V1y = 53;
// Vector 2
V2x = 48;
V2y = 18;
1) Нормализуем оба вектора
float length = sqrt (V1x * V1x + V1y * V1y);
float x = V1x / length;
float y = V1y / length;
float length2 = sqrt (V2x * V2x + V2y * V2y);
float x2 = V2x / length2;
float y2 = V2y / length2;
2) Находим DOT Product
float dot = (x * x2) + (y * y2);
3) Находим arccos от dot;
float angle = arccos(dot);
Верны ли шаги или я где то ошибся?
Спасибо.
Annihilator
Сейчас конкретно и не вспомню, но угол между векторами можно найти всего парой операций.
Annihilator
> Верны ли шаги
Да
можно быстрее (без деления и квадратных корней), проще, и без взятия аркосинуса от 1.000019817: http://users.livejournal.com/_winnie/237714.html
Annihilator
> Верны ли шаги или я где то ошибся?
Формально верны.
По факту - так обращаться с тригонометрией нельзя! Надо знать формулы, упрощающие расчёт.
Подробнее ответил _Winnie
_Winnie
спасибо. очень пригодилось.
> Только всё равно в функции angle замените аркосинусы на atan2. И проще, и безопасней.
объясните вот это выражение
1. atan2 требует проверки на сингулярность, acos - нет
2. atan2 принимает 2 параметра, acos - 1
где тут проще? где тут безопаснее?
EvilSpirit
>1. atan2 требует проверки на сингулярность, acos - нет
acos требует проверки на вхождение в диапазон [-1:1] всегда, а сингулярность чаще всего исключается алгоритмически/архитектурно.
> 2. atan2 принимает 2 параметра, acos - 1
думаю два параметра это меньше зло, чем две нормализации
aloha_hawaii
> acos требует проверки на вхождение в диапазон [-1:1]
не требует, векторы то нормализованные
> а сингулярность чаще всего исключается
только проверкой и никак больше
> чем две нормализации
ну да, кто бы спорил)
сам угол между векторами нужен достаточно редко. обычно нужно знать либо его косинус, либо синус, которые можно выразить из векторного/скалярного произведения, не используя тригонометрию.
EvilSpirit
>не требует, векторы то нормализованные
1a) вектора иногда нормализуются до длины 1.001231, и встречался несколько раз с крашем игры, когда acos возвращает NaN и этот NaN дальше расползается по всей игре.
1б) в исходном посте я не вижу утверждения что входные вектора нормализованные. я вижу что они приводятся к нормализованым после деления.
2) способ с atan2 не зависит от нормализованности векторов,
3) не требует деления, квадратных корней в 2d,
4) генерирует более простой и быстрый asm-код.
5) сохраняет информацию об знаке угле (против/по часовой стрелке)
>atan2 принимает 2 параметра, acos - 1
И? А операция сложения тоже принимает два параметра.
> где тут проще? где тут безопаснее?
вариант 1:
return atan2(ax*by - bx*ay, ax*bx + ay*by);
вариант 2:
float length = sqrt (V1x * V1x + V1y * V1y); float x = V1x / length; float y = V1y / length; if ( lenth == 0) //или length < EPSILON, что тоже некорректно return 0.0; float length2 = sqrt ( V2x * V2x + V2y * V2y); if ( length2 == 0) //или length2 < EPSILON, что тоже некорректно return 0.0; float x2 = V2x / length2; float y2 = V2y / length2; float dot = ( x * x2) + ( y * y2); if ( dot >= 1.0f) return 0.0f; else if ( dot <= -1.0f) return -M_PI; else return arccos( dot);
Вообще arccos в CRT для x86 реализован через atan2. Соответсвенно, использование acos - это "вылить воду из чайника, выключить газ, свести задачу к предыдущей".
> 1. atan2 требует проверки на сингулярность, acos - нет
Наоборот.
Suslik
> сам угол между векторами нужен достаточно редко. обычно нужно знать либо его косинус, либо синус, которые можно выразить из векторного/скалярного произведения, не используя тригонометрию.
+1
Suslik
+100500
сам только как первый пост прочитал, хотел написать это же =)))
Народ вот задача в том, что надо определить угол между 2мя векторами, и Вектор1 повернуть на этот угол чтобы он сровнялся с углом Вектора2 (симуляция Самонаводящейся Туррэли в игре)
Annihilator
зачнем угол то узнавать/менять?
нормализуй векторы и интерполируй плавно
HandriX
А по подробнее ? Если можно.
Вектор 1 - это статический вектор, а Вектор 2 двигается.
Вектор 1 - Крутится и когда угол с Вектор 2 совпадает, то он стреляет.
Тема в архиве.