Primeiro encontre a diferença entre o ponto inicial e o ponto final (aqui, este é mais um segmento de linha direcionado, não uma "linha", pois as linhas se estendem infinitamente e não iniciam em um ponto específico).
deltaY = P2_y - P1_y
deltaX = P2_x - P1_x
Em seguida, calcule o ângulo (que vai do eixo X positivo em P1
ao eixo Y positivo em P1
).
angleInDegrees = arctan(deltaY / deltaX) * 180 / PI
Mas arctan
pode não ser o ideal, porque dividir as diferenças dessa maneira apagará a distinção necessária para distinguir em qual quadrante o ângulo está (veja abaixo). Use o seguinte se o seu idioma incluir uma atan2
função:
angleInDegrees = atan2(deltaY, deltaX) * 180 / PI
EDIT (22 de fevereiro de 2017): No entanto, em geral, ligar atan2(deltaY,deltaX)
apenas para obter o ângulo adequado cos
e sin
pode ser deselegante. Nesses casos, muitas vezes você pode fazer o seguinte:
- Trate
(deltaX, deltaY)
como um vetor.
- Normalize esse vetor para um vetor de unidade. Para fazer isso, divida
deltaX
e deltaY
pelo comprimento do vetor ( sqrt(deltaX*deltaX+deltaY*deltaY)
), a menos que o comprimento seja 0.
- Depois disso,
deltaX
será agora o cosseno do ângulo entre o vetor e o eixo horizontal (na direção do eixo X positivo para o eixo Y positivo em P1
).
- E
deltaY
agora será o seno desse ângulo.
- Se o comprimento do vetor for 0, ele não terá um ângulo entre ele e o eixo horizontal (portanto, não terá um seno e cosseno significativos).
EDIT (28 de fevereiro de 2017): Mesmo sem normalizar (deltaX, deltaY)
:
- O sinal de
deltaX
indica se o cosseno descrito na etapa 3 é positivo ou negativo.
- O sinal de
deltaY
indica se o seno descrito na etapa 4 é positivo ou negativo.
- Os sinais de
deltaX
e deltaY
lhe dirão em que quadrante o ângulo está, em relação ao eixo X positivo em P1
:
+deltaX
, +deltaY
: 0 a 90 graus.
-deltaX
, +deltaY
: 90 a 180 graus.
-deltaX
, -deltaY
: 180 a 270 graus (-180 a -90 graus).
+deltaX
, -deltaY
: 270 a 360 graus (-90 a 0 graus).
Uma implementação em Python usando radianos (fornecida em 19 de julho de 2015 por Eric Leschinski, que editou minha resposta):
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)
Todos os testes são aprovados. Consulte https://en.wikipedia.org/wiki/Unit_circle