这是一个起点:
-
以固定的步数沿着路线行走(aspace
在我下面的例子中)。
A. 这涉及沿着两组点创建的线段采取步骤(x1
,y1
) and (x2
,y2
).
B. 如果您的步长比线段长,则转移到下一组点。
此时确定线的角度。
画一个箭头,其倾斜度与角度相对应。
我写了一个小脚本来演示这一点:
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
axes = fig.add_subplot(111)
# my random data
scale = 10
np.random.seed(101)
x = np.random.random(10)*scale
y = np.random.random(10)*scale
# spacing of arrows
aspace = .1 # good value for scale of 1
aspace *= scale
# r is the distance spanned between pairs of points
r = [0]
for i in range(1,len(x)):
dx = x[i]-x[i-1]
dy = y[i]-y[i-1]
r.append(np.sqrt(dx*dx+dy*dy))
r = np.array(r)
# rtot is a cumulative sum of r, it's used to save time
rtot = []
for i in range(len(r)):
rtot.append(r[0:i].sum())
rtot.append(r.sum())
arrowData = [] # will hold tuples of x,y,theta for each arrow
arrowPos = 0 # current point on walk along data
rcount = 1
while arrowPos < r.sum():
x1,x2 = x[rcount-1],x[rcount]
y1,y2 = y[rcount-1],y[rcount]
da = arrowPos-rtot[rcount]
theta = np.arctan2((x2-x1),(y2-y1))
ax = np.sin(theta)*da+x1
ay = np.cos(theta)*da+y1
arrowData.append((ax,ay,theta))
arrowPos+=aspace
while arrowPos > rtot[rcount+1]:
rcount+=1
if arrowPos > rtot[-1]:
break
# could be done in above block if you want
for ax,ay,theta in arrowData:
# use aspace as a guide for size and length of things
# scaling factors were chosen by experimenting a bit
axes.arrow(ax,ay,
np.sin(theta)*aspace/10,np.cos(theta)*aspace/10,
head_width=aspace/8)
axes.plot(x,y)
axes.set_xlim(x.min()*.9,x.max()*1.1)
axes.set_ylim(y.min()*.9,y.max()*1.1)
plt.show()
This example results in this figure:
对于初学者来说,这里还有很大的改进空间:
- 一个可以用花式箭头补丁 http://matplotlib.sourceforge.net/api/artist_api.html?highlight=arrow#matplotlib.patches.FancyArrowPatch自定义箭头的外观。
- 在创建箭头时可以添加进一步的测试,以确保它们不会超出线条。这与在线急剧改变方向的顶点处或附近创建的箭头相关。上面最右边的点就是这种情况。
- 人们可以从这个脚本中创建一种可以在更广泛的情况下工作的方法,即使其更加可移植。
在研究这个问题时,我发现quiver http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.quiver绘图方法。它也许能够取代上述工作,但目前还不清楚这是否得到保证。