Скажем, у меня два 2D-вектора: один для текущей позиции объектов и один для этой предыдущей позиции объектов. Как я могу определить направление движения angular?
Это изображение может помочь понять, что мне нужно:
Скажем, у меня два 2D-вектора: один для текущей позиции объектов и один для этой предыдущей позиции объектов. Как я могу определить направление движения angular?
Это изображение может помочь понять, что мне нужно:
Вектор направления движения будет разностью двух векторов положения,
d = (x1, y1) - (x, y) = (x1 - x, y1 - y)
Теперь, когда вы запрашиваете угол направления, это зависит от того, в каком направлении вы хотите измерить угол. Это против оси x? Пойдите с ответом Раду. Против произвольного вектора? См. Ответ justjeff.
Изменить: получить угол против оси y:
tan (theta) = (x1 -x)/(y1 - y)
тангенсом угла является отношение x-координаты разностного вектора к y-координате разностного вектора.
Итак,
theta = arctan[(x1 - x)/(y1 - y)]
Где arctan означает обратную касательную. Не путать с обратным касательной, что многие люди делают, поскольку оба они часто обозначаются tan ^ -1. И убедитесь, что вы знаете, работаете ли вы в градусах или радианах.
Если вы находитесь на C (или другом языке, который использует тот же набор функций), вы, вероятно, ищете функцию atan2()
. Из диаграммы:
double theta = atan2(x1-x, y1-y);
Этот угол будет от вертикальной оси, как вы отметили, и будет измеряться в радианах (единица измерения собственного угла).
Будьте осторожны, чтобы использовать atan2, чтобы избежать проблем с квадрантом и деления на ноль. Это то, что там есть.
float getAngle(CGPoint ptA, CGPoint ptOrigin, CGPoint ptB)
{
CGPoint A = makeVec(ptOrigin, ptA);
CGPoint B = makeVec(ptOrigin, ptB);
// angle with +ve x-axis, in the range (−π, π]
float thetaA = atan2(A.x, A.y);
float thetaB = atan2(B.x, B.y);
float thetaAB = thetaB - thetaA;
// get in range (−π, π]
while (thetaAB <= - M_PI)
thetaAB += 2 * M_PI;
while (thetaAB > M_PI)
thetaAB -= 2 * M_PI;
return thetaAB;
}
Однако, если вам неважно, есть ли это + ve или -ve angle, просто используйте правило продукта dot (меньше загрузки процессора):
float dotProduct(CGPoint p1, CGPoint p2) { return p1.x * p2.x + p1.y * p2.y; }
float getAngle(CGPoint A, CGPoint O, CGPoint B)
{
CGPoint U = makeVec(O, A);
CGPoint V = makeVec(O, B);
float magU = vecGetMag(U);
float magV = vecGetMag(V);
float magUmagV = magU * magV; assert (ABS(magUmagV) > 0.00001);
// U.V = |U| |V| cos t
float cosT = dotProduct(U, V) / magUmagV;
float theta = acos(cosT);
return theta;
}
Обратите внимание, что в любом вышеприведенном разделе кода, если один (или оба) вектора близки к 0, это приведет к сбою. Таким образом, вы можете каким-то образом уловить это.
Все еще не уверен, что вы подразумеваете под матрицами вращения, но это простой случай получения азимута от вектора направления.
Сложный ответ:
Обычно вы должны упаковать несколько функций преобразования/полезности с помощью двухмерных векторов: один для преобразования из X, Y (carthesian) в Theta, R (полярные координаты). Вы также должны поддерживать базовые векторные операции, такие как сложение, вычитание и точечный продукт. Ваш ответ в этом случае будет следующим:
double azimuth = (P2 - P1).ToPolarCoordinate().Azimuth;
Где ToPolarCoordinate() и ToCarhtesianCoordinate() - две взаимные функции, переходящие от одного типа вектора к другому.
Простой:
double azimuth = acos ((x2-x1)/sqrt((x2-x1) * (x2-x1) + (y2-y1) * (y2-y1));
//then do a quadrant resolution based on the +/- sign of (y2-y1) and (x2-x1)
if (x2-x1)>0 {
if (y2-y1)<0 { azimuth = Pi-azimuth; } //quadrant 2
} else
{ if (y2-y1)> 0 { azimuth = 2*Pi-azimuth;} //quadrant 4
else { azimuth = Pi + azimuth;} //quadrant 3
}