So ordnen Sie atan2 () den Graden 0-360 zu

108

atan2(y, x) hat diese Diskontinuität bei 180 °, wo sie im Uhrzeigersinn auf -180 ° ..0 ° umschaltet.

Wie ordne ich den Wertebereich 0 ° ..360 ° zu?

Hier ist mein Code:

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

Ich Berechnung der Richtung eines streichBerührungsEreignis angesichts der startPointund endPointbeide XY Punkt structs. Der Code ist für das iPhone, aber jede Sprache, die atan2f()dies unterstützt , reicht aus.

willc2
quelle
Hinweis: Die veröffentlichte Aktualisierungsmethode gibt keine Nullgrade zurück, sondern Werte von knapp über 0 bis 360,0.
chux
2
> [Wie man Winkel von 2 Positionen erhält
MAnoj Sarnaik
Diese Funktion funktioniert hervorragend, jedoch wird der Winkel der Berechnung der "Lagergrade" umgedreht. Zum Beispiel würden 45 Grad typischerweise durch den 1. Quadranten, jedoch dies im 4. Quadranten. 135 Grad befinden sich normalerweise im 2. Quadranten, aber diese Funktion gibt zurück, dass sie sich im 3. Quadranten befinden. Ich kann einfach den Funktionsrückgabewert x nehmen und diesen von 360 negieren, um den richtigen Winkelwert zu erhalten. Ich bin jedoch gespannt, warum dies überhaupt geschieht.
Goelv

Antworten:

66
(x > 0 ? x : (2*PI + x)) * 360 / (2*PI)
erikkallen
quelle
6
Möchte wahrscheinlich auch x> = 0 für den Fall x = 0.
bpw1621
13
Für diejenigen, die mit dieser Notation nicht vertraut sind und keine Umrechnung in eingebaute Grade vornehmen: if (x> 0) {radians = x;} else {radians = 2 * PI + x;}, also addieren wir nur 2PI zum Ergebnis if es ist weniger als 0.
David Doria
1
Oder (x >= 0 ? x : (2*PI + x)) * 180/PIwie in(x < 0 ? 2*PI + x : x) * 180/PI
user3342816
97

Lösung mit Modulo

Eine einfache Lösung, die alle Fälle erfasst.

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

Erläuterung

Positiv: 1 bis 180

Wenn Sie eine positive Zahl zwischen 1 und 180 mal 360 modifizieren, erhalten Sie genau die gleiche Zahl, die Sie eingegeben haben. Mod hier stellt nur sicher, dass diese positiven Zahlen als der gleiche Wert zurückgegeben werden.

Negativ: -180 bis -1

Wenn Sie hier mod verwenden, werden Werte im Bereich von 180 bis 359 Grad zurückgegeben.

Sonderfälle: 0 und 360

Die Verwendung von mod bedeutet, dass 0 zurückgegeben wird, was dies zu einer sicheren Lösung von 0-359 Grad macht.

Liam George Betsworth
quelle
3
tolle Lösungen :)
Qadir Hussain
5
Ich glaube nicht, dass es notwendig ist, 360 hinzuzufügen. -1% 360 ist immer noch 359 :)
Pleasemorebacon
11
Ich denke nicht, dass dies in allen Sprachen richtig ist. In Javascript-1 % 360 = -1
Startec
Auch kein praktikabler Ansatz in Java
Hulk
1
@pleasemorebacon Falsch. In einigen Sprachen ist -1% 360 -1.
Pharap
40

Fügen Sie einfach 360 ° hinzu, wenn die Antwort von atan2 weniger als 0 ° beträgt.

dave4420
quelle
6
Das ist das gleiche wie "nur 2 * PI hinzufügen", wenn Sie einen dieser Tage haben.
Chris O
33

Oder wenn Sie keine Verzweigung mögen, negieren Sie einfach die beiden Parameter und fügen Sie der Antwort 180 ° hinzu.

(Wenn Sie dem Rückgabewert 180 ° hinzufügen, liegt er gut im Bereich von 0 bis 360, dreht aber den Winkel um. Wenn Sie beide Eingabeparameter negieren, wird er zurückgedreht.)

