Calculer l'angle (dans le sens des aiguilles d'une montre) entre deux points
Je n'utilise pas les mathématiques depuis longtemps et cela devrait être un problème simple à résoudre.
Supposons que j'ai deux points: (1, 0) et B: (1, -1).
je veux utiliser un programme (Python ou n'importe quel langage de programmation) pour calculer l'angle dans le sens des aiguilles d'une montre entre A, origin (0, 0) et B. Ce sera quelque chose comme ceci:
angle_clockwise(point1, point2)
Notez que l'ordre des paramètres questions. Puisque le calcul de l'angle sera dans le sens des aiguilles d'une montre:
- si J'appelle angle_clockwise (A, B), il retourne 45.
- si j'appelle angle_clockwise (B, A), il renvoie 315.
En d'autres termes, l'algorithme est comme ceci:
- tracer une ligne (Ligne 1) entre le premier point param avec (0, 0).
- tracer une ligne (Ligne 2) entre le deuxième point param avec (0, 0).
- tourner la ligne 1 autour de (0, 0) dans le sens des aiguilles d'une montre jusqu'à ce qu'elle chevauche la ligne 2.
- la distance angulaire de la ligne 1 parcourue sera être le retour de l'angle.
y a-t-il un moyen de coder ce problème?
5 réponses
Utilisez le produit intérieur et le déterminant des deux vecteurs. C'est vraiment ce que vous devez comprendre si vous voulez comprendre comment cela fonctionne. Vous aurez besoin de savoir/lire sur vector math pour comprendre.
Voir: https://en.wikipedia.org/wiki/Dot_product et 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
dans le calcul déterminant, vous concaténez les deux vecteurs pour former une matrice 2 x 2, pour laquelle vous êtes le calcul du déterminant.
Numpy arctan2(y, x)
calcule l'angle dans le sens contraire des aiguilles d'une montre (une valeur en radians entre-π Et π) entre l'origine et le point (x, y)
.
Vous pouvez faire cela pour que vos points A
et B
, puis soustrayez le deuxième angle du premier pour obtenir la différence angulaire Signée dans le sens des aiguilles d'une montre. Cette différence s'entre -2π 2π, et, donc, afin d'obtenir un angle positif entre 0 et 2π vous pouvez ensuite prendre le modulo contre 2π. Enfin, vous pouvez convertir les radians en degrés en utilisant 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))
Par exemple:
A = (1, 0)
B = (1, -1)
print(angle_between(A, B))
# 45.
print(angle_between(B, A))
# 315.
Si vous ne souhaitez pas utiliser numpy, vous pouvez utiliser math.atan2
à la place de np.arctan2
, et utiliser math.degrees
(ou simplement multiplier par 180 / math.pi
) afin de convertir des radians en degrés. Un avantage de la version numpy est que vous pouvez également passer deux (2, ...)
tableaux p1
et p2
afin de calculer les angles entre plusieurs des paires de points dans un vectorisé.
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
découvrez le cmath bibliothèque 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
Vous pouvez vérifier si un nombre est inférieur à 0 et ajouter 360 si vous souhaitez tous les angles positifs, trop.
Chris St Pierre: lors de l'utilisation de votre fonction avec:
A = (x=1, y=0)
B = (x=0, y=1)
C'est censé être un 90
angle de degré de A
B
. Votre fonction sera de retour 270
.
y a-t-il une erreur dans la façon dont vous traitez le signe du det ou est-ce que je manque quelque chose?