首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在matplotlib中绘制“双向宽线”

如何在matplotlib中绘制“双向宽线”
EN

Stack Overflow用户
提问于 2016-06-10 04:53:34
回答 2查看 898关注 0票数 6

如何使用matplotlib或pyqtgraph绘制如下所示的绘图:

AB线是一条双向街道,绿色部分代表从A点到B点的方向,红色部分代表B到A点,每个部分的宽度代表交通量。宽度按点测量,在不同的缩放级别或dpi设置时不会更改。

这只是一个例子,其实我有很多街头小贩。这种情节在许多交通软件中是非常普遍的。我试图使用matplotlib的理解,但结果令人沮丧:

代码语言:javascript
运行
复制
from matplotlib import pyplot as plt
import matplotlib.patheffects as path_effects

x=[0,1,2,3]
y=[1,0,0,-1]
ab_width=20
ba_width=30

fig, axes= plt.subplots(1,1)
center_line, = axes.plot(x,y,color='k',linewidth=2)

center_line.set_path_effects(
[path_effects.SimpleLineShadow(offset=(0, -ab_width/2),shadow_color='g', alpha=1, linewidth=ab_width),
path_effects.SimpleLineShadow(offset=(0, ba_width/2), shadow_color='r', alpha=1, linewidth=ba_width),
path_effects.SimpleLineShadow(offset=(0, -ab_width), shadow_color='k', alpha=1, linewidth=2),
path_effects.SimpleLineShadow(offset=(0, ba_width), shadow_color='k', alpha=1, linewidth=2),
path_effects.Normal()])

axes.set_xlim(-1,4)
axes.set_ylim(-1.5,1.5)

我有一个想法,就是把这条线的每一部分作为一条独立的线,在改变缩放水平时重新计算它的位置,但它太复杂了,太慢了。

如果有什么简单的方法可以使用matplotlib或pyqtgraph来绘制我想要的?如有任何建议,将不胜感激!

EN

回答 2

Stack Overflow用户

发布于 2016-06-16 13:56:58

如果您可以拥有每一行独立的代码,这可以很容易地使用fill_between函数来完成。

代码语言:javascript
运行
复制
from matplotlib import pyplot as plt
import numpy as np

x=np.array([0,1,2,3])
y=np.array([1,0,0,-1])

y1width=-1
y2width=3
y1 = y + y1width
y2 = y + y2width

fig = plt.figure()
ax = fig.add_subplot(111)

plt.plot(x,y, 'k', x,y1, 'k',x,y2, 'k',linewidth=2)
ax.fill_between(x, y1, y, color='g')
ax.fill_between(x, y2, y, color='r')

plt.xlim(-1,4)
plt.ylim(-3,6)
plt.show()

在这里,我将中心线作为引用(因此是负的y1width),但是可以做不同的操作。结果是:

如果线条是“复杂的”,最终在某个点相交,那么必须使用关键字参数interpolate=True来正确地填充交叉区域。对您的用例可能有用的另一个有趣的论点是where,可以对区域进行条件化,例如,where=y1 < 0。有关更多信息,您可以查看文档

票数 4
EN

Stack Overflow用户

发布于 2016-06-19 01:15:58

解决问题的一个方法是使用填充多边形,一些线性代数和一些微积分。其主要思想是沿xy坐标绘制多边形,并沿移位坐标绘制多边形以关闭和填充多边形。

以下是我的研究结果:

这是密码:

代码语言:javascript
运行
复制
from __future__ import division
import numpy
from matplotlib import pyplot, patches


def road(x, y, w, scale=0.005, **kwargs):
    # Makes sure input coordinates are arrays.
    x, y = numpy.asarray(x, dtype=float), numpy.asarray(y, dtype=float)
    # Calculate derivative.
    dx = x[2:] - x[:-2]
    dy = y[2:] - y[:-2]
    dy_dx = numpy.concatenate([
        [(y[1] - y[0]) / (x[1] - x[0])],
        dy / dx,
        [(y[-1] - y[-2]) / (x[-1] - x[-2])]
    ])
    # Offsets the input coordinates according to the local derivative.
    offset = -dy_dx + 1j
    offset =  w * scale * offset / abs(offset)
    y_offset = y + w * scale
    #
    AB = zip(
        numpy.concatenate([x + offset.real, x[::-1]]),
        numpy.concatenate([y + offset.imag, y[::-1]]),
    )
    p = patches.Polygon(AB, **kwargs)

    # Returns polygon.
    return p


if __name__ == '__main__':
    # Some plot initializations
    pyplot.close('all')
    pyplot.ion()

    # This is the list of coordinates of each point
    x = [0, 1, 2, 3, 4]
    y = [1, 0, 0, -1, 0]

    # Creates figure and axes.
    fig, ax = pyplot.subplots(1,1)
    ax.axis('equal')
    center_line, = ax.plot(x, y, color='k', linewidth=2)

    AB = road(x, y, 20, color='g')
    BA = road(x, y, -30, color='r')
    ax.add_patch(AB)
    ax.add_patch(BA)

计算如何偏移每个数据点的第一步是通过计算离散导数dy / dx。我喜欢使用复杂符号来处理Python中的向量,即A = 1 - 1j。这使得一些数学运算更容易。

下一步是记住,导数给出的切线到曲线,从线性代数,法向正切是n=-dy_dx + 1j,使用复表示法。

确定偏移坐标的最后一步是确保法向量具有单位大小的n_norm = n / abs(n),并乘以所需多边形的宽度。

现在我们有了多边形中所有点的坐标,剩下的就很简单了。使用patches.Polygon并将它们添加到绘图中。

此代码还允许您定义是否希望修补程序位于路由的顶部或下面。只要给出一个正或负值的宽度。如果要根据缩放级别和/或分辨率更改多边形的宽度,则调整scale参数。它还允许您向补丁添加额外的参数,如填充模式、透明度等。

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

https://stackoverflow.com/questions/37740160

复制
相关文章

相似问题

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