首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >python中使用曲线(路径跟踪)矢量的流可视化

python中使用曲线(路径跟踪)矢量的流可视化
EN

Stack Overflow用户
提问于 2018-08-14 22:01:09
回答 4查看 4.1K关注 0票数 16

我想用python绘制一个带有曲线箭头的矢量场,就像在vfplot (见下文)或IDL中一样。

您可以在matplotlib中接近,但使用

将您限制为直线向量(请参见左下角),而

似乎不允许对箭头长度或箭头位置进行有意义的控制(见下图右),即使在更改时也是如此

,以及

..。

那么,有没有可以做到这一点的python库呢?或者有没有办法让matplotlib做到这一点?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2018-08-24 00:13:56

如果您查看matplotlib中包含的streamplot.py,在196 - 202行(ish,idk,如果这在不同版本之间发生了变化-我在matplotlib 2.1.2上),我们会看到以下内容:

代码语言:javascript
复制
... (to line 195)
    # Add arrows half way along each trajectory.
    s = np.cumsum(np.sqrt(np.diff(tx) ** 2 + np.diff(ty) ** 2))
    n = np.searchsorted(s, s[-1] / 2.)
    arrow_tail = (tx[n], ty[n])
    arrow_head = (np.mean(tx[n:n + 2]), np.mean(ty[n:n + 2]))
 ... (after line 196)

将该部分更改为以下内容将起到作用(更改n的赋值):

代码语言:javascript
复制
... (to line 195)
    # Add arrows half way along each trajectory.
    s = np.cumsum(np.sqrt(np.diff(tx) ** 2 + np.diff(ty) ** 2))
    n = np.searchsorted(s, s[-1]) ### THIS IS THE EDITED LINE! ###
    arrow_tail = (tx[n], ty[n])
    arrow_head = (np.mean(tx[n:n + 2]), np.mean(ty[n:n + 2]))
 ... (after line 196)

如果您将此修改为将箭头放在末尾,则可以根据您的喜好生成更多箭头。

此外,从函数顶部的文档中,我们可以看到以下内容:

代码语言:javascript
复制
*linewidth* : numeric or 2d array
        vary linewidth when given a 2d array with the same shape as velocities.

线宽可以是

,如果您可以预先计算出所需的箭头宽度,则可以在绘制箭头时修改铅笔宽度。看起来这部分已经为你完成了。

因此,结合缩短箭头最大长度,增加密度和添加起点

_

点,以及调整函数,将箭头放在末尾而不是中间,您可以获得所需的图形。

通过这些修改和下面的代码,我能够得到更接近您想要的结果:

代码语言:javascript
复制
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import matplotlib.patches as pat

w = 3
Y, X = np.mgrid[-w:w:100j, -w:w:100j]
U = -1 - X**2 + Y
V = 1 + X - Y**2
speed = np.sqrt(U*U + V*V)

fig = plt.figure(figsize=(14, 18))
gs = gridspec.GridSpec(nrows=3, ncols=2, height_ratios=[1, 1, 2])

grains = 10
tmp = tuple([x]*grains for x in np.linspace(-2, 2, grains))
xs = []
for x in tmp:
    xs += x
ys = tuple(np.linspace(-2, 2, grains))*grains


seed_points = np.array([list(xs), list(ys)])
# Varying color along a streamline
ax1 = fig.add_subplot(gs[0, 1])

strm = ax1.streamplot(X, Y, U, V, color=U, linewidth=np.array(5*np.random.random_sample((100, 100))**2 + 1), cmap='winter', density=10,
                      minlength=0.001, maxlength = 0.07, arrowstyle='fancy',
                      integration_direction='forward', start_points = seed_points.T)
fig.colorbar(strm.lines)
ax1.set_title('Varying Color')

plt.tight_layout()
plt.show()

tl;dr:复制源代码,并将其更改为将箭头放在每个路径的末尾,而不是中间。然后使用您的streamplot而不是matplotlib streamplot。

编辑:我得到了不同的线宽

票数 4
EN

Stack Overflow用户

发布于 2018-08-24 16:54:51

从开始

David Culbreth的

修改,即

重写

大块的

函数来实现所需的行为。有点太多了,无法在这里全部说明,但它包括一个长度归一化方法,并禁用轨迹重叠检查。我附加了新版本的两个比较

函数与原始文件一起使用

..。

票数 4
EN

Stack Overflow用户

发布于 2021-01-07 14:18:00

这里有一种在vanilla pyplot中获得所需输出的方法(即,不修改streamplot函数或任何花哨的东西)。作为提醒,目标是可视化具有弯曲箭头的矢量场,其长度与矢量的范数成比例。

诀窍是:

制作不带箭头的流线图,从给定点向后追踪(请参见)

从这一点开始画一个箭图。使箭袋足够小,以便只有箭头可见

在循环中对每个种子重复1.和2.,并缩放流图的长度,使其与向量的范数成比例。

代码语言:javascript
复制
import matplotlib.pyplot as plt
import numpy as np
w = 3
Y, X = np.mgrid[-w:w:8j, -w:w:8j]

U = -Y
V = X
norm = np.sqrt(U**2 + V**2)
norm_flat = norm.flatten()

start_points = np.array([X.flatten(),Y.flatten()]).T

plt.clf()
scale = .2/np.max(norm)

plt.subplot(121)
plt.title('scaling only the length')
for i in range(start_points.shape[0]):
    plt.streamplot(X,Y,U,V, color='k', start_points=np.array([start_points[i,:]]),minlength=.95*norm_flat[i]*scale, maxlength=1.0*norm_flat[i]*scale,
                integration_direction='backward', density=10, arrowsize=0.0)
plt.quiver(X,Y,U/norm, V/norm,scale=30)
plt.axis('square')



plt.subplot(122)
plt.title('scaling length, arrowhead and linewidth')
for i in range(start_points.shape[0]):
    plt.streamplot(X,Y,U,V, color='k', start_points=np.array([start_points[i,:]]),minlength=.95*norm_flat[i]*scale, maxlength=1.0*norm_flat[i]*scale,
                integration_direction='backward', density=10, arrowsize=0.0, linewidth=.5*norm_flat[i])
plt.quiver(X,Y,U/np.max(norm), V/np.max(norm),scale=30)

plt.axis('square')

结果如下:

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51843313

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档