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;
}
War es hilfreich?

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)))
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top