Najpierw znajdź różnicę między punktem początkowym i końcowym (tutaj jest to bardziej ukierunkowany odcinek linii, a nie „linia”, ponieważ linie rozciągają się nieskończenie i nie zaczynają w określonym punkcie).
deltaY = P2_y - P1_y
deltaX = P2_x - P1_x
Następnie obliczyć kąt (który biegnie od dodatniej osi X P1
do dodatniej osi Y w P1
).
angleInDegrees = arctan(deltaY / deltaX) * 180 / PI
Ale arctan
może nie być idealny, ponieważ podzielenie różnic w ten sposób usunie rozróżnienie potrzebne do rozróżnienia, w której kwadrancie znajduje się kąt (patrz poniżej). Zamiast tego zastosuj następujące informacje, jeśli Twój język zawiera atan2
funkcję:
angleInDegrees = atan2(deltaY, deltaX) * 180 / PI
EDIT (22 lutego 2017): Na ogół jednak, nazywając atan2(deltaY,deltaX)
tak aby uzyskać odpowiedni kąt dla cos
i sin
może być nieeleganckie. W takich przypadkach często można zamiast tego wykonać następujące czynności:
- Traktuj
(deltaX, deltaY)
jak wektor.
- Znormalizuj ten wektor do wektora jednostkowego. Aby to zrobić, podziel
deltaX
i deltaY
przez długość wektora ( sqrt(deltaX*deltaX+deltaY*deltaY)
), chyba że długość wynosi 0.
- Następnie
deltaX
będzie cosinus kąta między wektorem a osią poziomą (w kierunku od dodatniego X do dodatniej osi Y w P1
).
- I
deltaY
będzie teraz sinus tego kąta.
- Jeśli wektor ma długość 0, nie będzie miał kąta między nim a osią poziomą (więc nie będzie miał sensownego sinusa i cosinusa).
EDYCJA (28 lutego 2017 r.): Nawet bez normalizacji (deltaX, deltaY)
:
- Znak
deltaX
wskazuje, czy cosinus opisany w kroku 3 jest dodatni czy ujemny.
- Znak
deltaY
wskazuje, czy sinus opisany w kroku 4 jest dodatni czy ujemny.
- Znaki
deltaX
i deltaY
powiedzą, w której kwadrancie znajduje się kąt, w stosunku do dodatniej osi X w P1
:
+deltaX
, +deltaY
: Od 0 do 90 stopni.
-deltaX
, +deltaY
: Od 90 do 180 stopni.
-deltaX
, -deltaY
: 180 do 270 stopni (-180 do -90 stopni).
+deltaX
, -deltaY
: 270 do 360 stopni (od -90 do 0 stopni).
Implementacja w Pythonie przy użyciu radianów (dostarczona 19 lipca 2015 r. Przez Erica Leschinskiego, który zredagował moją odpowiedź):
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)
Wszystkie testy przeszły pomyślnie. Zobacz https://en.wikipedia.org/wiki/Unit_circle