相关文章推荐
紧张的小熊猫  ·  JOSN.parse(JSON.string ...·  1 年前    · 
听话的手套  ·  用 ...·  2 年前    · 
飘逸的青蛙  ·  javascript - ...·  2 年前    · 
  • If I call angle_clockwise(A, B), it returns 45.
  • If I call angle_clockwise(B, A), it returns 315.
  • 换句话说,这个算法是这样的。

  • Draw a line (line 1) between the first point param with (0, 0).
  • Draw a line (line 2) between the second point param with (0, 0).
  • Revolve line 1 around (0, 0) clockwise until it overlaps line 2.
  • The angular distance line 1 traveled will be the returned angle.
  • 有什么方法可以对这个问题进行编码吗?

    4 个评论
    ggrr
    这个问题问的是实现atan2的代码,而不是atan2的概念,为什么建议查看更多关于atan2的信息?
    "如果我调用angle_clockwise(B, A),它返回335" - 你肯定是指315(360-45)?
    Eric
    呜呼......。是的,我是说315。现在你知道我有多长时间没有使用数学了吧 :D
    python
    math
    angle
    Eric
    Eric
    发布于 2015-07-31
    8 个回答
    ali_m
    ali_m
    发布于 2021-05-28
    已采纳
    0 人赞同

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

    你可以对你的点 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))
    
    A = (1, 0)
    B = (1, -1)
    print(angle_between(A, B))
    # 45.
    print(angle_between(B, A))
    # 315.
    

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

    替换代码0】计算X轴与矢量 (x,y) 之间的逆时针角度(以readian为单位)。 要定义一个角度,你需要三个点或两个矢量,而不仅仅是两个点。
    @Spirko OP问的是原点到A点的矢量和原点到B点的矢量之间的顺时针角度。
    Eric
    "这将是在-π和π之间"这是不正确的 - 角度将在-2π和2π之间
    @Eric 你是对的--那只是指 np.arctan2 的输出,而不是两个这样的角度的差。我已经更新了措辞以澄清这一点。
    你真了不起。
    Chris St Pierre
    Chris St Pierre
    发布于 2021-05-28
    0 人赞同

    使用两个向量的内积和行列式。如果你想了解这一点,这才是你真正应该了解的。你需要了解/阅读有关向量数学的知识才能理解。

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

    在行列式计算中,你将两个向量连接起来,形成一个2×2的矩阵,你要计算这个矩阵的行列式。

    如何将其推广到n-dims?
    这能处理除以0的问题吗?
    Colin Basnett
    Colin Basnett
    发布于 2021-05-28
    0 人赞同

    这里有一个不需要 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
        
    最好不要用这么差的近似值来计算π
    @317070 固定π的值。
    可以在最后使用r % 360。在Python中,模数的工作原理是它应该与负数一起使用 :)
    ishahak
    ishahak
    发布于 2021-05-28
    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
        
    awmo
    awmo
    发布于 2021-05-28
    0 人赞同

    Check out the cmath python库。

    >>> import cmath
    >>> a_phase = cmath.phase(complex(1,0))
    >>> b_phase = cmath.phase(complex(1,-1))
    >>> (a_phase - b_phase) * 180 / cmath.pi
    >>> (b_phase - a_phase) * 180 / cmath.pi
    -45.0
    

    你可以检查一个数字是否小于0,如果你想得到所有的正角,也可以在上面加360。

    Antoine
    Antoine
    发布于 2021-05-28
    0 人赞同

    Chris St Pierre: when using your function with:

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

    这应该是一个从AB90度角。你的函数将返回270

    你在处理det的符号时是否有错误,还是我错过了什么?

    这并没有回答这个问题。一旦你获得足够的声誉,你就可以对问题进行评论。同时,请尝试回答那些不需要其作者澄清的问题。
    theodore panagos
    theodore panagos
    发布于 2021-05-28
    0 人赞同

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

    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)

    For N=E=0 the result is undefined.

    degr
    degr
    发布于 2021-05-28
    0 人赞同

    以弧度为单位,顺时针,从0到PI * 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;