aib
quelle
2
Danke, das ist genau das, wonach ich gesucht habe.
Jeremy Herrman
2
Ich würde meinen Code lieber ändern, um denormalisierte Winkel (<0,> = 360) zu verwenden, aber es scheint immer jemanden zu geben, der auf dieses falsche "optimierte" Gefühl abzielt. deshalb wollte ich das hinzufügen. (Oder lag es daran, dass dies der schnellere Weg war, um einen von mir verwendeten temporären Debug-Code zu umgehen? Hmm)
aib
1
Auf jeden Fall nicht einfach zu groken, da ich nach 2+ Jahren zustimmen kann. Also: Wenn Sie dem Rückgabewert 180 ° hinzufügen, liegt er gut im Bereich von 0 bis 360, dreht aber den Winkel um. Wenn Sie beide Eingabeparameter negieren, wird es zurückgeschaltet.
Aib
Dies kann einige Probleme haben, wenn $ x = 0 $ und $ y> 0 $ iirc
Trinidad
22

@erikkallen ist nah 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 ++ funktionieren: (Je nachdem, wie fmod implementiert ist, kann es schneller oder langsamer sein als der bedingte Ausdruck)

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) sich in den Winkeln um 180 Grad unterscheiden.

Jason S.
quelle
Wenn ich Sie in Fortran richtig verstanden habe, ist es atan2 (-y, -x) * 180 / PI + 180. Ist das richtig?
Gansub
Entschuldigung, ich kenne FORTRAN nicht. Aber deine Mathematik sieht richtig aus.
Jason S
11

Ich habe 2 Lösungen, die für alle Kombinationen von positivem und negativem x und y zu funktionieren scheinen.

1) Missbrauch atan2 ()

Gemäß den Dokumenten nimmt atan2 die Parameter y und x in dieser Reihenfolge. Wenn Sie sie jedoch umkehren, können Sie Folgendes tun:

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

2) Verwenden Sie atan2 () korrekt und konvertieren Sie anschließend

double degrees = std::atan2(y, x) * 180 / M_PI;
if (degrees > 90)
{
    degrees = 450 - degrees;
}
else
{
    degrees = 90 - degrees;
}
Fibbles
quelle
Sie, mein Herr, sind ein Lebensretter. Habe gerade diesen Ansatz in Unity verwendet und funktioniert wie ein Zauber.
Porfiriopartida
7

@Jason S: Ihre "fmod" -Variante funktioniert bei einer standardkonformen Implementierung nicht. Der C-Standard ist explizit und klar (7.12.10.1, "die fmod-Funktionen"):

Wenn y ungleich Null ist, hat das Ergebnis das gleiche Vorzeichen wie x

so,

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

ist eigentlich nur eine ausführliche Umschreibung von:

atan2(y,x)/M_PI*180

Ihr dritter Vorschlag ist jedoch genau richtig.

Stephen Canon
quelle
5

Das mache ich normalerweise:

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

Ich habe eine Formel zum Ausrichten des Winkels in 0 bis 360 erstellt

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

Eine alternative Lösung besteht darin, die Funktion mod () zu verwenden, die wie folgt definiert ist:

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

Dann wird mit der folgenden Funktion der Winkel zwischen den Punkten ini (x, y) und end (x, y) erhalten. Der Winkel wird in Grad ausgedrückt, die auf [0, 360] Grad normiert sind. und Nord mit 360 Grad.

    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);
    }
A. Torrez Garay
quelle
1

Die Geosphäre des R-Pakets berechnet die PeilungRumb, eine konstante Peilungslinie bei gegebenem Ursprungspunkt und Ost / Nord. Die Ost- und Nordrichtung muss in einer Matrix oder einem Vektor liegen. Der Ursprungspunkt für eine Windrose ist 0,0. Der folgende Code scheint das Problem leicht 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)
Ariane
quelle
1
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 ° wird (-1 + 360) = 359 °
-179 ° wird (-179 + 360) = 181 °

PhilC
quelle
Was ist Math.PI? Ist es das gleiche wie M_PI?
Pang
1
double degree = fmodf((atan2(x, y) * (180.0 / M_PI)) + 360, 360);

Dies gibt den Grad von 0 ° -360 ° gegen den Uhrzeigersinn zurück, 0 ° ist um 3 Uhr.

Finallz
quelle
1

Eine Formel für den Wertebereich von 0 bis 360 Grad.

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

     -(180/pi())*sign(x*y)*atan((abs(x)-abs(y))/(abs(x)+abs(y)))
Theodore Panagos
quelle
Können Sie bitte erklären, wie dies mit der Frage zusammenhängt?
Klaus Gütter
1

Hier ist etwas Javascript. Geben Sie einfach x- und y-Werte ein.

var angle = (Math.atan2(x,y) * (180/Math.PI) + 360) % 360;
Squarcle
quelle