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