134 votes

Comment faire correspondre atan2() aux degrés 0-360

atan2(y,x) a cette discontinuité à 180° où il passe à -180°..0° dans le sens des aiguilles d'une montre.

Comment faire correspondre la gamme de valeurs à 0°..360° ?

Voici mon code :

CGSize deltaPoint = CGSizeMake(endPoint.x - startPoint.x, endPoint.y - startPoint.y);
float swipeBearing = atan2f(deltaPoint.height, deltaPoint.width);

Je calcule la direction d'un événement tactile de glissement à partir des points de départ et d'arrivée, tous deux des structures de points XY. Le code est pour l'iPhone mais tout langage qui supporte atan2f() fera l'affaire.

Merci pour votre aide, tant pour la solution générale que pour le code.

Mise à jour : J'ai transformé la réponse d'erikkallen en une fonction avec de jolis noms de variables longs pour que je la comprenne dans 6 mois. Peut-être que cela aidera d'autres novices de l'iPhone.

float PointPairToBearingDegrees(CGPoint startingPoint, CGPoint endingPoint)
{
    CGPoint originPoint = CGPointMake(endingPoint.x - startingPoint.x, endingPoint.y - startingPoint.y); // get origin point to origin by subtracting end from start
    float bearingRadians = atan2f(originPoint.y, originPoint.x); // get bearing in radians
    float bearingDegrees = bearingRadians * (180.0 / M_PI); // convert to degrees
    bearingDegrees = (bearingDegrees > 0.0 ? bearingDegrees : (360.0 + bearingDegrees)); // correct discontinuity
    return bearingDegrees;
}

75voto

erikkallen Points 16601
(x > 0 ? x : (2*PI + x)) * 360 / (2*PI)

Edit : Oops, mauvais signe.

53voto

dave4420 Points 31298

Il suffit d'ajouter 360° si la réponse de atan2 est inférieure à 0°.

44voto

aib Points 18608

Ou si vous n'aimez pas les embranchements, il suffit de nier les deux paramètres et d'ajouter 180° à la réponse.

24voto

Jason S Points 58434

@erikkallen est proche mais pas tout à fait juste.

theta_rad = atan2(y,x);
theta_deg = (theta_rad/M_PI*180) + (theta_rad > 0 ? 0 : 360);

Ceci devrait fonctionner en C++ : (selon la façon dont fmod est implémenté, il peut être plus rapide ou plus lent que l'expression conditionnelle)

theta_deg = fmod(atan2(y,x)/M_PI*180,360);

Vous pouvez aussi faire ceci :

theta_deg = atan2(-y,-x)/M_PI*180 + 180;

puisque les angles de (x,y) et (-x,-y) diffèrent de 180 degrés.

10voto

Stephen Canon Points 58003

@Jason S : votre variante "fmod" ne fonctionnera pas sur une implémentation conforme aux standards. La norme C est explicite et claire (7.12.10.1, "les fonctions fmod") :

si y est non nul, le résultat a le même signe que x

ainsi,

fmod(atan2(y,x)/M_PI*180,360)

est en fait juste une réécriture verbeuse de :

atan2(y,x)/M_PI*180

Votre troisième suggestion, cependant, est tout à fait pertinente.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X