Pregunta

atan2 (y, x) tiene que discontinuidad en 180 °, donde se cambia a -180 ° ..0 ° va hacia la derecha.

¿Cómo puedo asignar el rango de valores de 0 ° ..360 °?

Aquí está mi código:

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

Estoy calcular la dirección de un evento de toque deslizar dado el punto inicial y el punto final, ambas estructuras de puntos XY. El código es para el iPhone pero cualquier lenguaje que soporte atan2f () va a hacer.

Gracias por su ayuda chicos, tanto con la solución general y el código.

Actualizar : Hice la respuesta de erikkallen en una función con buenos nombres largos de variable así que comprendo 6 meses a partir de ahora. Tal vez pueda ayudar a otro novato iPhone.

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;
}
¿Fue útil?

Solución

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

Otros consejos

Solución usando Modulo

Una solución simple que capta todos los casos.

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

Explicación

Positivo: 1 a 180

Si MOD cualquier número positivo entre 1 y 180 por 360, obtendrá exactamente el mismo número que pone en Mod. Aquí sólo asegura que estos números positivos se devuelven como el mismo valor.

Negativo: -180 a es -1

Uso mod aquí valores devolverá en el rango de 180 y 359 grados.

casos especiales: 0 y 360

Uso de medios mod que se devuelve 0, haciendo de esta una solución 0-359 grados seguro.

Sólo tiene que añadir 360 ° si la respuesta de atan2 es inferior a 0 °.

O si no te gusta la ramificación, simplemente negar los dos parámetros y añadir 180 ° a la respuesta.

(Adición de 180 ° al valor de retorno pone muy bien en el intervalo de 0-360, pero voltea el ángulo. Negando ambos parámetros de entrada voltea de nuevo.)

@erikkallen está cerca, pero no del todo bien.

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

Esto debería funcionar en C ++: (dependiendo de cómo se implementa HOQF, puede ser más rápido o más lento que la expresión condicional)

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

Si lo prefiere puede hacer esto:

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

desde (x, y) y (-x, -y) difieren en ángulos de 180 grados.

Tengo 2 soluciones que parecen funcionar para todas las combinaciones de x positivos y negativos y.

1) Abuso atan2 ()

Según los docs atan2 toma parámetros Y y X en ese orden. Sin embargo, si los invierte se puede hacer lo siguiente:

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

2) Utilizar atan2 () correctamente y convertir posteriormente

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

@ Jason S: su variante "HOQF" no funcionará en una aplicación compatible con los estándares. El estándar de C es explícita y clara (7.12.10.1, "las funciones FMOD"):

  

si y es distinto de cero, el resultado tiene el mismo signo que x

Por lo tanto,

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

es en realidad sólo una reescritura detallado de:

atan2(y,x)/M_PI*180

Su tercera sugerencia, sin embargo, es en el clavo.

Esto es lo que normalmente hago:

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;

he hecho un Fórmula para orientar ángulo en 0 a 360

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

Una solución alternativa es utilizar el mod función () definido como:

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

A continuación, con la siguiente función, el ángulo entre ini (x, y) y final (x, y) puntos es obtenida. El ángulo se expresa en grados normalizaron a deg [0, 360]. y el Norte de referencia a 360 grados.

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

Los geosphere paquetes de R calculará bearingRhumb, que es una línea de apoyo constante dada de un punto de origen y Este / Norte. El este y norte deben estar en una matriz o vector. El punto de origen de una rosa de los vientos es 0,0. El siguiente código parece resolver fácilmente el 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 ° se convierte en (-1 + 360) = 359 °
-179 ° se convierte en (-179 + 360) = 181 °

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

Esto devolverá grado de 0 ° -360 ° en sentido antihorario, 0 ° es en tres.

Una fórmula para tener el rango de valores de 0 a 360 grados.

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

     -(180/pi())*sign(x*y)*atan((abs(x)-abs(y))/(abs(x)+abs(y)))
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top