Как рассчитать угол вектора от вертикали?
Im пытается выяснить угол (в градусах) между двумя 2D-векторами. Я знаю, что мне нужно использовать тригонометрию, но я не очень хорошо с ней справляюсь. Это то, что я пытаюсь выяснить (ось Y увеличивается вниз): alt текст http://i38.tinypic.com/2dcefch.png
Я пытаюсь использовать этот код на данный момент, но он не работает вообще (вычисляет случайные углы по какой-то причине):
private float calcAngle(float x, float y, float x1, float y1)
{
float _angle = (float)Math.toDegrees(Math.atan2(Math.abs(x1-x), Math.abs(y1-y)));
Log.d("Angle","Angle: "+_angle+" x: "+x+" y: "+y+" x1: "+x1+" y1: "+y1);
return _angle;
}
Это мои результаты (там константа при предоставлении постоянной позиции, но когда я меняю положение, угол меняется, и я не могу найти никакой связи между двумя углами):
положение 1: x: 100 y: 100 x1: 50 y1:50 Угол: 45
положение 2: x: 92 y: 85 x1: 24 y1:16 Угол: 44.58
положение 3: x: 44 y: 16 x1: 106 y1:132 Угол: 28.12
Edit: спасибо всем, кто ответил и помог мне понять, что это было неправильно! Извините, название и вопрос сбивали с толку.
9 ответов
сначала вы должны понять, как вычислить угол между двумя векторами и их несколько. Я дам вам то, что считаю самым простым.
- дано v1 и v2 их скалярное произведение:
v1x * v2x + v1y * v2y
- норма вектора v дано: sqtr (vx^2+vy^2)
С этой информацией, пожалуйста, данное определение:
dot(v1, v2) = norm(v1) * norm(v2) * cos(angle(v1, v2))
теперь, вы решаете для angle(v1, v2)
:
angle(v1, v2) = acos( dot(v1, v2) / (norm(v1) * norm(v2)) )
наконец, принимая определения, приведенные в начале, то вы в конечном итоге с:
angle(v1, v2) = acos( (v1x * v2x + v1y * v2y) / (sqrt(v1x^2+v1y^2) * sqrt(v2x^2+v2y^2)) )
опять же, есть много способов сделать это, но мне нравится этот, потому что это полезно для точечного продукта, заданного углом и нормой, или углом, заданными векторами.
ответ будет в радианах, но вы знаете, что радианы pi (то есть 3,14 Радиана) составляют 180 градусов, поэтому вы просто умножаете на коэффициент преобразования 180/pi.
Аха! Оказывается, мне просто нужно было перевернуть угол и использовать atan2. Это мой последний код:
private float calcAngle(float x, float y, float x1, float y1)
{
float _angle = (float)Math.toDegrees(Math.atan2(x1-x, y-y1));
return _angle;
}
спасибо всем за то, что помогли мне понять это, а также за то, что помогли мне понять, что я на самом деле делаю! :)
не принимать абсолютное значение аргументов в atan2
. Весь смысл atan2
заключается в том, что он использует знаки своих аргументов для определения того, в каком qaudrant находится угол. Принимая абсолютные значения, которые вы заставляете atan2
возвращать только значения между 0 и pi / 2 вместо-pi в pi.
избегается деление потенциала на ноль в пределах atan2 ()- возвращаемое значение всегда положительно в диапазоне от 0 до 360 градусов
atan2()
возвращает угол против часовой стрелки относительно положительной оси X. Найл искал угол по часовой стрелке относительно положительной оси Y (между вектором, образованным двумя точками и положительной осью Y).
следующая функция адаптирована из моей игры asteroids, где я хотел рассчитать направление, в котором вектор корабля / скорости " указывал:"
// Calculate angle between vector from (x1,y1) to (x2,y2) & +Y axis in degrees.
// Essentially gives a compass reading, where N is 0 degrees and E is 90 degrees.
double bearing(double x1, double y1, double x2, double y2)
{
// x and y args to atan2() swapped to rotate resulting angle 90 degrees
// (Thus angle in respect to +Y axis instead of +X axis)
double angle = Math.toDegrees(atan2(x1 - x2, y2 - y1));
// Ensure result is in interval [0, 360)
// Subtract because positive degree angles go clockwise
return (360 - angle) % 360;
}
Я считаю, что уравнение для угла между двумя векторами должно выглядеть как:
toDegrees(acos((x*x1+y*y1)/(sqrt(x*x+y*y)*sqrt(x1*x1+y1*y1))))
ваше выше уравнение вычислит угол, сделанный между вектором p1-p2 и линией, сделанной путем расширения ортогонального от точки p2 до вектора p1.
точечное произведение двух векторов V1 и V2 равно |V1|*|V2/cos (тета). Поэтому тета равна acos ((v1 dot V2)/(|V1| / V2|)). V1 точка V2-Это V1.xV2.x+V1.yV2.год. Этот величина V (т. е. |V|) является теоремой патогореана... sqrt (V. x^2 + V. y^2)
должно быть :
atan( abs(x1 - x)/abs(y1 - y) )
abs
означает Абсолют (во избежание отрицательных значений)
моей первой догадкой было бы вычислить угол каждого вектора с осями, используя atan (y/x), а затем вычесть этих ангелов и принять абсолютное значение, то есть:
abs(atan(y/x) - atan (y1/x1))
вы используете целые числа? Приведите аргументы как двойные, и я бы использовал fabs для результата, а не аргументы. Результат будет в радианах; чтобы получить степени, используйте:
res * = (360.0 / (2.0 * Math.PI));
угол второго вектора относительно первого = atan2(y2,x2) - atan2(y1,x1)
.
http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm