计算两点之间的角度(顺时针)

Eri*_*ric 16 python math angle

我一直没有使用数学,这应该是一个简单的问题需要解决.

假设我有两个点A:(1,0)和B:(1,-1).

我想使用程序(Python或任何编程语言)来计算A,原点(0,0)和B之间的顺时针角度.它将是这样的:

angle_clockwise(point1, point2)
Run Code Online (Sandbox Code Playgroud)

请注意,参数的顺序很重要.由于角度计算将是顺时针的:

  • 如果我调用angle_clockwise(A,B),则返回45.
  • 如果我调用angle_clockwise(B,A),则返回315.

换句话说,算法是这样的:

  1. 在第一个点参数和(0,0)之间画一条线(第1行).
  2. 在第二个点参数和(0,0)之间画一条线(第2行).
  3. 顺时针旋转第1行(0,0),直到它与第2行重叠.
  4. 行进的角距离线1将是返回的角度.

有没有办法编码这个问题?

ali*_*i_m 22

Numpy arctan2(y, x)将计算原点和点之间的逆时针角度(-π和π之间的弧度值)(x, y).

你可以为你的观点做到这一点A,并B,然后从第一减去第二角度获得顺时针签署角度差.这个差异在-2π和2π之间,所以为了得到0到2π之间的正角,你可以取模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))
Run Code Online (Sandbox Code Playgroud)

例如:

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

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

print(angle_between(B, A))
# 315.
Run Code Online (Sandbox Code Playgroud)

如果你不想使用numpy,你可以使用math.atan2代替np.arctan2,并使用math.degrees(或只是乘以180 / math.pi)以便从弧度转换为度数.的numpy的版本的一个好处是,你还可以传递两个(2, ...)数组的p1p2以计算的方式矢量多对点之间的角度.

  • @Spirko OP要求从原点到点A的矢量与从原点到点B的矢量之间的顺时针角度.我们有三个点和两个矢量,因此角度是明确定义的. (2认同)
  • @Eric 你是对的 - 这仅指的是 `np.arctan2` 的输出,而不是两个这样的角度的差异。我已经更新了措辞以澄清这一点。 (2认同)

Chr*_*rre 10

使用内积和两个向量的行列式.如果你想了解它的工作原理,这就是你应该理解的.您需要了解/阅读有关矢量数学的知识.

请参阅:https://en.wikipedia.org/wiki/Dot_producthttps://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
Run Code Online (Sandbox Code Playgroud)

在行列式计算中,您将两个向量连接起来形成一个2 x 2矩阵,为此计算行列式.


ish*_*hak 6

经过验证的 0\xc2\xb0 到 360\xc2\xb0 解决方案

\n

这是一个旧线程,但对我来说其他解决方案效果不佳,所以我实现了自己的版本。

\n

我的函数将为屏幕上的两个点返回 0 到 360(不包括 360)之间的数字(即“y”从顶部开始并向底部增加),其中结果如指南针所示,0\xc2\xb0 位于顶部,顺时针增加:

\n
def angle_between_points(p1, p2):\n    d1 = p2[0] - p1[0]\n    d2 = p2[1] - p1[1]\n    if d1 == 0:\n        if d2 == 0:  # same points?\n            deg = 0\n        else:\n            deg = 0 if p1[1] > p2[1] else 180\n    elif d2 == 0:\n        deg = 90 if p1[0] < p2[0] else 270\n    else:\n        deg = math.atan(d2 / d1) / pi * 180\n        lowering = p1[1] < p2[1]\n        if (lowering and deg < 0) or (not lowering and deg > 0):\n            deg += 270\n        else:\n            deg += 90\n    return deg\n
Run Code Online (Sandbox Code Playgroud)\n


Col*_*ett 5

这是一个不需要的解决方案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
Run Code Online (Sandbox Code Playgroud)