Trouvez d'abord la différence entre le point de départ et le point d'arrivée (ici, il s'agit plus d'un segment de ligne dirigé, pas d'une "ligne", car les lignes s'étendent à l'infini et ne commencent pas à un point particulier).
deltaY = P2_y - P1_y
deltaX = P2_x - P1_x
Calculez ensuite l'angle (qui va de l'axe X positif à P1
à l'axe Y positif à P1
).
angleInDegrees = arctan(deltaY / deltaX) * 180 / PI
Mais arctan
peut ne pas être idéal, car la division des différences de cette façon effacera la distinction nécessaire pour distinguer dans quel quadrant l'angle se trouve (voir ci-dessous). Utilisez plutôt ce qui suit si votre langue comprend une atan2
fonction:
angleInDegrees = atan2(deltaY, deltaX) * 180 / PI
EDIT (22 février 2017): En général, cependant, appeler atan2(deltaY,deltaX)
juste pour obtenir l'angle approprié cos
et sin
peut être inélégant. Dans ces cas, vous pouvez souvent effectuer les opérations suivantes à la place:
- Traitez-le
(deltaX, deltaY)
comme un vecteur.
- Normalisez ce vecteur en un vecteur unitaire. Pour ce faire, divisez
deltaX
et deltaY
par la longueur du vecteur ( sqrt(deltaX*deltaX+deltaY*deltaY)
), sauf si la longueur est 0.
- Après cela,
deltaX
sera maintenant le cosinus de l'angle entre le vecteur et l'axe horizontal (dans la direction du X positif vers l'axe Y positif en P1
).
- Et
deltaY
sera maintenant le sinus de cet angle.
- Si la longueur du vecteur est 0, il n'aura pas d'angle entre lui et l'axe horizontal (il n'aura donc pas de sinus et cosinus significatif).
EDIT (28 février 2017): Même sans normalisation (deltaX, deltaY)
:
- Le signe de
deltaX
vous indiquera si le cosinus décrit à l'étape 3 est positif ou négatif.
- Le signe de
deltaY
vous indiquera si le sinus décrit à l'étape 4 est positif ou négatif.
- Les signes
deltaX
et deltaY
vous indiqueront dans quel quadrant l'angle se trouve, par rapport à l'axe X positif à P1
:
+deltaX
, +deltaY
: 0 à 90 degrés.
-deltaX
, +deltaY
: 90 à 180 degrés.
-deltaX
, -deltaY
: 180 à 270 degrés (-180 à -90 degrés).
+deltaX
, -deltaY
: 270 à 360 degrés (-90 à 0 degrés).
Une implémentation en Python utilisant des radians (fournie le 19 juillet 2015 par Eric Leschinski, qui a édité ma réponse):
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)
Tous les tests réussissent. Voir https://en.wikipedia.org/wiki/Unit_circle