durumdara
Quiero obtener una solución simple para calcular el ángulo de una línea (como el puntero de un reloj).
tengo 2 puntos:
cX, cY - the center of the line.
eX, eY - the end of the line.
The result is angle (0 <= a < 360).
¿Qué función es capaz de proporcionar este valor?
cristiano mann
Quieres el arcotangente:
dy = ey - cy
dx = ex - cx
theta = arctan(dy/dx)
theta *= 180/pi // rads to degs
Erm, tenga en cuenta que lo anterior obviamente no compila el código Javascript. Tendrás que mirar a través de la documentación para el arcotangente función.
Editar: Usando Matemáticas.atan2(y,x) manejará todos los casos especiales y la lógica adicional por usted:
función ángulo(cx, cy, ex, ey) { var dy = ey - cy; var dx = ex - cx; var theta = Math.atan2(dy, dx); // rango (-PI, PI]theta *= 180 / Math.PI; // rads a grados, rango (-180, 180]//si (theta
-
Note that to avoid division by 0, you should test if
dx == 0
first; if it is, then return 90 degrees ifdy > 0
and 270 degrees ifdy < 0
.– Etienne PerotMar 8, 2012 at 7:20
-
@EtiennePerot: I remembered another useful function and updated my answer to use that instead.
– Christian MannMar 8, 2012 at 7:24
-
You may also want to convert the result to degrees, it sounds like that's what the OP wants.
– Etienne PerotMar 8, 2012 at 7:26
-
Almost, there is a little error in it:
theta*=180/Math.PI
is correct. You also don't need to worry about zero division, when usingatan2()
, it returns correct value with0
too.– TeemuMar 8, 2012 at 7:36
-
Added (optional) code to flip it to 360 range as the question asked.
– TWiStErRobJun 30, 2015 at 11:12
TWiStErRob
Runnable version of Christian's answer.
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 a grados, range (-180, 180]return theta; } function angle360(cx, cy, ex, ey) { var theta = angle(cx, cy, ex, ey); // range (-180, 180]si (theta
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] + ""; fila += "" + [ex, ey] + " "; fila += "" + ángulo(cx, cy, ex, ey) + " "; fila += "" + ángulo360(cx, cy, ex, ey) + " "; fila += ""; document.getElementById("ángulos").innerHTML += fila; }
Si está utilizando lienzo, notará (si aún no lo ha hecho) que el lienzo usa la rotación en el sentido de las agujas del reloj(MDN) y y
se invierte el eje. Para obtener resultados consistentes, necesita ajustar su angle
función.
De vez en cuando, necesito escribir esta función y cada vez necesito buscarla, porque nunca llego al final del cálculo.
Si bien las soluciones sugeridas funcionan, no tienen en cuenta el sistema de coordenadas del lienzo. Examine la siguiente demostración:
Calcular ángulo a partir de puntos - 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;
}
-
¿Qué significa cuando tengo que sumar 90 grados a la respuesta para obtener la rotación correcta?
– 1,21 gigavatios
15 de agosto de 2019 a las 21:37
-
Además, ¿cuáles son los nombres de los sistemas de coordenadas? Movimiento de coordenadas cartesianas hacia la derecha y hacia arriba en.wikipedia.org/wiki/Cartesian_coordinates. ¿Cómo se llama cuando los valores positivos se mueven hacia la derecha y hacia abajo?
– 1,21 gigavatios
15 de agosto de 2019 a las 21:41
-
@ 1,21 gigavatios ¿Me estás citando con "hay que sumar 90 grados a la respuesta para obtener la rotación correcta" (porque no dije tal cosa) ¿o es otra cosa y estás tratando de encontrarle sentido? Hmm, no estoy seguro si tiene un nombre. La única diferencia entre los dos es la dirección de la rotación. Canvas también utiliza el sistema de coordenadas cartesianas. Es solo en el sentido de las agujas del reloj en lugar de en el sentido contrario a las agujas del reloj. Examine la sección "Cuadrantes y octantes" en la página que vinculó. voltear el
y
eje, eso es cambiarI
yII
cuadrantes conIV
yIII
, respectivamente. Ahora, es en el sentido de las agujas del reloj.– akinuri
16 de agosto de 2019 a las 7:25
-
Estoy tratando de entender por qué agregar 90 grados al resultado funciona para mi caso. Acabo de notar en la respuesta de @pasx que tiene un comentario.
a -= (Math.PI/2); //shift by 90deg
y he visto mención de 90 grados en otros lugares.– 1,21 gigavatios
16 de agosto de 2019 a las 14:33
-
@ 1,21 gigavatios, lo mismo. Desviación de 90°.
–Jeff Fischer
24 de septiembre de 2020 a las 17:34
Uno de los problemas para obtener el ángulo entre dos puntos o cualquier ángulo es la referencia que usa.
En matemáticas usamos un círculo trigonométrico con el origen a la derecha del círculo (un punto en x=radio, y=0) y contamos el ángulo en sentido antihorario de 0 a 2PI.
En geografía el origen es el Norte a 0 grados y vamos en el sentido de las agujas del reloj desde a 360 grados.
El siguiente código (en C#) obtiene el ángulo en radianes y luego lo convierte en un ángulo geográfico:
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;
}
Aquí encuentras dos fórmulas, una desde el eje x positivo y en sentido contrario a las agujas del reloj
y uno desde el norte y en el sentido de las agujas del reloj.
Hay x=x2-x1 y y=y2=y1. Hay E=E2-E1 y N=N2-N1.
Las fórmulas funcionan para cualquier valor de x, y, E y N.
Para x=y=0 o E=N=0 el resultado no está definido.
f(x,y)=pi()-pi()/2*(1+signo(x))*(1-signo(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+signo(N))*(1-signo(E^2))
-pi()/4*(2+sign(N))*sign(E)
-sign(E*N)*atan((abs(N)-abs(E))/(abs(N)+abs(E)))
Necesitas al menos tres puntos para calcular un ángulo. ¿Cuál es tu 3ro? ¿El eje x o el eje y?
– Sirko
8 de marzo de 2012 a las 7:19
Ver también: Misma pregunta para Python
– Martín Tomas
20 de junio de 2020 a las 17:34