Question

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

Comment mapper la plage 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 calculer la direction d'un événement tactile étant donné la startPoint balayant et endPoint, les deux struct point XY. Le code est pour l'iPhone, mais une langue qui prend en charge atan2f () le fera.

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

Mise à jour : J'ai fait la réponse de erikkallen en fonction des noms de variables belles longues donc je le comprends 6 mois à partir de maintenant. Peut-être que cela aidera d'autres iPhone Noob.

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;
}
Était-ce utile?

La solution

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

Autres conseils

Solution en utilisant Modulo

Une solution simple qui attire tous les cas.

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

Explication

Positif: 1-180

Si vous mod un nombre positif entre 1 et 180 par 360, vous obtiendrez le même nombre que vous mettez dans. Mod ici assure que ces chiffres positifs sont renvoyés sous la même valeur.

négatif: -180 à -1

Utilisation de mod ici renvoie les valeurs dans la gamme de 180 et 359 degrés.

Cas particuliers: 0 et 360

En utilisant des moyens mod que 0 est renvoyé, ce qui en fait une solution 0-359 degrés sûre.

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

Ou si vous ne l'aimez pas ramification, nier que les deux paramètres et ajouter 180 ° à la réponse.

(Ajout de 180 ° par rapport à la valeur de retour met bien dans la plage de 0 à 360, mais retourne l'angle. Nier les deux paramètres d'entrée retourne en arrière.)

@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 façon dont fmod est mis en œuvre, il peut être plus rapide ou plus lent que l'expression conditionnelle)

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

vous pourriez aussi faire ceci:

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

puisque (x, y) et (-x, -y) sont différentes dans des angles de 180 degrés.

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

1) atan2 Abuse ()

Selon la documentation atan2 prend des paramètres y et x dans cet ordre. Toutefois, si vous les renversez, vous pouvez faire ce qui suit:

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

2) Utilisez correctement et convertir ensuite atan2 ()

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

S @ Jason: votre variante « de fmod » ne fonctionnera pas sur une mise en œuvre 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 de bavard:

atan2(y,x)/M_PI*180

Votre troisième suggestion, cependant, est sur place.

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;
angle = Math.atan2(x,y)*180/Math.PI;

I ai fait une formule d'orientation en angle 0 à 360

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

Une solution alternative consiste à utiliser la fonction mod () défini comme suit:

function mod(a, b) {return a - Math.floor (a / b) * b;}

Ensuite, avec la fonction suivante, l'angle entre ini (x, y) et extrémité (x, y) points est obtenue. L'angle est exprimé en degrés normalisés à [0, 360] deg. et le référencement du Nord 360 deg.

    function angleInDegrees(ini, end) {
        var radian = Math.atan2((end.y - ini.y), (end.x - ini.x));//radian [-PI,PI]
        return mod(radian * 180 / Math.PI + 90, 360);
    }

Les paquets de R geosphere calculent bearingRhumb, qui est une ligne d'appui constant donné un point d'origine et une abscisse / ordonnée. Le azimutes Ordonnée doit être dans une matrice ou d'un vecteur. Le point d'origine pour une rose des vents est 0,0. Le code suivant semble résoudre facilement la question:

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)
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 °
-179 deg devient (-179 + 360) = 181 deg

double degree = fmodf((atan2(x, y) * (180.0 / M_PI)) + 360, 360);

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

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)))
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top