Как рассчитать угол вектора от вертикали?

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 ответов


сначала вы должны понять, как вычислить угол между двумя векторами и их несколько. Я дам вам то, что считаю самым простым.

  1. дано v1 и v2 их скалярное произведение: v1x * v2x + v1y * v2y
  2. норма вектора 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