Java: calcular el ángulo entre dos puntos en grados

5 minutos de lectura

Necesito calcular el ángulo en grados entre dos puntos para mi propia clase Point, el punto a será el punto central.

Método:

public float getAngle(Point target) {
    return (float) Math.toDegrees(Math.atan2(target.x - x, target.y - y));
}

Prueba 1: // devuelve 45

Point a = new Point(0, 0);
    System.out.println(a.getAngle(new Point(1, 1)));

Prueba 2: // devuelve -90, esperado: 270

Point a = new Point(0, 0);
    System.out.println(a.getAngle(new Point(-1, 0)));

¿Cómo puedo convertir el resultado devuelto en un número entre 0 y 359?

  • Acabo de notar que los argumentos atan2 están en el orden inverso: debe ser atan2(y, x)

    – alexm

    2 de abril de 2012 a las 3:01

  • No sé qué sale mal, pero mi pedido funciona bien, el orden inverso no lo haría.

    – Aich

    2 de abril de 2012 a las 3:09

  • Solo puedes medir el ángulo entre tres puntos. podrías asumir (0, 0) o (min(x1,x2), min(y1,y2)) es uno de los puntos pero no se puede dibujar un ángulo entre dos puntos.

    – Peter Lawrey

    2 de abril de 2012 a las 7:16

  • @Peter Lawrey Point a representa el centro. Entonces me refiero al ángulo del punto central y la línea a al nuevo Punto (x, y). ¿O no tiene este sentido?

    – Aich

    2 abr 2012 a las 16:37

  • Entonces te refieres al ángulo entre la línea (0, 0) para (1, 0) y (0,0) para (x, y) ?

    – Peter Lawrey

    2 abr 2012 a las 19:18

avatar de usuario
Juan Ericksen

podrías agregar lo siguiente:

public float getAngle(Point target) {
    float angle = (float) Math.toDegrees(Math.atan2(target.y - y, target.x - x));

    if(angle < 0){
        angle += 360;
    }

    return angle;
}

por cierto, ¿por qué no quieres usar un doble aquí?

  • Dado que el ángulo solo estaría por debajo de 0 por un instante, no veo ninguna razón para usar un bucle while aquí.

    – Makoto

    2 de abril de 2012 a las 2:43

  • Llamo a este método cientos de veces en un marco de juego. Supongo que tengo un poco más de rendimiento con menos precisión y tampoco necesito los dígitos adicionales.

    – Aich

    2 de abril de 2012 a las 2:52

  • Ah, y si estás tratando con estos números en un juego -90 y 270 serán tratados exactamente igual en términos de dirección delta.

    – John Erickson

    2 de abril de 2012 a las 2:56

  • No tienes que comprobar si es >= 360. Esto nunca puede suceder, ya que atan2 devuelve un valor entre +/- pi/2.

    – Dawud ibn Karim

    2 de abril de 2012 a las 3:00

  • @johncarl debería ser tan2(deltay/deltax)

    – mihajlv

    14/09/2013 a las 15:26

Comencé con la solución de johncarls, pero necesitaba ajustarla para obtener exactamente lo que necesitaba. Principalmente, necesitaba que girara en el sentido de las agujas del reloj cuando aumentaba el ángulo. También necesitaba 0 grados para apuntar al NORTE. Su solución me acercó, pero decidí publicar mi solución también en caso de que ayude a alguien más.

He agregado algunos comentarios adicionales para ayudar a explicar mi comprensión de la función en caso de que necesite realizar modificaciones simples.

/** * Calcula el ángulo desde centerPt hasta targetPt en grados.  * La rentabilidad debe oscilar entre [0,360), rotating CLOCKWISE, 
 * 0 and 360 degrees represents NORTH,
 * 90 degrees represents EAST, etc...
 *
 * Assumes all points are in the same coordinate space.  If they are not, 
 * you will need to call SwingUtilities.convertPointToScreen or equivalent 
 * on all arguments before passing them  to this function.
 *
 * @param centerPt   Point we are rotating around.
 * @param targetPt   Point we want to calcuate the angle to.  
 * @return angle in degrees.  This is the angle from centerPt to targetPt.
 */
public static double calcRotationAngleInDegrees(Point centerPt, Point targetPt)
{
    // calculate the angle theta from the deltaY and deltaX values
    // (atan2 returns radians values from [-PI,PI]) // 0 actualmente apunta al ESTE.  // NOTA: Al conservar el orden de los parámetros Y y X en atan2, estamos esperando // una dirección de ángulo en SENTIDO HORARIO.  double theta = Math.atan2(targetPt.y - centerPt.y, targetPt.x - centerPt.x);  // gira el ángulo theta en el sentido de las agujas del reloj 90 grados // (esto hace que el 0 sea el NORTE) // NOTA: al sumar un ángulo, se gira en el sentido de las agujas del reloj.  // restar lo rotaría en sentido antihorario theta += Math.PI/2.0;  // convierte de radianes a grados // esto te dará un ángulo de [0->270],[-180,0]
    ángulo doble = Math.toDegrees(theta);  // convertir a rango positivo [0-360)
    // since we want to prevent negative angles, adjust them now.
    // we can assume that atan2 will not return a negative value
    // greater than one partial rotation
    if (angle < 0) {
        angle += 360;
    }

    return angle;
}

  • Instead of adding Pi/2 (an inexact approximation) to the radian value before converting it to degrees, would make more sense to add 90 after it is converted to degrees.

    – user486646

    Nov 19, 2013 at 5:00

  • Can you do this for radians too? Edit: Never mind – you just remove theMath.toDegrees call.

    – starbeamrainbowlabs

    Dec 29, 2015 at 11:19


  • Here I’d also suggest return (angle + 360) % 360;

    – Joeri

    Apr 29, 2018 at 13:03

user avatar
Stevoisiak

Based on Saad Ahmed’s answer, here is a method that can be used for any two points.

public static double calculateAngle(double x1, double y1, double x2, double y2)
{
    double angle = Math.toDegrees(Math.atan2(x2 - x1, y2 - y1));
    // Keep angle between 0 and 360
    angle = angle + Math.ceil( -angle / 360 ) * 360;

    return angle;
}

  • this is not a generic method

    – FrankK

    Sep 28, 2017 at 13:15

  • @FrankK I’ve removed “generic” as a descriptor

    – Stevoisiak

    Sep 28, 2017 at 13:17

The javadoc for Math.atan(double) is pretty clear that the returning value can range from -pi/2 to pi/2. So you need to compensate for that return value.

user avatar
Death Strike Gaming

Why is everyone complicating this?

The only problem is Math.atan2( x , y)

The corret answer is Math.atan2( y, x)

All they did was mix the variable order for Atan2 causing it to reverse the degree of rotation.

All you had to do was look up the syntax
https://www.google.com/amp/s/www.geeksforgeeks.org/java-lang-math-atan2-java/amp/

user avatar
Saad Ahmed

angle = Math.toDegrees(Math.atan2(target.x - x, target.y - y));

now for orientation of circular values to keep angle between 0 and 359 can be:

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

user avatar
Rudi Kershaw

What about something like :

angle = angle % 360;

  • But.. We do not have te angle!

    – Joehot200

    Dec 2, 2014 at 10:05

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad