Domanda

atan2(y,x), ha la discontinuità a 180° dove si passa a -180°..0° in senso orario.

Come faccio a mappare la gamma di valori da 0°..a 360°?

ecco il mio codice:

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

Io sono il calcolo della direzione di una strisciata eventi di tocco dato il punto di partenza e di endPoint, sia punto XY strutture.Il codice è per l'iPhone, ma qualsiasi linguaggio che supporti atan2f() fa.

Grazie per il vostro aiuto ragazzi, sia con la soluzione generale e del codice.

Aggiornamento:Ho fatto erikkallen risposta in una funzione con una lunga e piacevole nomi di variabili, quindi non posso comprendere a 6 mesi da ora.Forse aiuterà alcuni altri 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;
}
È stato utile?

Soluzione

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

Altri suggerimenti

Soluzione utilizzando il Modulo

Una soluzione semplice che cattura tutti i casi.

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

Spiegazione

Positivo:1 a 180

Se hai mod di qualsiasi numero positivo compreso tra 1 e 180 da 360, si ottiene esattamente lo stesso numero si mette.Mod qui solo assicura che questi numeri positivi sono tornato lo stesso valore.

Negativo:-180 -1

Utilizzando il mod qui restituirà valori nell'intervallo di 180 359 gradi.

Casi particolari:0 e 360

Utilizzando il mod significa che il valore restituito è 0, facendo di questo una cassetta di sicurezza 0 e 359 gradi soluzione.

Basta aggiungere a 360° se la risposta da atan2 è inferiore a 0°.

O se non vi piace ramificazione, basta negare i due parametri e aggiungere 180 ° per la risposta.

(Aggiunta di 180 ° per il valore restituito mette bene nell'intervallo 0-360, ma gira l'angolo. Negazione di entrambi i parametri di ingresso ribalta indietro.)

@erikkallen è vicino ma non abbastanza di destra.

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

Questo dovrebbe funzionare in C ++: (a seconda di come viene implementato fmod, può essere più veloce o più lento rispetto l'espressione condizionale)

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

In alternativa si potrebbe fare questo:

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

dal (x, y) e (-x, -y) differiscono in angoli di 180 gradi.

Ho 2 soluzioni che sembrano funzionare per tutte le combinazioni di x positivi e negativi e a.

1) Abuso atan2 ()

Secondo la documentazione atan2 prende parametri X e Y in questo ordine. Tuttavia se si inverte è possibile effettuare le seguenti operazioni:

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

2) Usare atan2 () in modo corretto e convertire successivamente

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

@ Jason S: la vostra variante "fmod" non funzionerà su un'implementazione conforme agli standard. Lo standard C è esplicito e chiaro (7.12.10.1, "le funzioni FMOD"):

  

se y è diverso da zero, il risultato è lo stesso segno di x

quindi,

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

è in realtà solo una riscrittura verbose di:

atan2(y,x)/M_PI*180

Il terzo suggerimento, tuttavia, è a posto.

Questo è quello che faccio normalmente:

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;

Ho fatto una formula per orientare inclinata all'interno 0 ° a 360

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

Una soluzione alternativa è quella di utilizzare il mod function () definito come:

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

Poi, con la seguente funzione, l'angolo tra ini (x, y) e estremità (x, y) punti si ottiene. L'angolo è espresso in gradi normalizzati su [0, 360] gradi. e Nord riferimento 360 gradi.

    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);
    }

I pacchetti R geosphere calcolerà bearingRhumb, che è una linea di rilevamento costante in un punto di origine e Est / Nord. Coordinate est e nord devono essere in una matrice o vettoriale. Il punto di origine di una rosa dei venti è 0,0. Il seguente codice sembra per risolvere prontamente il problema:

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 ° diventa (-1 + 360) = 359 °
-179 gradi diventa (-179 + 360) = 181 deg

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

Ciò restituirà grado da 0 ° -360 ° in senso antiorario, 0 ° è a ore 3.

Una formula per tutta la gamma di valori da 0 a 360 gradi.

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

     -(180/pi())*sign(x*y)*atan((abs(x)-abs(y))/(abs(x)+abs(y)))
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top