如何在 Matplotlib 中指定类似箭头的线型? [英] How do I specify an arrow-like linestyle in Matplotlib?

查看:34
本文介绍了如何在 Matplotlib 中指定类似箭头的线型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想以指示特定路径的方式在 Matplotlib 中显示一组 xy 数据.理想情况下,可以将线型修改为使用类似箭头的补丁.我创建了一个模型,如下所示(使用Omnigraphsketcher).似乎我应该能够覆盖常见的 linestyle 声明之一 ('-', '--', ':' 等) 达到这种效果.

I would like to display a set of xy-data in Matplotlib in such a way as to indicate a particular path. Ideally, the linestyle would be modified to use an arrow-like patch. I have created a mock-up, shown below (using Omnigraphsketcher). It seems like I should be able to override one of the common linestyle declarations ('-', '--', ':', etc) to this effect.

请注意,我不想简单地用单个箭头连接每个数据点——实际数据点的间距不均匀,我需要一致的箭头间距.

Note that I do NOT want to simply connect each datapoint with a single arrow---the actually data points are not uniformly spaced and I need consistent arrow spacing.

推荐答案

这是一个起点:

  1. 以固定的步骤(在我下面的示例中为aspace)沿着您的路线走.

A.这涉及沿着由两组点 (x1,y1) 和 (x2,y2).

A. This involves taking steps along the line segments created by two sets of points (x1,y1) and (x2,y2).

B.如果您的步长比线段长,请移至下一组点.

B. If your step is longer than the line segment, shift to the next set of points.

在那一点确定线的角度.

At that point determine the angle of the line.

绘制一个与角度相对应的倾斜度的箭头.

Draw an arrow with an inclination corresponding to the angle.

我写了一个小脚本来演示这一点:

I wrote a little script to demonstrate this:

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:

对于初学者来说,这里有很大的改进空间:

There's plenty of room for improvement here, for starters:

  1. 可以使用 FancyArrowPatch 来自定义箭头的外观.
  2. 创建箭头时,可以添加进一步的测试,以确保箭头不会超出该线.这将与在线急剧改变方向的顶点处或附近创建的箭头相关.上面最右边的点就是这种情况.
  3. 一个人可以从此脚本制作一种方法,该方法将在更广泛的情况下工作,即使其更易于移植.
  1. One can use FancyArrowPatch to customize the look of the arrows.
  2. One can add a further test when creating the arrows to make sure they don't extend beyond the line. This will be relevant to arrows created at or near a vertex where the line changes direction sharply. This is the case for the right most point above.
  3. One can make a method from this script that will work across a broader range of cases, ie make it more portable.

在调查时,我发现了颤音绘图方法.它也许可以代替上面的工作,但是并不能立即保证是可以保证的.

While looking into this, I discovered the quiver plotting method. It might be able to replace the above work, but it wasn't immediately obvious that this was guaranteed.

这篇关于如何在 Matplotlib 中指定类似箭头的线型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