wake-up-neo.net

Berechnen Sie den Winkel (im Uhrzeigersinn) zwischen zwei Punkten

Ich benutze schon lange keine Mathematik und dies sollte ein einfaches Problem sein.

Angenommen, ich habe zwei Punkte A: (1, 0) und B: (1, -1).

Ich möchte ein Programm (Python oder eine andere Programmiersprache) verwenden, um den Winkel im Uhrzeigersinn zwischen A, Origin (0, 0) und B zu berechnen.

angle_clockwise(point1, point2)

Beachten Sie, dass die Reihenfolge der Parameter von Bedeutung ist. Da die Winkelberechnung im Uhrzeigersinn erfolgt:

  • Wenn ich angle_clockwise (A, B) anrufe, wird 45 zurückgegeben.
  • Wenn ich angle_clockwise (B, A) anrufe, wird 315 zurückgegeben.

Mit anderen Worten ist der Algorithmus so:

  1. Zeichnen Sie eine Linie (Linie 1) zwischen dem ersten Punkt param mit (0, 0).
  2. Zeichnen Sie eine Linie (Linie 2) zwischen dem zweiten Punkt param mit (0, 0).
  3. Drehen Sie Linie 1 im Uhrzeigersinn um (0, 0), bis sie Linie 2 überlappt.
  4. Die zurückgelegte Winkelentfernungslinie 1 ist der zurückgegebene Winkel.

Gibt es eine Möglichkeit, dieses Problem zu codieren?

13
Eric

Verwenden Sie das innere Produkt und die Determinante der beiden Vektoren. Dies ist wirklich das, was Sie verstehen sollten, wenn Sie wissen möchten, wie dies funktioniert. Sie müssen über Vektor-Mathematik verfügen, um sie zu verstehen.

Siehe: https://en.wikipedia.org/wiki/Dot_product und 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

Bei der Determinantenberechnung verketten Sie die zwei Vektoren zu einer 2 x 2-Matrix, für die Sie die Determinante berechnen.

9
Chris St Pierre

Numpys arctan2(y, x) berechnet den Winkel entgegen dem Uhrzeigersinn (ein Wert im Bogenmaß zwischen -π und π) zwischen dem Ursprung und dem Punkt (x, y).

Sie könnten dies für Ihre Punkte A und B tun und dann den zweiten Winkel von dem ersten subtrahieren, um die im Uhrzeigersinn vorzeichenbehaftete Winkeldifferenz zu erhalten. Dieser Unterschied liegt zwischen -2π und 2π. Um einen positiven Winkel zwischen 0 und 2π zu erhalten, können Sie dann den Modulo gegen 2π nehmen. Schließlich können Sie Radiant in Grad konvertieren, indem Sie np.rad2deg verwenden.

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))

Zum Beispiel:

A = (1, 0)
B = (1, -1)

print(angle_between(A, B))
# 45.

print(angle_between(B, A))
# 315.

Wenn Sie numpy nicht verwenden möchten, können Sie anstelle von math.atan2np.arctan2 verwenden und math.degrees (oder einfach mit 180 / math.pi multiplizieren) verwenden, um den Radiant in Grad zu konvertieren. Ein Vorteil der numpy-Version ist, dass Sie auch zwei (2, ...)-Arrays für p1 und p2 übergeben können, um die Winkel zwischen mehreren Punktpaaren vektorisiert zu berechnen.

18
ali_m

Hier ist eine Lösung, die cmath nicht benötigt.

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
Colin Basnett

Schauen Sie sich die Bibliothek " cmath python" an.

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

Sie können überprüfen, ob eine Zahl kleiner als 0 ist, und 360 hinzufügen, wenn Sie auch alle positiven Winkel verwenden möchten.

1
awmo

Chris St Pierre: bei Verwendung Ihrer Funktion mit:

A = (x=1, y=0)
B = (x=0, y=1)

Dies soll ein 90-Winkel von A zu B sein. Ihre Funktion gibt 270 zurück.

Gibt es einen Fehler bei der Verarbeitung des Zeichens des Det oder fehlt mir etwas?

1
Antoine

Eine Formel, die einen Winkel im Uhrzeigersinn berechnet und bei der Vermessung verwendet wird:

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)))

Die Formel gibt Winkel von 0 bis 2pi an, beginnend von Norden und

arbeitet für jeden Wert vonNundE. ( N = N2 - N1 und E = E2 - E1 )

Für N = E = 0 ist das Ergebnis undefiniert.

0