使用 matplotlib 填充区域的补集

发布于 2024-10-14 16:15:10 字数 222 浏览 0 评论 0原文

我目前正在使用 Python 和 matplotlib 实现一些东西。我知道如何绘制多边形以及如何填充它们,但是如何填充除多边形内部之外的所有内容?为了更清楚起见,我想修改下面使用 axhspan 和 axvspan 获得的结果,通过裁剪水平和垂直红线以获得一个红色矩形(外面的所有内容都像现在一样被阴影化): 在此处输入图像描述

I'm currently implementing something with Python and matplotlib. I know how to draw polygons and also how to fill them, but how do I fill everything except the interior of a polygon? To be clearer, I'd like to modify the result below, obtained using axhspan's and axvspan's, by clipping the horizontal and vertical red lines so as to obtain a red rectangle (outside which everything is hatched as it is now):
enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

棒棒糖 2024-10-21 16:15:10

这篇文章本质上提出(并回答)这个问题。查看已接受答案中的“编辑 2”。它描述了如何创建绘图边界大小的矢量多边形,以及如何在其中创建孔以匹配您想要补充的形状。它通过分配定义笔移动时是否绘制的行代码来实现此目的。

以下是上述帖子中与此问题相关的部分:

import numpy as np
import matplotlib.pyplot as plt

def main():
    # Contour some regular (fake) data
    grid = np.arange(100).reshape((10,10))
    plt.contourf(grid)

    # Verticies of the clipping polygon in counter-clockwise order
    #  (A triange, in this case)
    poly_verts = [(2, 2), (5, 2.5), (6, 8), (2, 2)]

    mask_outside_polygon(poly_verts)

    plt.show()

def mask_outside_polygon(poly_verts, ax=None):
    """
    Plots a mask on the specified axis ("ax", defaults to plt.gca()) such that
    all areas outside of the polygon specified by "poly_verts" are masked.  

    "poly_verts" must be a list of tuples of the verticies in the polygon in
    counter-clockwise order.

    Returns the matplotlib.patches.PathPatch instance plotted on the figure.
    """
    import matplotlib.patches as mpatches
    import matplotlib.path as mpath

    if ax is None:
        ax = plt.gca()

    # Get current plot limits
    xlim = ax.get_xlim()
    ylim = ax.get_ylim()

    # Verticies of the plot boundaries in clockwise order
    bound_verts = [(xlim[0], ylim[0]), (xlim[0], ylim[1]), 
                   (xlim[1], ylim[1]), (xlim[1], ylim[0]), 
                   (xlim[0], ylim[0])]

    # A series of codes (1 and 2) to tell matplotlib whether to draw a line or 
    # move the "pen" (So that there's no connecting line)
    bound_codes = [mpath.Path.MOVETO] + (len(bound_verts) - 1) * [mpath.Path.LINETO]
    poly_codes = [mpath.Path.MOVETO] + (len(poly_verts) - 1) * [mpath.Path.LINETO]

    # Plot the masking patch
    path = mpath.Path(bound_verts + poly_verts, bound_codes + poly_codes)
    patch = mpatches.PathPatch(path, facecolor='white', edgecolor='none')
    patch = ax.add_patch(patch)

    # Reset the plot limits to their original extents
    ax.set_xlim(xlim)
    ax.set_ylim(ylim)

    return patch

if __name__ == '__main__':
    main()

This post asks (and answers) essentially this question. Look at 'Edit 2' in the accepted answer. It describes how to create a vector polygon the size of your plot bounds and then how to create a hole in it to match the shape you want to complement. It does this by assigning line codes that define whether or not the pen draws when it moves.

Here is the portion of the above-referenced post that is relevant to this question:

import numpy as np
import matplotlib.pyplot as plt

def main():
    # Contour some regular (fake) data
    grid = np.arange(100).reshape((10,10))
    plt.contourf(grid)

    # Verticies of the clipping polygon in counter-clockwise order
    #  (A triange, in this case)
    poly_verts = [(2, 2), (5, 2.5), (6, 8), (2, 2)]

    mask_outside_polygon(poly_verts)

    plt.show()

def mask_outside_polygon(poly_verts, ax=None):
    """
    Plots a mask on the specified axis ("ax", defaults to plt.gca()) such that
    all areas outside of the polygon specified by "poly_verts" are masked.  

    "poly_verts" must be a list of tuples of the verticies in the polygon in
    counter-clockwise order.

    Returns the matplotlib.patches.PathPatch instance plotted on the figure.
    """
    import matplotlib.patches as mpatches
    import matplotlib.path as mpath

    if ax is None:
        ax = plt.gca()

    # Get current plot limits
    xlim = ax.get_xlim()
    ylim = ax.get_ylim()

    # Verticies of the plot boundaries in clockwise order
    bound_verts = [(xlim[0], ylim[0]), (xlim[0], ylim[1]), 
                   (xlim[1], ylim[1]), (xlim[1], ylim[0]), 
                   (xlim[0], ylim[0])]

    # A series of codes (1 and 2) to tell matplotlib whether to draw a line or 
    # move the "pen" (So that there's no connecting line)
    bound_codes = [mpath.Path.MOVETO] + (len(bound_verts) - 1) * [mpath.Path.LINETO]
    poly_codes = [mpath.Path.MOVETO] + (len(poly_verts) - 1) * [mpath.Path.LINETO]

    # Plot the masking patch
    path = mpath.Path(bound_verts + poly_verts, bound_codes + poly_codes)
    patch = mpatches.PathPatch(path, facecolor='white', edgecolor='none')
    patch = ax.add_patch(patch)

    # Reset the plot limits to their original extents
    ax.set_xlim(xlim)
    ax.set_ylim(ylim)

    return patch

if __name__ == '__main__':
    main()
我不咬妳我踢妳 2024-10-21 16:15:10

如果您只需要一个矩形的补集,则可以在其周围绘制 4 个矩形(如示例图像中可见的 4 个矩形)。绘图边缘的坐标可以通过 xlim()ylim() 获得。

我不确定 Matplotlib 是否提供了一种绘制多边形外部的方法......

If you only need the complement of a rectangle, you could instead draw 4 rectangles around it (like the 4 rectangles that are visible in your example image). The coordinates of the plot edges can be obtained with xlim() and ylim().

I am not sure that Matplotlib offers a way of painting the outside of a polygon…

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文