从3个点计算方向旋转角度

时间:2013-03-15 20:42:23

标签: python rotation angle

我要做的是找到由三个连续点形成的线之间的旋转角度。这些是连续点,因此旋转方向很重要。 我的输入是一对坐标。

我想要的输出是每个点的旋转角度,其中该点将充当角度的顶点。该角度在1到360之间,其中负数表示向左旋转,正数表示向右旋转。

我几周来一直在努力解决这个问题,但我终于比以往任何时候都更接近解决方案了。我编写了以下脚本,并将其与程序地理空间建​​模工具(GME)的“pathmetrics”函数的输出进行了比较。

coords=coords=[[283907,971700],[284185,971634],[284287,971507],[284275,971608],[283919,971761],[284311,971648],[284277,971637],[284280,971651],[284174,971649],[283909,971701],[283941,971700],[284294,971518],[284288,971517],[284315,971539],[284250,971505]
print "A"+"\t"+"B"+"\t"+"C"+"\t"+"orientation"+"\t"+"angle"+"\t"+"bearing AB"+"\t"+"bearing BC"
for a in coords:
  A=a
  indexA=coords.index(a)
  B=coords[indexA+1]
  C=coords[indexA+2]
  ##Find the bearings of AB and BC
  AB=[B[0]-A[0],B[1]-A[1]]          #find the extreme of vector AB
  BearAB=math.atan2(AB[0],AB[1])    #use arctan2 to find the angle
  ABBearDeg=math.degrees(BearAB)    #in degrees
  if ABBearDeg<0:                   #if negative, add 360 in order to obtain the angle in a clockwise direction
   ABBearDeg=360+ABBearDeg          #Bearing AB
  BC=[C[0]-B[0],C[1]-B[1]]          #Do the same for points BC
  BearBC=math.atan2(BC[0],BC[1])
  BCBearDeg=math.degrees(BearBC)
  if BCBearDeg<0:
   BCBearDeg=360+BCBearDeg          #Bearing BC
 ##Find the angle between the lines
  alfa=BCBearDeg-ABBearDeg          #Obtain the difference between the bearing angles
  if abs(alfa)>180:                 #If greater than 180
   if alfa<0:                        #and negative
    angle=(360+alfa)                   #Direction of rotation is right and angle is obtained by adding 360
    print format(A)+"\t"+format(B)+"\t"+format(C)+"\t"+"right"+"\t"+format(angle)+"\t"+format(round(ABBearDeg,2))+"\t"+format(round(BCBearDeg,2))
   else:                             #If positive
    angle=alfa-360                      #Direction of rotation is left and angle is obtained by substracting 360
    print format(A)+"\t"+format(B)+"\t"+format(C)+"\t"+"left"+"\t"+format(angle)+"\t"+format(ABBearDeg)+"\t"+format(round(BCBearDeg,2))
  else:                            #If the difference was less than 180, then the rotation angle is equal to it
   angle=alfa
   if angle<0:                     #If negative, left rotation
       print format(A)+"\t"+format(B)+"\t"+format(C)+"\t"+"left"+"\t"+format(angle)+"\t"+format(ABBearDeg)+"\t"+format(round(BCBearDeg,2))
   else:                            #If positive, right rotation
    print format(A)+"\t"+format(B)+"\t"+format(C)+"\t"+"right"+"\t"+format(angle)+"\t"+format(ABBearDeg)+"\t"+format(round(BCBearDeg,2))

虽然许多结果重合,但其他结果却不一致。

                            My results                                                                      GME results     
        A                   B                   C       orientation     angle       bearing AB  bearing BC  GMEangle    GMEbearing AB   GMEbearing BC
[283907, 971700]    [284185, 971634]    [284287, 971507]    right       37.8750     103.3553    141.2300    37.8750     103.3553        141.2303
[284185, 971634]    [284287, 971507]    [284275, 971608]    left        -148.0060   141.2303    353.2200    -148.0060   141.2303        353.2243
[284287, 971507]    [284275, 971608]    [283919, 971761]    left        -59.9675    353.2243    293.2600    -68.9673    353.2243        284.2570
[284275, 971608]    [283919, 971761]    [284311, 971648]    right       172.8236    293.2600    106.0800    96.6181     284.2570        106.0804
[283919, 971761]    [284311, 971648]    [284277, 971637]    right       145.9916    106.0804    252.0700    145.9916    106.0804        252.0721
[284311, 971648]    [284277, 971637]    [284280, 971651]    right       120.0227    252.0700    12.0900     120.0227    252.0721        12.0948
[284277, 971637]    [284280, 971651]    [284174, 971649]    left        -103.1757   12.0948     268.9200    -103.1757   12.0948         268.9191
[284280, 971651]    [284174, 971649]    [283909, 971701]    right       12.1828     268.9191    281.1000    -131.4097   268.9191        137.5094
[284174, 971649]    [283909, 971701]    [283941, 971700]    right       170.6880    281.1000    91.7900     85.2053     137.5094        9.4623
[283909, 971701]    [283941, 971700]    [284294, 971518]    right       25.4848     91.7899     117.2700    146.4722    9.4623          85.0429
[283941, 971700]    [284294, 971518]    [284288, 971517]    right       143.2629    117.2748    260.5400    123.0283    85.0429         260.5377
[284294, 971518]    [284288, 971517]    [284315, 971539]    right       150.2887    260.5400    50.8300     150.2887    260.5377        50.8263
[284288, 971517]    [284315, 971539]    [284250, 971505]    left        -168.4394   50.8263     242.3900    -147.5925   50.8263         263.2338

(抱歉这张杂乱的桌子;我无法上传我想要的图片)

我已经能够指出错误发生的点,但我无法弄清楚它为什么会发生,因为它严格依赖于我无法控制的预设公式。 所以,不同之处在于(有时候)我对矢量方位的计算与GME计算的不同。 奇怪的是它有时会发生,我不知道是什么触发它。

有关可能发生的事情的任何想法?

如果你知道任何其他方法来计算包含运动方向的线条之间的角度,请告诉我。 任何有效的东西都可以和我一起使用。

感谢!!!!

1 个答案:

答案 0 :(得分:1)

你有A,B和C点。我从你的描述中假设B是旋转点。也就是说,矢量BA转换为BC。

  • 创建向量BA(A-B)和BC(C-B)。
  • 计算向量的角度(使它们为正)及其差异
  • 矢量之间的角度差是旋转角度。

使用numpy让这很容易。像这样:

In [1]: import numpy as np

In [2]: A = np.array([283907, 971700])

In [3]: B = np.array([284185, 971634])

In [4]: C = np.array([284287, 971507])

In [5]: BA = A - B

In [6]: BC = C - B

In [7]: BA
Out[7]: array([-278,   66])

In [8]: BC
Out[8]: array([ 102, -127])

In [9]: s = np.arctan2(*BA)

In [10]: if s < 0:
   ....:     s += 2*np.pi
   ....:     

In [11]: s
Out[11]: 4.9454836529138948

In [12]: e = np.arctan2(*BC)

In [13]: if e < 0:
    e += 2*np.pi
   ....:     

In [14]: e
Out[14]: 2.4649341681747883

In [15]: delta = e - s

In [16]: np.degrees(delta)
Out[16]: -142.12501634890182

In [17]: delta
Out[17]: -2.4805494847391065

正角度是逆时针方向。