Bir programlama dilinde (Python, C#, vb.) bir çizgi ile yatay eksen arasındaki açıyı nasıl hesaplayacağımı belirlemem gerekiyor?
Sanırım ne istediğimi en iyi bir resim anlatıyor:
(P1x,P1y) ve (P2x,P2y) verildiğinde bu açıyı hesaplamanın en iyi yolu nedir? Orijin sol üstte ve sadece pozitif çeyrek kullanılıyor.
Önce başlangıç noktası ile bitiş noktası arasındaki farkı bulun (burada bu bir "çizgi" değil, daha çok yönlendirilmiş bir doğru parçasıdır, çünkü çizgiler sonsuza kadar uzanır ve belirli bir noktada başlamaz).
deltaY = P2_y - P1_y
deltaX = P2_x - P1_x
Ardından açıyı hesaplayın (bu açı P1
deki pozitif X ekseninden P1
deki pozitif Y eksenine uzanır).
angleInDegrees = arctan(deltaY / deltaX) * 180 / PI
Ancak arctan
ideal olmayabilir, çünkü farkları bu şekilde bölmek, açının hangi çeyrekte olduğunu ayırt etmek için gereken ayrımı silecektir (aşağıya bakın). Eğer diliniz bir atan2
fonksiyonu içeriyorsa bunun yerine aşağıdakini kullanın:
angleInDegrees = atan2(deltaY, deltaX) * 180 / PI
DÜZENLEME (22 Şubat 2017): Bununla birlikte, genel olarak, sadece cos
ve sin
için uygun açıyı elde etmek için atan2(deltaY,deltaX)
çağırmak uygun olmayabilir. Bu gibi durumlarda, bunun yerine genellikle aşağıdakileri yapabilirsiniz:
deltaX
ve deltaY
değerlerini vektörün uzunluğuna (sqrt(deltaX*deltaX+deltaY*deltaY)
) bölün.deltaX
artık vektör ile yatay eksen arasındaki açının kosinüsü olacaktır (pozitif Xten pozitif Y eksenine
P1` yönünde).deltaY
şimdi bu açının sinüsü olacaktır.DÜZENLEME (28 Şubat 2017): Normalleştirme olmadan bile (deltaX, deltaY)
:
ve deltaY
nin işaretleri, P1
deki pozitif X eksenine göre açının hangi çeyrekte olduğunu söyleyecektir:+deltaX
, +deltaY
: 0 ila 90 derece.-deltaX
, +deltaY
: 90 ila 180 derece.-deltaX
, -deltaY
: 180 ila 270 derece (-180 ila -90 derece).+deltaX
, -deltaY
: 270 ila 360 derece (-90 ila 0 derece).Python'da radyan kullanan bir uygulama (19 Temmuz 2015 tarihinde cevabımı düzenleyen Eric Leschinski tarafından sağlanmıştır):
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)
Tüm testler geçer. Bkz. https://en.wikipedia.org/wiki/Unit_circle
Üzgünüm ama Peter'ın cevabının yanlış olduğuna eminim. Y ekseninin sayfanın aşağısına doğru gittiğine dikkat edin (grafiklerde yaygındır). Bu nedenle deltaY hesaplamasının tersine çevrilmesi gerekir, aksi takdirde yanlış cevap alırsınız.
Bir düşünün:
System.out.println (Math.toDegrees(Math.atan2(1,1)));
System.out.println (Math.toDegrees(Math.atan2(-1,1)));
System.out.println (Math.toDegrees(Math.atan2(1,-1)));
System.out.println (Math.toDegrees(Math.atan2(-1,-1)));
verir
45.0
-45.0
135.0
-135.0
Dolayısıyla, yukarıdaki örnekte P1 (1,1) ve P2 (2,2) ise [çünkü Y sayfanın aşağısında artar], yukarıdaki kod gösterilen örnek için 45,0 derece verecektir ki bu yanlıştır. DeltaY hesaplamasının sırasını değiştirdiğinizde düzgün çalışır.