私は長い間数学を使用していませんでしたが、これは簡単な問題です。
2つのポイントA:(1、0)とB:(1、-1)があるとします。
プログラム(Pythonまたは任意のプログラミング言語)を使用して、A、Origin(0、0)、B間の時計回りの角度を計算します。これは次のようになります。
angle_clockwise(point1, point2)
パラメーターの順序が重要であることに注意してください。角度の計算は時計回りになるため:
つまり、アルゴリズムは次のようになります。
この問題をコーディングする方法はありますか?
2つのベクトルの内積と行列式を使用します。これが実際にどのように機能するかを理解したい場合、これは本当に理解すべきことです。理解するには、ベクトル演算について知っておく必要があります。
参照: https://en.wikipedia.org/wiki/Dot_product および https://en.wikipedia.org/wiki/Determinant
from math import acos
from math import sqrt
from math import pi
def length(v):
return sqrt(v[0]**2+v[1]**2)
def dot_product(v,w):
return v[0]*w[0]+v[1]*w[1]
def determinant(v,w):
return v[0]*w[1]-v[1]*w[0]
def inner_angle(v,w):
cosx=dot_product(v,w)/(length(v)*length(w))
rad=acos(cosx) # in radians
return rad*180/pi # returns degrees
def angle_clockwise(A, B):
inner=inner_angle(A,B)
det = determinant(A,B)
if det<0: #this is a property of the det. If the det < 0 then B is clockwise of A
return inner
else: # if the det > 0 then A is immediately clockwise of B
return 360-inner
行列式の計算では、2つのベクトルを連結して2 x 2行列を形成し、行列式を計算しています。
Numpyの arctan2(y, x)
は、Originとポイント(x, y)
間の反時計回りの角度(-πとπの間のラジアン値)を計算します。
ポイントA
とB
に対してこれを実行し、最初の角度から2番目の角度を減算して、時計回りの符号付きangular差を取得します。この差は-2πと2πの間であるため、0から2πの間の正の角度を得るために、2πに対するモジュロを取ることができます。最後に、 np.rad2deg
を使用してラジアンを度に変換できます。
import numpy as np
def angle_between(p1, p2):
ang1 = np.arctan2(*p1[::-1])
ang2 = np.arctan2(*p2[::-1])
return np.rad2deg((ang1 - ang2) % (2 * np.pi))
例えば:
A = (1, 0)
B = (1, -1)
print(angle_between(A, B))
# 45.
print(angle_between(B, A))
# 315.
Numpyを使用したくない場合は、math.atan2
の代わりに np.arctan2
を使用し、 math.degrees
(または単に乗算ラジアンから度に変換するために180 / math.pi
で)。 numpyバージョンの利点の1つは、ベクトル化された方法でポイントの複数のペア間の角度を計算するために、(2, ...)
およびp1
に2つのp2
配列を渡すこともできることです。
cmath
を必要としないソリューションを次に示します。
import math
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
v1 = Vector(0, 1)
v2 = Vector(0, -1)
v1_theta = math.atan2(v1.y, v1.x)
v2_theta = math.atan2(v2.y, v2.x)
r = (v2_theta - v1_theta) * (180.0 / math.pi)
if r < 0:
r += 360.0
print r
cmath pythonライブラリ。
>>> import cmath
>>> a_phase = cmath.phase(complex(1,0))
>>> b_phase = cmath.phase(complex(1,-1))
>>> (a_phase - b_phase) * 180 / cmath.pi
45.0
>>> (b_phase - a_phase) * 180 / cmath.pi
-45.0
すべての正の角度が必要な場合は、数値が0より小さいかどうかを確認し、360を追加できます。
Chris St Pierre:関数を以下で使用する場合:
A = (x=1, y=0)
B = (x=0, y=1)
これは、A
からB
までの90
度の角度になるはずです。関数は270
を返します。
あなたがdetのサインを処理する方法にエラーがありますか、何か不足していますか?
時計回りに角度を計算し、測量で使用される式:
f(E,N)=pi()-pi()/2*(1+sign(N))* (1-sign(E^2))-pi()/4*(2+sign(N))*sign(E)
-sign(N*E)*atan((abs(N)-abs(E))/(abs(N)+abs(E)))
式は、0から2piまでの角度を与え、北から始まり、
[〜#〜] n [〜#〜]および[〜#〜] e [〜#〜]の任意の値に対して機能します。 (N = N2-N1およびE = E2-E1)
N = E =の場合、結果は未定義です。