web-dev-qa-db-fra.com

Comment calculer un angle à partir de points?

Je veux une solution simple pour calculer l'angle d'une ligne (comme un pointeur d'une horloge).

J'ai 2 points:

cX, cY - the center of the line.
eX, eY - the end of the line.

The result is angle (0 <= a < 360).

Quelle fonction est capable de fournir cette valeur?

37
durumdara

Vous voulez l'arctangent:

dy = ey - cy
dx = ex - cx
theta = arctan(dy/dx)
theta *= 180/pi // rads to degs

Euh, notez que ce qui précède ne compile évidemment pas le code Javascript. Vous devrez parcourir la documentation pour la fonction arctangent .

Edit: Using Math.atan2 (y, x) gérera tous les cas particuliers et la logique supplémentaire pour vous:

function angle(cx, cy, ex, ey) {
  var dy = ey - cy;
  var dx = ex - cx;
  var theta = Math.atan2(dy, dx); // range (-PI, PI]
  theta *= 180 / Math.PI; // rads to degs, range (-180, 180]
  //if (theta < 0) theta = 360 + theta; // range [0, 360)
  return theta;
}
82
Christian Mann

Version exécutable de réponse de Christian .

function angle(cx, cy, ex, ey) {
  var dy = ey - cy;
  var dx = ex - cx;
  var theta = Math.atan2(dy, dx); // range (-PI, PI]
  theta *= 180 / Math.PI; // rads to degs, range (-180, 180]
  return theta;
}
function angle360(cx, cy, ex, ey) {
  var theta = angle(cx, cy, ex, ey); // range (-180, 180]
  if (theta < 0) theta = 360 + theta; // range [0, 360)
  return theta;
}

show("right", 0, 0, 1, 0);
show("top right", 0, 0, 1, 1);
show("top", 0, 0, 0, 1);
show("top left", 0, 0, -1, 1);
show("left", 0, 0, -1, 0);
show("bottom left", 0, 0, -1, -1);
show("bottom", 0, 0, 0, -1);
show("bottom right", 0, 0, 1, -1);

// IGNORE BELOW HERE (all presentational stuff)
table {
  border-collapse: collapse;
}
table, th, td {
  border: 1px solid black;
  padding: 2px 4px;
}
tr > td:not(:first-child) {
  text-align: center;
}
tfoot {
  font-style: italic;
}
<table>
  <thead>
    <tr><th>Direction*</th><th>Start</th><th>End</th><th>Angle</th><th>Angle 360</th></tr>
  </thead>
  <tfoot>
     <tr><td colspan="5">* Cartesian coordinate system<br>positive x pointing right, and positive y pointing up.</td>
  </tfoot>
  <tbody id="angles">
  </tbody>
</table>
<script>
function show(label, cx, cy, ex, ey) {
  var row = "<tr>";
  row += "<td>" + label + "</td>";
  row += "<td>" + [cx, cy] + "</td>";
  row += "<td>" + [ex, ey] + "</td>";
  row += "<td>" + angle(cx, cy, ex, ey) + "</td>";
  row += "<td>" + angle360(cx, cy, ex, ey) + "</td>";
  row += "</tr>";
  document.getElementById("angles").innerHTML += row;
}
</script>

11
TWiStErRob

Si vous utilisez canvas, vous remarquerez (si vous ne l'avez pas déjà fait) que la toile utilise la rotation dans le sens des aiguilles d'une montre.(MDN) et y axe est retourné. Pour obtenir des résultats cohérents, vous devez ajuster votre fonction angle.

De temps en temps, je dois écrire cette fonction et chaque fois, il faut que je la vérifie, parce que je n'arrive jamais au bout du calcul.

Bien que les solutions suggérées fonctionnent, elles ne prennent pas en compte le système de coordonnées de la zone de dessin. Examinez la démo suivante:

Calculer l'angle à partir de points - JSFiddle

function angle(originX, originY, targetX, targetY) {
    var dx = originX - targetX;
    var dy = originY - targetY;

    // var theta = Math.atan2(dy, dx);  // [0, Ⲡ] then [-Ⲡ, 0]; clockwise; 0° = west
    // theta *= 180 / Math.PI;          // [0, 180] then [-180, 0]; clockwise; 0° = west
    // if (theta < 0) theta += 360;     // [0, 360]; clockwise; 0° = west

    // var theta = Math.atan2(-dy, dx); // [0, Ⲡ] then [-Ⲡ, 0]; anticlockwise; 0° = west
    // theta *= 180 / Math.PI;          // [0, 180] then [-180, 0]; anticlockwise; 0° = west
    // if (theta < 0) theta += 360;     // [0, 360]; anticlockwise; 0° = west

    // var theta = Math.atan2(dy, -dx); // [0, Ⲡ] then [-Ⲡ, 0]; anticlockwise; 0° = east
    // theta *= 180 / Math.PI;          // [0, 180] then [-180, 0]; anticlockwise; 0° = east
    // if (theta < 0) theta += 360;     // [0, 360]; anticlockwise; 0° = east

    var theta = Math.atan2(-dy, -dx); // [0, Ⲡ] then [-Ⲡ, 0]; clockwise; 0° = east
    theta *= 180 / Math.PI;           // [0, 180] then [-180, 0]; clockwise; 0° = east
    if (theta < 0) theta += 360;      // [0, 360]; clockwise; 0° = east

    return theta;
}
0
akinuri

Vous trouvez ici deux formules, une d'axe positif x et antihoraire

et un du nord et dans le sens des aiguilles d'une montre.

Il y a x = x2-x1 et y = y2 = y1. Il y a E = E2-E1 et N = N2-N1.

Les formules fonctionnent pour toute valeur de x, y, E et N.

Pour x = y = 0 ou E = N = 0, le résultat est indéfini.

f(x,y)=pi()-pi()/2*(1+sign(x))*(1-sign(y^2))

     -pi()/4*(2+sign(x))*sign(y)

     -sign(x*y)*atan((abs(x)-abs(y))/(abs(x)+abs(y)))

f(E,N)=pi()-pi()/2*(1+sign(N))*(1-sign(E^2))

     -pi()/4*(2+sign(N))*sign(E)

     -sign(E*N)*atan((abs(N)-abs(E))/(abs(N)+abs(E)))
0
theodore panagos

L’un des problèmes pour obtenir l’angle entre deux points ou n’importe quel angle est la référence que vous utilisez.

En mathématiques, nous utilisons un cercle trigonométrique avec l'origine à la droite du cercle (un point dans x = rayon, y = 0) et comptons l'angle dans le sens anti-horaire de 0 à 2PI.

En géographie, l'origine est le nord à 0 degré et nous allons dans le sens des aiguilles d'une montre de 360 ​​degrés.

Le code ci-dessous (en C #) obtient l’angle en radians puis se convertit en un angle géographique:

    public double GetAngle()
    {
        var a = Math.Atan2(YEnd - YStart, XEnd - XStart);
        if (a < 0) a += 2*Math.PI; //angle is now in radians

        a -= (Math.PI/2); //shift by 90deg
        //restore value in range 0-2pi instead of -pi/2-3pi/2
        if (a < 0) a += 2*Math.PI;
        if (a < 0) a += 2*Math.PI;
        a = Math.Abs((Math.PI*2) - a); //invert rotation
        a = a*180/Math.PI; //convert to deg

        return a;
    }
0
pasx