math quartz-2d atan2

math - Cómo mapear atan2() a grados 0-360



math.atan2 javascript (13)

atan2 (y, x) tiene esa discontinuidad a 180 ° donde cambia a -180 ° ..0 ° en el sentido de las agujas del reloj.

¿Cómo mapeo el rango de valores a 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 calculando la dirección de un evento táctil al deslizar dado el inicioPoint y el punto final, ambas estructuras de punto XY. El código es para el iPhone, pero cualquier lenguaje que admita atan2f () funcionará.

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

Actualización : Hice la respuesta de Erikkallen en una función con buenos nombres variables largos, así que lo comprenderé dentro de 6 meses. Quizás ayude a algún otro novato de 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; }


Solución usando Modulo

Una solución simple que atrapa todos los casos.

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

Explicación

Positivo: 1 a 180

Si modificas cualquier número positivo entre 1 y 180 por 360, obtendrás el mismo número exacto que pones. La modificación aquí solo asegura que estos números positivos se devuelven con el mismo valor.

Negativo: -180 a -1

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

Casos especiales: 0 y 360

Usar mod significa que se devuelve 0, lo que la convierte en una solución segura de 0-359 grados.


@Jason S: su variante "fmod" no funcionará en una implementación que cumpla con los estándares. El estándar C es explícito y claro (7.12.10.1, "las funciones fmod"):

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

así,

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

en realidad es solo una reescritura detallada de:

atan2(y,x)/M_PI*180

Su tercera sugerencia, sin embargo, es perfecta.


@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 implemente fmod, 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);

Alternativamente, podrías hacer esto:

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

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


Esto es lo que hago normalmente:

float rads = atan2(y, x); if (y < 0) rads = M_PI*2.f + rads; float degrees = rads*180.f/M_PI;


La geosfera de paquetes R calculará bearingRhumb, que es una línea de rumbo constante dado un punto de origen y este / norte. El este y el 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)


O si no le gusta la ramificación, solo niegue los dos parámetros y agregue 180 ° a la respuesta.


Solo agregue 360 ​​° si la respuesta de atan2 es menor que 0 °.


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

1) Abuso atan2 ()

De acuerdo con los documentos atan2 toma los parámetros y y x en ese orden. Sin embargo, si los invierte, puede hacer lo siguiente:

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

2) Use atan2 () correctamente y convierta después

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


Una solución alternativa es usar la función mod () definida como:

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

Luego, con la siguiente función, se obtiene el ángulo entre los puntos ini (x, y) y el final (x, y) . El ángulo se expresa en grados normalizados a [0, 360] grados. y North hace 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); }


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

Editar: Vaya, señal incorrecta.


angle = Math.atan2(x,y)*180/Math.PI;

He hecho una Fórmula para orientar el ángulo de 0 a 360

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


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

Esto devolverá un grado de 0 ° -360 ° en el sentido contrario a las agujas del reloj, 0 ° a las 3 en punto.


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 grado se convierte en (-1 + 360) = 359 grados
-179 grados se convierte en (-179 + 360) = 181 grados