首页 > 解决方案 > 旋转参考系,改变角度计算比例

问题描述

我浪费了令人尴尬的时间来编写一个函数,该函数采用两个笛卡尔坐标origintarget,并指定箭头指向的角度,origin其中target零度[0,360)是箭头笔直向上。

默认的pythonatan2()会给我一个(-180,180]零度箭头指向右边。

我可以将角度转换为 [0,360) 比例,但我找不到一种外观简洁的方法来将 0 度参考从指向右侧的向量更改为指向上方的向量。我做了一些例子来展示计算的演变以及它如何偏离我想要的。

def measure_angle_standard(origin, target):
    x = target[0]-origin[0]
    y = target[1]-origin[1]

    #angle relative to X axis going clockwise-positive
    angle_degrees =  math.degrees(math.atan2(y,x))
    return angle_degrees


def measure_angle_0_360(origin, target):
    x = target[0]-origin[0]
    y = target[1]-origin[1]

    #angle relative to X axis going clockwise-positive
    angle_degrees =  math.degrees(math.atan2(y,x))
    angle_degrees =      (angle_degrees + 360) % 360  
    return angle_degrees

def measure_angle_up_is_zero(origin, target):
    x = target[0]-origin[0]
    y = target[1]-origin[1]

    #angle relative to X axis going clockwise-positive
    angle_degrees =  math.degrees(math.atan2(y,x))
    #angle_degrees = angle_degrees -90 # this is wrong!
    angle_degrees =      (angle_degrees + 360) % 360  
    angle_degrees = (angle_degrees - 90) % 180   # this is also wrong!
    return angle_degrees


for v in [measure_angle_standard,  measure_angle_0_360, measure_angle_up_is_zero ]:
    print(f"\n\n {v}")
    print("up slightly right", round(v( (5,5), (5.1,2)),1),  " s/b tiny positive angle") #should be tiny positive angle
    print("point up ", v( (5,5), (5,2)), " s/b 0" )  #should be zero
    print("up slightly left ", round(v( (5,5), (4.9,2)),1), " s/b ~359 degrees") #should be almost 360

    print("point right ", v( (5,5), (9,5)), " s/b 90")  #should be 90
    print("point left ", v( (5,5), (1,5)), " s/b 270") #should be 270
    print("point down ", v( (5,5), (5,8)), " s/b 180") #should be 180

我看不出如何以非总的方式干净地获得最终轮换。

(在有人将此消息标记为重复消息之前,我已经在这里阅读了数十个类似的问题,其中大多数是用代码高尔夫片段咒语回答的半成形问题。我不感兴趣只是随机尝试黑客,直到我得到有效的东西。这些答案通常在边距 0、360 等处失败。)

 <function measure_angle_standard at 0x7fecda0947b8>
up slightly right -88.1  s/b tiny positive angle
point up  -90.0  s/b 0
up slightly left  -91.9  s/b ~359 degrees
point right  0.0  s/b 90
point left  180.0  s/b 270
point down  90.0  s/b 180


 <function measure_angle_0_360 at 0x7fecda040730>
up slightly right 271.9  s/b tiny positive angle
point up  270.0  s/b 0
up slightly left  268.1  s/b ~359 degrees
point right  0.0  s/b 90
point left  180.0  s/b 270
point down  90.0  s/b 180


 <function measure_angle_up_is_zero at 0x7fecda0940d0>
up slightly right 1.9  s/b tiny positive angle
point up  0.0  s/b 0
up slightly left  178.1  s/b ~359 degrees
point right  90.0  s/b 90
point left  90.0  s/b 270
point down  0.0  s/b 180

标签: pythongeometry

解决方案


math.p1/2在转换为度数之前,我用弧度移动它。

def measure_angle_up_is_zero(origin, target):
    x = target[0]-origin[0]
    y = target[1]-origin[1]

    #angle relative to Y axis going clockwise-positive
    angle_degrees =  math.degrees(math.atan2(y,x)+ (math.pi/2.0)) 
    angle_degrees =      (angle_degrees + 360) % 360  
    return angle_degrees

这给了我想要的答案:

 <function measure_angle_up_is_zero at 0x7fecda243400>
up slightly right 1.9  s/b tiny positive angle
point up  0.0  s/b 0
up slightly left  358.1  s/b ~359 degrees
slightly above right 88.56790381583534  s/b ~89
point right  90.0  s/b 90
slightly below right 91.43209618416466  s/b ~91
point left  270.0  s/b 270
point down  180.0  s/b 180

推荐阅读