我认为叉积 np.cross 会在这里为您提供帮助。对于一个简单的三角形,首先逆时针,然后顺时针,这可能看起来像这样(可以优化,为了清晰起见,让它更长)。角度输出是向量之间的夹角,方向遵循右手定则:编辑:添加了一条方向变化的曲线,添加了图形(逆时针方向的注释):
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.path import Path
def drangl(vsgi, vsgi1):
'''sin(theta)=|axb|/(|a||b|)'''
return np.arcsin(np.cross(vsgi, vsgi1)/np.linalg.norm(vsgi)/np.linalg.norm(vsgi1))
print('going around the traingle counter-clockwise and clockwise:\n')
trace = np.array([(0.,0.), (10.,-1.), (5.,10.), (0.,0.)])
vsegs = np.diff(trace, axis=0)
for iv in [0,1,-1]: # counter-clockwise
print(f'ctr-cl: {iv:d} {drangl(vsegs[iv], vsegs[iv+1]):2.2f}')
for iv in [-1,1,0]: # clockwise
print(f'cw: {iv:d} {drangl(vsegs[iv], vsegs[iv+1]):2.2f}')
print('\nnow with direction change in the path:\n')
trace = np.array([(0.,0.), (10.,-1.), (9., 5.), (12., 5.), (5.,10.), (0.,0.)])
vsegs = np.diff(trace, axis=0)
for iv in [0,1,2,3,-1]: # counter-clockwise
print(f'ctr-cl: {iv:d} {drangl(vsegs[iv], vsegs[iv+1]):2.2f}')
for iv in [-1,3,2,1,0]: # clockwise
print(f'cw: {iv:d} {drangl(vsegs[iv], vsegs[iv+1]):2.2f}')
codes = [
Path.MOVETO,
Path.LINETO,
Path.LINETO,
Path.LINETO,
Path.LINETO,
Path.CLOSEPOLY,
]
path = Path(trace, codes)
fig, ax = plt.subplots()
patch = patches.PathPatch(path, facecolor='white', lw=2)
ax.add_patch(patch)
ax.set_xlim(-1, 13)
ax.set_ylim(-2, 11)
ax.annotate('turns right', xy=(9, 5), xytext=(5, 5),
arrowprops=dict(facecolor='black', shrink=0.05),
)
ax.annotate('turns left', xy=(12, 5), xytext=(10, 10),
arrowprops=dict(facecolor='black', shrink=0.05),
)
plt.show()
产生
逆时针和顺时针绕着火车转:
ctr-cl: 0 1.04
ctr-cl: 1 0.89
ctr-cl: -1 1.21
cw: -1 1.21
cw: 1 0.89
cw: 0 1.04
now with direction change in the path:
ctr-cl: 0 1.31
ctr-cl: 1 -1.41
ctr-cl: 2 0.62
ctr-cl: 3 1.41
ctr-cl: -1 1.21
cw: -1 1.21
cw: 3 1.41
cw: 2 0.62
cw: 1 -1.41
cw: 0 1.31
符号变化现在指示曲线改变方向的位置。