Comment calculer l'angle d'un vecteur par rapport à la verticale?

j'essaie de trouver l'angle (en degrés) entre deux vecteurs 2D. Je sais que j'ai besoin de trigonométrie, mais je ne suis pas très doué. C'est ce que j'essaie de comprendre (l'axe des Y augmente vers le bas): alt texte http://i38.tinypic.com/2dcefch.png

j'essaie d'utiliser ce code pour le moment, mais il ne fonctionne pas du tout (calcule des angles aléatoires pour une raison quelconque):

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

ce sont mes résultats (il constante quand je fournis une position constante, mais quand je change la position, l'angle change et je ne trouve aucun lien entre les deux angles):

Position 1: x:100 j:100 x1: 50 y1: 50 Angle: 45

Position 2: x: 92 y: 85 x1: 24 y1: 16 Angle: 44,58

Position 3: x: 44 y: 16 x1: 106 y1: 132 Angle: 28.12

Edit: remercie tous ceux qui ont répondu et m'ont aidé à comprendre que c'était mal! Désolé, le titre et le la question a été source de confusion.

10
demandé sur Josh Stodola 2010-08-09 19:51:54

9 réponses

Vous devez d'abord comprendre comment calculer angle entre deux vecteurs et il y en a plusieurs. Je vais vous donner ce que je pense être le plus simple.

  1. étant donné v1 et v2 , leur produit dot est: v1x * v2x + v1y * v2y
  2. la norme d'un vecteur v est donnée par: sqtr(vx^2+vy^2)

avec ce d'informations, veuillez prendre cette définition:

dot(v1, v2) = norm(v1) * norm(v2) * cos(angle(v1, v2))

maintenant, vous résolvez pour angle(v1, v2) :

angle(v1, v2) = acos( dot(v1, v2) / (norm(v1) * norm(v2)) )

enfin, si on prend les définitions données au début, on finit par:

angle(v1, v2) = acos( (v1x * v2x + v1y * v2y) / (sqrt(v1x^2+v1y^2) * sqrt(v2x^2+v2y^2)) )

encore une fois, il y a plusieurs façons de faire ceci, mais j'aime celui-ci parce qu'il est utile pour le produit de point donné angle et norme, ou angle, donné vecteurs.

La réponse sera en radians, mais vous savez que pi radians (c'est-à-dire 3,14 radians) sont de 180 degrés, donc vous multipliez simplement par le facteur de conversion 180/pi.

14
répondu Escualo 2010-08-09 17:47:58

Aha! Il s'avère que j'avais juste besoin de changer d'angle et d'utiliser atan2. C'est mon code final:

private float calcAngle(float x, float y, float x1, float y1)
{
    float _angle = (float)Math.toDegrees(Math.atan2(x1-x, y-y1));
    return _angle;
}

merci à tous de m'avoir aidé à comprendre cela et aussi de m'avoir aidé à comprendre ce que je fais réellement! :)

13
répondu Niall 2010-08-12 08:37:55

ne pas prendre la valeur absolue des arguments à atan2 . Le point entier de atan2 , c'est qu'il utilise les signes de ses arguments de qaudrant l'angle est en. En prenant les valeurs absolues vous forcez atan2 à retourner Seulement les valeurs entre 0 et pi/2 au lieu de-pi à pi.

5
répondu Troubadour 2010-08-09 16:31:15

on dirait que Niall l'a compris, mais je vais finir mon explication, de toute façon. En plus d'expliquer pourquoi la solution fonctionne, ma solution a deux avantages:

  • division potentielle par zéro dans atan2() est évitée
  • la valeur de retour est toujours positive dans l'intervalle 0 à 360 degrés

atan2() renvoie le inverse des aiguilles d'angle par rapport à l'axe X positif. Niall cherchait l'angle dans le sens des aiguilles d'une montre par rapport à l'axe positif Y (entre le vecteur formé par les deux points et l'axe Y positivé).

la fonction suivante est adaptée de mon jeu asteroids où je voulais calculer la direction d'un navire / vecteur vitesse était "pointage: "

// 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;
}
2
répondu Leftium 2010-08-10 00:06:39

je crois que l'équation pour l'angle entre deux vecteurs devrait ressembler plus à:

toDegrees(acos((x*x1+y*y1)/(sqrt(x*x+y*y)*sqrt(x1*x1+y1*y1))))

votre équation ci-dessus calculera l'angle formé entre le vecteur p1-p2 et la ligne obtenue en prolongeant une orthogonale du point p2 au vecteur p1.

le produit dot de deux vecteurs V1 et V2 est égal à |V1|*|V2| cos(theta). Par conséquent, theta est égal à acos((v1 point V2)/(|V1| |V2|)). V1 point V2 est V1.x V2.x+V1.y V2.y. La magnitude de V (i.e., |V|) est le théorème de pathogenorean... (V. x ^ 2 + V. y^2)

1
répondu aepryus 2010-08-09 16:16:55

il devrait être:

atan( abs(x1 - x)/abs(y1 - y) ) 

abs signifie absolu (pour éviter les valeurs négatives)

0
répondu 3rgo 2010-08-09 15:54:12

ma première hypothèse serait de calculer l'angle de chaque vecteur avec les axes en utilisant atan (y / x) et puis soustraire ces anges et prendre la valeur absolue, c'est-à-dire:

abs(atan(y/x) - atan (y1/x1))

0
répondu smichak 2010-08-09 15:59:08

utilisez-vous des nombres entiers? Les arguments sont présentés en double, et j'utiliserais fabs sur le résultat, pas les arguments. Le résultat sera en radians; pour obtenir des degrés, utilisez:

res * = (360.0 / (2.0*Math.PI));

0
répondu Jess 2010-08-09 16:02:10

angle du deuxième vecteur par rapport au premier = atan2(y2,x2) - atan2(y1,x1) .

http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm

0
répondu Mark Cidade 2010-08-09 16:03:07