web-dev-qa-db-fra.com

Utiliser atan2 pour trouver un angle entre deux vecteurs

Je comprends que:

atan2(vector.y, vector.x) = angle entre le vecteur et l'axe X .

Mais je voulais savoir comment obtenir l'angle entre deux vecteurs en utilisant atan2. Alors je suis tombé sur cette solution:

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

Ma question est très simple:

Les deux formules suivantes produiront-elles le même nombre?

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

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

Si non: Comment savoir quel vecteur vient en premier dans les soustractions?

Merci

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

est l'angle entre le vecteur de différence (reliant vecteur2 et vecteur1) et l'axe des x,

L’angle (dirigé) du vecteur1 au vecteur2 peut être calculé comme suit:

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

et vous voudrez peut-être le normaliser dans l'intervalle [0, 2 π):

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

ou à la plage (-π, π]:

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

Pour ce faire, recherchez le sinus de l'angle à l'aide du produit croisé et son cosinus à l'aide du produit scalaire, puis combinez les deux avec la fonction Atan2().

En C# c'est 

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
    }
}

Voir cas de test ci-dessus dans GeoGebra.

GeoGebra

33
ja72

Je pense qu'une meilleure formule a été publiée ici: http://www.mathworks.com/matlabcentral/answers/16243-angle-between-two-vectors-in-3d

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

Donc, cette formule fonctionne en 2 ou 3 dimensions . Pour 2 dimensions, cette formule simplifie celle indiquée ci-dessus.

10
Klaus

Personne n'a indiqué que si vous avez un seul vecteur et que vous voulez trouver l'angle du vecteur à partir de l'axe des X, vous pouvez tirer parti du fait que l'argument de atan2 () est en réalité la pente de la ligne, ou Y/delta X). Donc, si vous connaissez la pente, vous pouvez procéder comme suit:

donné:

A = angle du vecteur/ligne que vous souhaitez déterminer (à partir de l’axe X).

m = pente signée du vecteur/ligne.

puis:

A = atan2 (m, 1)

Très utile!

6
sbus

Si vous vous souciez de la précision pour les petits angles, vous voulez utiliser ceci:

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

Où "||" signifie valeur absolue, AKA "longueur du vecteur". Voir https://math.stackexchange.com/questions/1143354/numerically-stable-method-for-angle-between-3d-vectors/1782769

Cependant, cela a l’inconvénient que dans les deux dimensions, il perd le signe de l’angle.

2
D0SBoots

Vous n'avez pas {avez} à utiliser atan2 pour calculer l'angle entre deux vecteurs. Si vous voulez juste le moyen le plus rapide, vous pouvez utiliser dot(v1, v2)=|v1|*|v2|*cos A pour obtenir

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

La formule, angle(vector.b,vector.a), que j'ai envoyée donne des résultats 

dans les quatre quadrants et pour toutes les coordonnées xa,ya et xb,yb.

Pour les coordonnées xa=ya=0 et ou xb=yb=0 est undefined .

L'angle peut être plus grand ou plus petit que pi et peut être positif

ou négatif.

0
theodore panagos

En complément de la réponse de @ martin-r, il convient de noter qu’il est possible d’utiliser la formule somme/différence pour les arcs tangents.

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
  • Attention 1 : assurez-vous que l'angle reste dans -pi ... + pi
  • Attention 2 : Attention, lorsque les vecteurs deviennent très similaires, vous risquez d'obtenir l'extinction au premier argument, ce qui entraîne des imprécisions numériques
0
Ichthyo
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 et xa, ya sont les coordonnées des deux vecteurs

0
theodore panagos