web-dev-qa-db-fra.com

Comment mapper atan2 () en degrés 0-360

atan2 (y, x) a cette discontinuité à 180 ° où il bascule à -180 ° ..0 ° en sens horaire.

Comment mapper la plage de valeurs sur 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 balayé en fonction des structures startPoint et endPoint, les deux points XY. Le code est pour l'iPhone, mais toutes les langues qui prennent en charge atan2f () feront l'affaire.

Merci pour votre aide les gars, avec la solution générale et le code.

Mise à jour : J'ai fait de la réponse de erikkallen une fonction avec de beaux noms de variable longs, je vais donc la comprendre dans 6 mois. Peut-être que cela aidera d'autres noob 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;
}
85
willc2
(x > 0 ? x : (2*PI + x)) * 360 / (2*PI)
52
erikkallen

Solution utilisant Modulo

Une solution simple qui intercepte tous les cas.

degrees = (degrees + 360) % 360;  // +360 for implementations where mod returns negative numbers

Explication

Positif: 1 à 180

Si vous modifiez un nombre positif compris entre 1 et 180 sur 360, vous obtiendrez exactement le même nombre que vous avez entré. Mod garantit simplement que ces nombres positifs sont retournés sous la même valeur.

Négatif: -180 à -1

L'utilisation de mod ici renvoie des valeurs comprises entre 180 et 359 degrés.

Cas particuliers: 0 et 360

Utiliser mod signifie que 0 est renvoyé, ce qui en fait une solution sûre de 0 à 359 degrés.

79

Ajoutez simplement 360 ° si la réponse de atan2 est inférieure à 0 °.

34
dave4420

Ou si vous n'aimez pas créer de branches, annulez simplement les deux paramètres et ajoutez 180 ° à la réponse.

30
aib

@erikkallen est proche mais pas tout à fait raison.

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

Cela devrait fonctionner en C++: (selon la manière 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);

Sinon, vous pouvez faire ceci:

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

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

20
Jason S

@Jason S: votre variante "fmod" ne fonctionnera pas avec une implémentation conforme aux normes. 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 parfaite.

6
Stephen Canon

J'ai 2 solutions qui semblent fonctionner pour toutes les combinaisons de x et y positifs et négatifs.

1) Exploiter atan2 ()

Selon la documentation, atan2 prend les paramètres y et x dans cet ordre. Cependant, si vous les inversez, vous pouvez procéder comme suit:

double radians = std::atan2(x, y);
double degrees = radians * 180 / M_PI;
if (radians < 0)
{
    degrees += 360; 
}

2) Utilisez atan2 () correctement et convertissez ensuite

double degrees = std::atan2(y, x) * 180 / M_PI;
if (degrees > 90)
{
    degrees = 450 - degrees;
}
else
{
    degrees = 90 - degrees;
}
6
Fibbles

C'est ce que je fais normalement:

float rads = atan2(y, x);
if (y < 0) rads = M_PI*2.f + rads;
float degrees = rads*180.f/M_PI;
2
andrés
angle = Math.atan2(x,y)*180/Math.PI;

J'ai créé une formule pour orienter l'angle de 0 à 360

angle + Math.ceil( -angle / 360 ) * 360;
1
Saad Ahmed

La géosphère des paquets R calculera bearingRhumb, qui est une ligne de relèvement constante étant donnée un point d'origine et une direction opposée. L'est et le nord doivent être dans une matrice ou un vecteur. Le point d'origine d'une rose des vents est 0,0. Le code suivant semble résoudre facilement le problème:

windE<-wind$uasE
windN<-wind$vasN
wind_matrix<-cbind(windE, windN)
wind$wind_dir<-bearingRhumb(c(0,0), wind_matrix)
wind$wind_dir<-round(wind$wind_dir, 0)
0
Ariane

Une formule pour avoir la plage de valeurs de 0 à 360 degrés.

f(x,y)=180-90*(1+sign(x))* (1-sign(y^2))-45*(2+sign(x))*sign(y)

     -(180/pi())*sign(x*y)*atan((abs(x)-abs(y))/(abs(x)+abs(y)))
0
theodore panagos
double degree = fmodf((atan2(x, y) * (180.0 / M_PI)) + 360, 360);

Cela retournera degré de 0 ° -360 ° dans le sens anti-horaire, 0 ° est à 3 heures.

0
Finallz
theta_rad = Math.Atan2(y,x);
if(theta_rad < 0)
  theta_rad = theta_rad + 2 * Math.PI;    //if neg., add 2 PI to it
theta_deg = (theta_rad/M_PI*180) ;        //convert from radian to degree

//or
theta_rad = Math.Atan2(y,x);
theta_rad = (theta_rad < 0) ? theta_rad + 2 * Math.PI : theta_rad;
theta_deg = (theta_rad/M_PI*180) ;

-1 deg devient (-1 + 360) = 359 deg
- 179 degrés devient (-179 + 360) = 181 degrés

0
PhilC