Скалярное произведение
Одно число, по знаку которого видно, смотрят векторы в одну сторону или в разные. Проекция, перпендикулярность и угол.
3 мин
Скалярное произведение двух векторов — число:
Два выражения равны — это несложное упражнение на раскрытие скобок. Пользоваться будем вторым: оно считается по координатам, без всякой тригонометрии.
Скалярное произведение симметрично: . Косинусу безразлично направление угла, потому что .
Геометрический смысл
Величина — длина проекции на направление (со знаком). Значит,
Отсюда — вся польза.
Знак
| знак | угол | смысл |
|---|---|---|
| положительный | меньше | смотрят «в одну сторону» |
| ноль | ровно | перпендикулярны |
| отрицательный | больше | смотрят «в разные стороны» |
Это первое из двух главных применений: проверка перпендикулярности и проверка «вперёд или назад».
if (a * b == 0) { /* перпендикулярны */ }
if (a * b > 0) { /* смотрят в одну сторону */ }
(В шаблоне скалярное произведение обычно вешают на operator*.)
Косинус и угол
Из определения сразу получается косинус:
Соблазн взять acos от этого и получить угол. Так делать можно, но с оговоркой: acos возвращает значение от до , то есть теряет знак угла. Развёрнут ли относительно влево или вправо, по косинусу не узнать.
Правильный способ — функция atan2, которая берёт оба произведения сразу:
long double angle = atan2(a % b, a * b); // векторное, затем скалярное
Она возвращает угол от до , со знаком, и не требует ручного разбора случаев. Порядок аргументов запомнить легко: сначала то, что отвечает за синус (векторное), потом за косинус (скалярное).
Есть и вторая причина не считать угол без нужды: acos теряет точность у краёв диапазона, а из-за погрешности аргумент вообще может оказаться чуть больше единицы, и функция вернёт NaN. Если задача не просит угол явно — не считайте его.
Проекция точки
Проекция вектора на направление :
Знаменатель — квадрат длины, а не длина: одно деление вместо корня и нормировки.
Этим считается проекция точки на прямую и, через неё, симметричная точка.
Целые числа
Если координаты целые, скалярное произведение целое — никаких потерь точности. Считайте его в long long: при координатах до произведение доходит до , и int переполнится молча.
Это одна из самых частых ошибок в геометрии: шаблон, написанный когда-то с int, годами работает и однажды даёт неверный ответ на большом тесте.
Что оно не умеет
Скалярное произведение не различает «слева» и «справа». Векторы и его отражение относительно дают одинаковое скалярное произведение — угол-то по модулю тот же.
Для стороны нужно векторное произведение. Вместе они полностью определяют взаимное расположение двух векторов.