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:

  1. tracer une ligne (Ligne 1) entre le premier point param avec (0, 0).
  2. tracer une ligne (Ligne 2) entre le deuxième point param avec (0, 0).
  3. tourner la ligne 1 autour de (0, 0) dans le sens des aiguilles d'une montre jusqu'à ce qu'elle chevauche la ligne 2.
  4. 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?

12
demandé sur Laurel 2015-07-31 02:01:59

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.

8
répondu Chris St Pierre 2016-05-24 18:19:28

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é.

17
répondu ali_m 2018-05-08 18:58:36
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
5
répondu Colin Basnett 2017-02-16 23:56:33

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.

1
répondu awmo 2015-07-30 23:12:30

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 AB. 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?

1
répondu Antoine 2018-02-13 14:47:14