Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 计算两点之间的角度(顺时针方向)_Python_Math_Angle - Fatal编程技术网

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

Python 计算两点之间的角度(顺时针方向),python,math,angle,Python,Math,Angle,我已经很久没有使用数学了,这应该是一个简单的问题来解决 假设我有两点A:(1,0)和B:(1,-1) 我想用一个程序(Python或任何编程语言)来计算a,原点(0,0)和B之间的顺时针角度。它将是这样的: angle_clockwise(point1, point2) 请注意,参数的顺序很重要。由于角度计算将顺时针进行: def angle_between_points(p1, p2): d1 = p2[0] - p1[0] d2 = p2[1] - p1[1] if

我已经很久没有使用数学了,这应该是一个简单的问题来解决

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

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

angle_clockwise(point1, point2)
请注意,参数的顺序很重要。由于角度计算将顺时针进行:

def angle_between_points(p1, p2):
    d1 = p2[0] - p1[0]
    d2 = p2[1] - p1[1]
    if d1 == 0:
        if d2 == 0:  # same points?
            deg = 0
        else:
            deg = 0 if p1[1] > p2[1] else 180
    elif d2 == 0:
        deg = 90 if p1[0] < p2[0] else 270
    else:
        deg = math.atan(d2 / d1) / pi * 180
        lowering = p1[1] < p2[1]
        if (lowering and deg < 0) or (not lowering and deg > 0):
            deg += 270
        else:
            deg += 90
    return deg
  • 如果我顺时针调用角度_(A,B),它返回45
  • 如果我顺时针调用角度_(B,A),它返回315
换句话说,算法是这样的:

angle_clockwise(point1, point2)
  • 使用(0,0)在第一个点参数之间绘制一条线(线1)
  • 使用(0,0)在第二个点参数之间绘制一条线(线2)
  • 顺时针旋转线1(0,0),直到它与线2重叠
  • 直线1经过的角距离将是返回的角度
  • 有没有办法编写这个问题的代码?

    查看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
    
    你可以检查一个数字是否小于0,如果你想要所有的正角度,也可以加360。

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

    您可以对点
    A
    B
    执行此操作,然后从第一个角度减去第二个角度,以获得符号顺时针角度差。这个差在-2π和2π之间,所以为了得到0和2π之间的正角度,你可以取模与2π的比值。最后,可以使用将弧度转换为度

    例如:

    A = (1, 0)
    B = (1, -1)
    
    print(angle_between(A, B))
    # 45.
    
    print(angle_between(B, A))
    # 315.
    

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

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

    见:和

    从数学导入acos
    从数学导入sqrt
    从数学导入pi
    def长度(v):
    返回sqrt(v[0]**2+v[1]**2)
    def dot_产品(v、w):
    返回v[0]*w[0]+v[1]*w[1]
    def行列式(v,w):
    返回v[0]*w[1]-v[1]*w[0]
    def内倾角(v,w):
    cosx=点积(v,w)/(长度(v)*长度(w))
    rad=acos(cosx)#弧度
    返回弧度*180/pi#返回度
    def角度_顺时针(A、B):
    内=内倾角(A,B)
    det=行列式(A,B)
    如果det为0,则A为B的顺时针方向
    返回360内部
    

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

    这是一个不需要
    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
    
    导入数学
    类向量:
    定义初始化(self,x,y):
    self.x=x
    self.y=y
    v1=向量(0,1)
    v2=向量(0,-1)
    v1_θ=数学atan2(v1.y,v1.x)
    v2_θ=数学常数2(v2.y,v2.x)
    r=(v2θ-v1θ)*(180.0/math.pi)
    如果r<0:
    r+=360.0
    印刷机
    
    Chris St Pierre:使用函数时:

    A = (x=1, y=0)
    B = (x=0, y=1)
    
    这应该是从
    a
    B
    90度角。您的函数将返回
    270


    在处理det符号时是否有错误,或者我是否遗漏了什么?

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

    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)))
    
    公式给出了从0到2pi的角度,从北到北

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


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

    验证的0°至360°解决方案

    这是一个旧线程,但对我来说,其他解决方案没有很好地工作,所以我实现了自己的版本

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

    def angle_between_points(p1, p2):
        d1 = p2[0] - p1[0]
        d2 = p2[1] - p1[1]
        if d1 == 0:
            if d2 == 0:  # same points?
                deg = 0
            else:
                deg = 0 if p1[1] > p2[1] else 180
        elif d2 == 0:
            deg = 90 if p1[0] < p2[0] else 270
        else:
            deg = math.atan(d2 / d1) / pi * 180
            lowering = p1[1] < p2[1]
            if (lowering and deg < 0) or (not lowering and deg > 0):
                deg += 270
            else:
                deg += 90
        return deg
    
    点(p1、p2)之间的定义角度: d1=p2[0]-p1[0] d2=p2[1]-p1[1] 如果d1==0: 如果d2==0:#相同的点? 度=0 其他: 如果p1[1]>p2[1],则deg=0,否则为180 elif d2==0: 如果p1[0]0): 摄氏度+=270度 其他: 摄氏度+=90度 返回度
    以弧度为单位,顺时针,从0到π*2

    static angle(center:Coord, p1:Coord, p2:Coord) {
        var a1 = Math.atan2(p1.y - center.y, p1.x - center.x);
        var a2 = Math.atan2(p2.y - center.y, p2.x -center.x);
        a1 = a1 > 0 ? a1 : Math.PI * 2 + a1;//make angle from 0 to PI * 2
        a2 = a2 > 0 ? a2 : Math.PI * 2 + a2;
        if(a1 > a2) {
            return a1 - a2;
        } else {
            return Math.PI * 2 - (a2 - a1)
        }
    }
    

    阅读并注意atan2在问题中是关于实现atan2的代码,而不是atan2的概念,为什么建议查看更多关于atan2的内容?“如果我顺时针调用angle_(B,A),它返回335”-当然你是指315(360-45)?哇。。。是的,我是说315。现在你知道我有多长时间没用数学了:最好不要用这么差的近似值pi@317070pi的固定值。最后可以使用r%360。在Python中,模数的工作原理与负数相同:)
    arctan2(y,x)
    计算x轴和向量之间的逆时针角度
    (x,y)
    。要定义一个角度,你需要三个点或两个向量,而不仅仅是两个点。@Spirko OP要求的是从原点到点A的向量与从原点到点B的向量之间的顺时针角度。我们有三个点和两个向量,所以角度定义得很好。“这将介于-π和π之间”这不是真的-角度将在-2π和2π@Eric之间-你是对的-这只是指
    np.arctan2
    的输出,而不是两个suc的差