Primero encuentre la diferencia entre el punto inicial y el punto final (aquí, esto es más un segmento de línea dirigida, no una "línea", ya que las líneas se extienden infinitamente y no comienzan en un punto en particular).
deltaY = P2_y - P1_y
deltaX = P2_x - P1_x
Luego calcule el ángulo (que se extiende desde el eje X positivo en P1
el eje Y positivo en P1
).
angleInDegrees = arctan(deltaY / deltaX) * 180 / PI
Pero arctan
puede no ser ideal, porque dividir las diferencias de esta manera borrará la distinción necesaria para distinguir en qué cuadrante se encuentra el ángulo (ver más abajo). Utilice lo siguiente si su idioma incluye una atan2
función:
angleInDegrees = atan2(deltaY, deltaX) * 180 / PI
EDITAR (22 de febrero de 2017): en general, sin embargo, llamar atan2(deltaY,deltaX)
solo para obtener el ángulo adecuado cos
y sin
puede ser poco elegante. En esos casos, a menudo puede hacer lo siguiente:
- Tratar
(deltaX, deltaY)
como un vector.
- Normalice ese vector a un vector unitario. Para hacerlo, divida
deltaX
y deltaY
por la longitud del vector ( sqrt(deltaX*deltaX+deltaY*deltaY)
), a menos que la longitud sea 0.
- Después de eso,
deltaX
ahora será el coseno del ángulo entre el vector y el eje horizontal (en la dirección del eje X positivo al eje Y positivo en P1
).
- Y
deltaY
ahora será el seno de ese ángulo.
- Si la longitud del vector es 0, no tendrá un ángulo entre él y el eje horizontal (por lo que no tendrá un seno y un coseno significativos).
EDITAR (28 de febrero de 2017): incluso sin normalizar (deltaX, deltaY)
:
- El signo de
deltaX
le indicará si el coseno descrito en el paso 3 es positivo o negativo.
- El signo de
deltaY
le indicará si el seno descrito en el paso 4 es positivo o negativo.
- Los signos de
deltaX
y deltaY
le indicarán en qué cuadrante se encuentra el ángulo, en relación con el eje X positivo en P1
:
+deltaX
, +deltaY
: 0 a 90 grados.
-deltaX
, +deltaY
: 90 a 180 grados.
-deltaX
, -deltaY
: 180 a 270 grados (-180 a -90 grados).
+deltaX
, -deltaY
: 270 a 360 grados (-90 a 0 grados).
Una implementación en Python usando radianes (proporcionada el 19 de julio de 2015 por Eric Leschinski, quien editó mi respuesta):
from math import *
def angle_trunc(a):
while a < 0.0:
a += pi * 2
return a
def getAngleBetweenPoints(x_orig, y_orig, x_landmark, y_landmark):
deltaY = y_landmark - y_orig
deltaX = x_landmark - x_orig
return angle_trunc(atan2(deltaY, deltaX))
angle = getAngleBetweenPoints(5, 2, 1,4)
assert angle >= 0, "angle must be >= 0"
angle = getAngleBetweenPoints(1, 1, 2, 1)
assert angle == 0, "expecting angle to be 0"
angle = getAngleBetweenPoints(2, 1, 1, 1)
assert abs(pi - angle) <= 0.01, "expecting angle to be pi, it is: " + str(angle)
angle = getAngleBetweenPoints(2, 1, 2, 3)
assert abs(angle - pi/2) <= 0.01, "expecting angle to be pi/2, it is: " + str(angle)
angle = getAngleBetweenPoints(2, 1, 2, 0)
assert abs(angle - (pi+pi/2)) <= 0.01, "expecting angle to be pi+pi/2, it is: " + str(angle)
angle = getAngleBetweenPoints(1, 1, 2, 2)
assert abs(angle - (pi/4)) <= 0.01, "expecting angle to be pi/4, it is: " + str(angle)
angle = getAngleBetweenPoints(-1, -1, -2, -2)
assert abs(angle - (pi+pi/4)) <= 0.01, "expecting angle to be pi+pi/4, it is: " + str(angle)
angle = getAngleBetweenPoints(-1, -1, -1, 2)
assert abs(angle - (pi/2)) <= 0.01, "expecting angle to be pi/2, it is: " + str(angle)
Todas las pruebas pasan. Ver https://en.wikipedia.org/wiki/Unit_circle