概要
下図左側のように2つのベクトルの間の角度を算出する方法は内積などを取れば良く、よく知られている。本記事では、2つのベクトルの角度に加え、下図右側のように任意のベクトルを基準とした2つのベクトルの回転角を算出するコードをget rotation angle between two vectorsの記事を参考にして紹介する。
Google Colabで作成したコードは、こちらにあります。
各種インポート
各種インポート
import numpy as np
import matplotlib.pyplot as plt
2つのベクトルの角度
def vector_to_vector_angle(vector_1, vector_2):
unit_vector_1 = vector_1 / np.linalg.norm(vector_1)
unit_vector_2 = vector_2 / np.linalg.norm(vector_2)
cos = np.dot(unit_vector_1, unit_vector_2)
rad_angle = np.arccos(cos)
angle = rad_angle / np.pi * 180
return angle
-
vector_* / np.linalg.norm(vector_*)
で単位ベクトルに変換します。 - 単位ベクトルに対して
np.dot(unit_vector_1, unit_vector_2)
で内積を取り、2つの角度の$\cos(\theta)$を求めます。 -
np.arccos(cos)
で、$\theta$を求めます。 - $\theta$はラジアンなので、
rad_angle / np.pi * 180
で度に変換します。
任意のベクトルからの回転角
任意のベクトルからの回転角
def vector_to_vector_rotation_angle(vector_1, vector_2):
unit_vector_1 = vector_1 / np.linalg.norm(vector_1)
unit_vector_2 = vector_2 / np.linalg.norm(vector_2)
cos = np.dot(unit_vector_1, unit_vector_2)
rad_angle = np.arccos(cos)
angle = rad_angle / np.pi * 180
cross = np.cross(vector_1, vector_2)
if cross < 0:
angle *= -1
return angle
途中までは、2つのベクトルの角度と同じです。
-
cross = np.cross(vector_1, vector_2)
で、2次元のクロス積を求めます。(np.cross(vector_1, vector_2)
は、vector_1[0]*vector_2[1]-vector_2[0]*vector_1[1]
で定義されていて、$|vector_1||vector_2|\sin(\theta)$となり、$\sin(\theta)$が求まるので回転方向を決めるのに役立ちます。) -
cross < 0
のとき、$\sin(\theta)$が負となり回転角も負となります。
サンプルでの実装結果
サンプルでの実装結果
# サンプル1
vector_1 = np.array([3, 5])
vector_2 = np.array([4, 2])
angle = vector_to_vector_angle(vector_1, vector_2)
rotate_angle = vector_to_vector_rotation_angle(vector_1, vector_2)
print(f'2つのベクトルの角度: {angle:.2f}')
print(f'vector_1を基準とした回転角: {rotate_angle:.2f}')
# 図に表示
fig, ax = plt.subplots()
ax.quiver(*vector_1, angles='xy', scale_units='xy', scale=1, color='r', label='vector_1')
ax.quiver(*vector_2, angles='xy', scale_units='xy', scale=1, color='b', label='vector_2')
ax.set_aspect('equal')
ax.set_xlim(0, 5)
ax.set_ylim(0, 5)
ax.legend()
plt.show()
出力結果
2つのベクトルの角度: 32.47
vector_1を基準とした回転角: -32.47
注意事項
- vector_1とvector_2=λvecotr_1(λ>0)の場合、0°が期待されるが正しく計算されない場合がある。
- vecotr_1とvector_2=-λvecotr_1(λ>0)の場合、180°が期待されるが正しく計算されない場合がある。
- 0ベクトルがある場合は正しく計算されない。
参考資料