Wie man anzeigen atan2 (), um 0-360 Grad
Frage
atan2(y,x) hat, die Diskontinuität bei 180°, wo es schaltet, um -180°..0° weiter im Uhrzeigersinn.
Wie kann ich anzeigen die Werte auf 0°..360°?
hier ist mein code:
CGSize deltaPoint = CGSizeMake(endPoint.x - startPoint.x, endPoint.y - startPoint.y);
float swipeBearing = atan2f(deltaPoint.height, deltaPoint.width);
Ich bin die Berechnung der Richtung des Swipe-touch-event-angesichts der Startpunkt und Endpunkt, beide XY-Punkt-Strukturen.Der code ist für das iPhone, aber jede Sprache, die unterstützt atan2f() tun.
Vielen Dank für Ihre Hilfe Jungs, sowohl die Allgemeine Lösung und code.
Update:Ich machte erikkallen Antwort in eine Funktion mit schönen langen Variablennamen, so werde ich es verstehen 6 Monate ab jetzt.Vielleicht wird es helfen, einige andere 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;
}
Lösung
(x > 0 ? x : (2*PI + x)) * 360 / (2*PI)
Andere Tipps
Lösung mit Modulo
Eine einfache Lösung, die alle Fälle zu erreichen.
degrees = (degrees + 360) % 360; // +360 for implementations where mod returns negative numbers
Erklärung
Positiv: 1 bis 180
Wenn Sie eine positive Zahl zwischen 1 und 180 mod 360, werden Sie genau die gleiche Nummer, die Sie in setzen bekommen. Mod hier sorgt dafür, nur diese positiven Zahlen werden als der gleiche Wert zurückgegeben.
Negativ: -180 bis -1
mod hier verwenden werden Werte im Bereich von 180 und 359 Grad zurück.
Sonderfälle: 0 und 360
Mit mod bedeutet, dass 0 zurückgegeben wird, das eine sichere 0-359 Grad Lösung.
Fügen Sie einfach um 360 °, wenn die Antwort von atan2 weniger als 0 °.
Oder wenn Sie nicht Verzweigung mögen, nur die beiden Parameter negieren und 180 ° zur Antwort hinzuzufügen.
(Hinzufügen von 180 ° zu dem Rückgabewert setzt es schön im Bereich 0-360, sondern dreht den Winkel. Beiden Eingangsparameter Negieren Flips es zurück.)
@erikkallen ist in der Nähe, aber nicht ganz richtig.
theta_rad = atan2(y,x);
theta_deg = (theta_rad/M_PI*180) + (theta_rad > 0 ? 0 : 360);
Dies sollte in C ++ arbeiten: (je nachdem, wie fmod implementiert ist, kann es schneller oder langsamer als der bedingten Ausdruck sein)
theta_deg = fmod(atan2(y,x)/M_PI*180,360);
Alternativ können Sie dies tun:
theta_deg = atan2(-y,-x)/M_PI*180 + 180;
da (x, y) und (-x, -y) unterscheiden sich im Winkel von 180 Grad.
Ich habe 2 Lösungen, die für alle Kombinationen von positiven und negativen x und y zu funktionieren scheint.
1) Abuse atan2 ()
die Dokumentation Nach atan2 Parametern y und x in dieser Reihenfolge. Allerdings, wenn Sie sie umkehren können Sie wie folgt vor:
double radians = std::atan2(x, y);
double degrees = radians * 180 / M_PI;
if (radians < 0)
{
degrees += 360;
}
2) Verwenden Sie atan2 () korrekt und wandeln danach
double degrees = std::atan2(y, x) * 180 / M_PI;
if (degrees > 90)
{
degrees = 450 - degrees;
}
else
{
degrees = 90 - degrees;
}
@ Jason S: Ihre „fmod“ Variante wird nicht auf eine standardkonforme Umsetzung arbeiten. Der C-Standard ist explizit und klar (7.12.10.1 "die fmod Funktionen"):
, wenn y nicht Null ist, ist das Ergebnis das gleiche Vorzeichen wie x
also
fmod(atan2(y,x)/M_PI*180,360)
ist eigentlich nur eine ausführliche Umschreiben von:
atan2(y,x)/M_PI*180
Ihr dritte Vorschlag ist jedoch vor Ort auf.
Dies ist, was ich normalerweise tun:
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;
Ich habe eine Formel gemacht zum Orientieren Winkels in 0 bis 360
angle + Math.ceil( -angle / 360 ) * 360;
Eine alternative Lösung ist, die verwenden mod () Funktion definiert ist als:
function mod(a, b) {return a - Math.floor (a / b) * b;}
Dann mit der folgenden Funktion der Winkel zwischen ini (x, y) und Ende (x, y) Punkte erhalten wird. Der Winkel wird in Grad ausgedrückt, normalisiert auf [0, 360] °. und Nord Referenzierung 360 °.
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);
}
Die R-Pakete geosphere wird bearingRhumb berechnen, die eine konstante Peillinie einen Ursprungspunkt und easting / northing gegeben ist. Die Rechts- und Hochwert muss in einer Matrix oder Vektor sein. Der Ursprungspunkt für eine Windrose ist 0,0. Der folgende Code scheint leicht das Problem zu beheben:
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 Grad wird (-1 + 360) = 359 °
-179 ° wird (-179 + 360) = 181 °
double degree = fmodf((atan2(x, y) * (180.0 / M_PI)) + 360, 360);
Dies wird Rückgrad von 0 ° -360 ° gegen den Uhrzeigersinn, 0 ° ist bei 3 Uhr.
Eine Formel, um den Wertebereich von 0 bis 360 Grad.
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)))