web-dev-qa-db-fra.com

Java: Calculer l'angle entre deux points en degrés

Je dois calculer l'angle en degrés entre deux points pour ma propre classe de points. Le point a doit être le point central.

Méthode:

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

Test 1: // retourne 45

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

Test 2: // renvoie -90, attendu: 270

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

Comment puis-je convertir le résultat renvoyé en un nombre compris entre 0 et 359?

44
Aich

vous pouvez ajouter ce qui suit:

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

au fait, pourquoi ne voulez-vous pas utiliser un double ici?

74
John Ericksen

J'ai commencé avec la solution johncarls, mais il fallait l'adapter pour obtenir exactement ce dont j'avais besoin. J'avais surtout besoin de le faire tourner dans le sens des aiguilles d'une montre lorsque l'angle augmentait. J'avais également besoin de 0 degrés pour pointer NORTH. Sa solution m'a rapproché, mais j'ai décidé d'afficher ma solution au cas où cela aiderait quelqu'un d'autre.

J'ai ajouté quelques commentaires supplémentaires pour expliquer ma compréhension de la fonction au cas où vous auriez besoin d'apporter de simples modifications.

/**
 * Calculates the angle from centerPt to targetPt in degrees.
 * The return should range from [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 currently points EAST.  
    // NOTE: By preserving Y and X param order to atan2,  we are expecting 
    // a CLOCKWISE angle direction.  
    double theta = Math.atan2(targetPt.y - centerPt.y, targetPt.x - centerPt.x);

    // rotate the theta angle clockwise by 90 degrees 
    // (this makes 0 point NORTH)
    // NOTE: adding to an angle rotates it clockwise.  
    // subtracting would rotate it counter-clockwise
    theta += Math.PI/2.0;

    // convert from radians to degrees
    // this will give you an angle from [0->270],[-180,0]
    double angle = Math.toDegrees(theta);

    // convert to positive range [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;
}
29
Joseph Snow

Basé sur réponse de Saad Ahmed , voici une méthode qui peut être utilisée pour deux points quelconques.

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;
}
2
angle = Math.toDegrees(Math.atan2(target.x - x, target.y - y));

maintenant pour l'orientation des valeurs circulaires pour garder un angle entre 0 et 359 peut être:

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

Le javadoc pour Math.atan (double) indique assez clairement que la valeur renvoyée peut aller de -pi/2 à pi/2. Vous devez donc compenser cette valeur de retour.

1
Spencer Kormos