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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31735499/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 10:29:12  来源:igfitidea点击:

Calculate angle (clockwise) between two points

pythonmathangle

提问by Eric

I have been not using math for a long time and this should be a simple problem to solve.

我已经很长时间没有使用数学了,这应该是一个很容易解决的问题。

Suppose I have two points A: (1, 0) and B: (1, -1).

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

I want to use a program (Python or whatever programming language) to calculate the clockwise angle between A, origin (0, 0) and B. It will be something like this:

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

angle_clockwise(point1, point2)

Note that the order of the parameters matters. Since the angle calculation will be clockwise:

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

  • If I call angle_clockwise(A, B), it returns 45.
  • If I call angle_clockwise(B, A), it returns 315.
  • 如果我调用angle_clock(A, B),它返回45。
  • 如果我调用angle_clock(B, A),它返回315。

In other words, the algorithm is like this:

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

  1. Draw a line (line 1) between the first point param with (0, 0).
  2. Draw a line (line 2) between the second point param with (0, 0).
  3. Revolve line 1 around (0, 0) clockwise until it overlaps line 2.
  4. The angular distance line 1 traveled will be the returned angle.
  1. 在第一个点参数与 (0, 0) 之间画一条线(第 1 行)。
  2. 在带有 (0, 0) 的第二个点参数之间画一条线(第 2 行)。
  3. 将第 1 行绕 (0, 0) 顺时针旋转,直到它与第 2 行重叠。
  4. 线 1 行进的角距离将是返回的角度。

Is there any way to code this problem?

有什么办法可以解决这个问题吗?

采纳答案by Chris St Pierre

Use the inner product and the determinant of the two vectors. This is really what you should understand if you want to understand how this works. You'll need to know/read about vector math to understand.

使用两个向量的内积和行列式。如果您想了解其工作原理,这确实是您应该了解的内容。您需要了解/阅读矢量数学才能理解。

See: https://en.wikipedia.org/wiki/Dot_productand https://en.wikipedia.org/wiki/Determinant

请参阅: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

In the determinant computation, you're concatenating the two vectors to form a 2 x 2 matrix, for which you're computing the determinant.

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

回答by awmo

Check out the cmathpython library.

查看cmathpython 库。

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

You can check if a number is less than 0 and add 360 to it if you want all positive angles, too.

如果您想要所有正角度,您也可以检查数字是否小于 0 并添加 360。

回答by ali_m

Numpy's arctan2(y, x)will compute the counterclockwise angle (a value in radians between -π and π) between the origin and the point (x, y).

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

You could do this for your points Aand B, then subtract the second angle from the first to get the signed clockwise angular difference. This difference will be between -2π and 2π, so in order to get a positive angle between 0 and 2π you could then take the modulo against 2π. Finally you can convert radians to degrees using np.rad2deg.

您可以对您的点A和执行此操作B,然后从第一个角度减去第二个角度以获得带符号的顺时针角度差。这种差异将在 -2π 和 2π 之间,因此为了获得 0 和 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))

For example:

例如:

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

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

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

If you don't want to use numpy, you could use math.atan2in place of np.arctan2, and use math.degrees(or just multiply by 180 / math.pi) in order to convert from radians to degrees. One advantage of the numpy version is that you can also pass two (2, ...)arrays for p1and p2in order to compute the angles between multiple pairs of points in a vectorized way.

如果您不想使用 numpy,则可以使用math.atan2代替np.arctan2, 并使用math.degrees(或仅乘以180 / math.pi)以将弧度转换为度数。numpy 版本的一个优点是您还可(2, ...)以为p1and传递两个数组p2,以便以矢量化方式计算多对点之间的角度。

回答by Colin Basnett

Here's a solution that doesn't require cmath.

这是一个不需要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

回答by Antoine

Chris St Pierre: when using your function with:

Chris St Pierre:将您的函数用于:

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

This is supposed to be a 90degree angle from Ato B. Your function will return 270.

这应该是90A到的度角B。您的函数将返回270.

Is there an error in how you process the sign of the det or am I missing something?

您处理 det 符号的方式是否有错误,或者我是否遗漏了什么?

回答by theodore panagos

A formula that calculates an angle clockwise, and is used in surveying:

顺时针计算角度的公式,用于测量:

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

The formula gives angles from 0 to 2pi,start from the North and

该公式给出了从 0 到 2pi 的角度,从北开始,然后

is working for any value of Nand E. (N=N2-N1 and E=E2-E1)

正在为NE 的任何值工作。( N=N2-N1 和 E=E2-E1)

For N=E=0the result is undefined.

对于 N=E=0,结果未定义。