Подтвердить что ты не робот

Использование atan2 для нахождения угла между двумя векторами

Я понимаю, что:

atan2(vector.y, vector.x)= угол между вектором и осью X.

Но я хотел знать, как получить угол между двумя векторами, используя atan2. Поэтому я наткнулся на это решение:

atan2(vector1.y - vector2.y, vector1.x - vector2.x)

Мой вопрос очень прост:

Получают ли две следующие формулы одинаковое число?

  • atan2(vector1.y - vector2.y, vector1.x - vector2.x)

  • atan2(vector2.y - vector1.y, vector2.x - vector1.x)

Если нет: Как я узнаю, какой вектор приходит первым в вычитаниях?

Спасибо

4b9b3361

Ответ 1

 atan2(vector1.y - vector2.y, vector1.x - vector2.x)

это угол между вектором разности (соединяющим vector2 и vector1) и осью x, что, вероятно, не то, что вы имели в виду.

(Направленный) угол от вектора 1 до вектора 2 может быть вычислен как

angle = atan2(vector2.y, vector2.x) - atan2(vector1.y, vector1.x);

и вы можете нормализовать его до диапазона [0, 2 π):

if (angle < 0) { angle += 2 * M_PI; }

или в диапазон (-π, π]:

if (angle > M_PI)        { angle -= 2 * M_PI; }
else if (angle <= -M_PI) { angle += 2 * M_PI; }

Ответ 2

Правильный способ сделать это - найти синус угла с использованием поперечного произведения и косинус угла с использованием точечного произведения и объединить два с функцией Atan2().

В C# это

public struct Vector2
{
    public double X, Y;

    /// <summary>
    /// Returns the angle between two vectos
    /// </summary>
    public static double GetAngle(Vector2 A, Vector2 B)
    {
        // |A·B| = |A| |B| COS(θ)
        // |A×B| = |A| |B| SIN(θ)

        return Math.Atan2(Cross(A,B), Dot(A,B));
    }

    public double Magnitude { get { return Math.Sqrt(Dot(this,this)); } }

    public static double Dot(Vector2 A, Vector2 B)
    {
        return A.X*B.X+A.Y*B.Y;
    }
    public static double Cross(Vector2 A, Vector2 B)
    {
        return A.X*B.Y-A.Y*B.X;
    }
}
class Program
{
    static void Main(string[] args)
    {
        Vector2 A=new Vector2() { X=5.45, Y=1.12};
        Vector2 B=new Vector2() { X=-3.86, Y=4.32 };

        double angle=Vector2.GetAngle(A, B) * 180/Math.PI;
        // angle = 120.16850967865749
    }
}

См. тестовый пример выше в GeoGebra.

GeoGebra

Ответ 3

Я думаю, что лучшая формула была опубликована здесь: http://www.mathworks.com/matlabcentral/answers/16243-angle-between-two-vectors-in-3d

angle = atan2(norm(cross(a,b)), dot(a,b))

Таким образом, эта формула работает в 2 или 3 измерениях. Для двух измерений эта формула упрощается до указанной выше.

Ответ 4

Никто не указал, что если у вас есть один вектор, и вы хотите найти угол вектора от оси X, вы можете воспользоваться тем фактом, что аргумент atan2() на самом деле является наклоном линии, или (дельта Y/delta X). Так что, если вы знаете наклон, вы можете сделать следующее:

дано:

A = угол вектора/линии, которую вы хотите определить (от оси X).

m = знаковый наклон вектора/линии.

затем:

A = atan2 (м, 1)

Очень полезно!

Ответ 5

Если вам нужна точность для небольших углов, вы хотите использовать это:

angle = 2 * atan2 (|| || b || a - || a || b ||, || || b || a + || a || b ||)

Где "||" означает абсолютное значение, AKA "длина вектора". См. https://math.stackexchange.com/questions/1143354/numerically-stable-method-for-angle-between-3d-vectors/1782769

Однако это имеет недостаток, который в двух измерениях теряет знак угла.

Ответ 6

Вам не нужно использовать atan2 для вычисления угла между двумя векторами. Если вы просто хотите самый быстрый способ, вы можете использовать dot(v1, v2)=|v1|*|v2|*cos A получить

A = Math.acos( dot(v1, v2)/(v1.length()*v2.length()) );

Ответ 7

В качестве дополнения к ответу @martin-r следует отметить, что можно использовать формулу суммы/разности для дуговых тангенсов.

angle = atan2(vec2.y, vec2.x) - atan2(vec1.y, vec1.x);
angle = -atan2(vec1.x * vec2.y - vec1.y * vec2.x, dot(vec1, vec2))
        where dot = vec1.x * vec2.x  + vec1.y * vec2.y
  • Caveat 1: убедитесь, что угол остается в пределах -pi... + pi
  • Caveat 2: будьте осторожны, когда векторы становятся очень похожими, вы можете исчезнуть в первом аргументе, что приведет к числовым неточностям

Ответ 8

angle(vector.b,vector.a)=pi/2*((1+sgn(xa))*(1-sgn(ya^2))-(1+sgn(xb))*(1-sgn(yb^2)))

+pi/4*((2+sgn(xa))*sgn(ya)-(2+sgn(xb))*sgn(yb))

+sgn(xa*ya)*atan((abs(xa)-abs(ya))/(abs(xa)+abs(ya)))

-sgn(xb*yb)*atan((abs(xb)-abs(yb))/(abs(xb)+abs(yb)))

xb, yb и xa, ya - координаты двух векторов

Ответ 9

Формула angle(vector.b,vector.a), которую я отправил, даст результаты

в четырех квадрантах и для любых координат xa,ya и xb,yb.

Для координат xa=ya=0 и или xb=yb=0 не определено.

Угол может быть больше или меньше, чем pi, и может быть положительным

или отрицательный.