Нахождение угла между векторами - самая обычная, часто возникающая задача в компьютерной графике. Пусть, например, нам даны два вектора на плоскости с целыми координатами v1=(x1 , y1 ), v2=(x2 , y2 ). Косинус угла между ними равен
(x1*x2+y1*y2)/(sqrt(x1*x1+y1*y1)*sqrt(x2*x2+y2*y2))
double angle( int x1, int y1, int x2, int y2) { return acos( (x1*x2+y1*y2)/(sqrt((double)x1*x1+y1*y1)*sqrt((double)x2*x2+y2*y2))); }
Здесь (double)x1 приходится писать, чтобы явно указать компилятору, какой именно вариант функции sqrt использовать, а именно - квадратный корень из double.
Проверим:
Но давайте найдем угол вектора с самим собой. Конечно, угол должен быть равен 0. Часто так и получается. Но проверим для вектора (2,3) :
Неужели компьютер сломался? Нет, конечно.
Так почему же? Всё просто.
x1*x1+y1*y1=13, sqrt(x1*x1+y1*y1)=3.6055512754640
sqrt(x1*x1+y1*y1)*sqrt(x1*x1+y1*y1)=12.999999999999998
Поэтому величина
(x1*x2+y1*y2)/(sqrt(x1*x1+y1*y1)*sqrt(x2*x2+y2*y2)
Как же быть? Да ничего сложного, просто придется функцию несколько усложнить, например так:
double angle( int x1, int y1, int x2, int y2) { double t = (x1*x2+y1*y2)/(sqrt((double)x1*x1+y1*y1)*sqrt((double)x2*x2+y2*y2)); if (t<-1) t=-1; else if(t> 1) t= 1; return acos(t); }