填充多边形外部|索引超出圆形边界的掩码数组?

发布于 2024-09-11 07:39:03 字数 1944 浏览 3 评论 0原文

我使用 plot(x,y,'r') 绘制红色圆圈。 x 和 y 是数组,当配对为 (x,y) 并绘制时,所有点形成一条圆线。

fill(x,y,'r') 绘制一个用红色填充(或着色)的红色圆圈。

如何使圆圈内部保持白色,但将圆圈外部填充到轴边界?

我研究过使用 fill_ Between(x_array, y1_array, y2_array, where) 但经过一番尝试后,我认为这不适用于我的 x,y 数组。我想在圆之外和由轴边界定义的正方形内填充,但我认为填充之间没有能力……我'我确信我可以将它变成一个积分类型的问题,其中 delta x 和 delta y 为零,但我不愿意这样做。

如果有人发现我缺少 fill_ Between() 的某些内容,请告诉我。

我真正需要做的就是屏蔽二维数组中位于用 x 和 y 创建的圆的边界之外的数字,这样当二维数组被视为彩色图或轮廓时,圆内将是图像,外面会变白。

这可以通过二维阵列的掩蔽技术来实现吗?就像使用 masked_where() 一样?我还没研究过,但会的。

有什么想法吗?谢谢

编辑1:这是我有权展示的内容,我认为这可以解释我的问题。

from pylab import *
from matplotlib.path import Path
from matplotlib.patches import PathPatch

f=Figure()
a=f.add_subplot(111)

# x,y,z are 2d arrays

# sometimes i plot a color plot
# im = a.pcolor(x,y,z)
a.pcolor(x,y,z)

# sometimes i plot a contour
a.contour(x,y,z)

# sometimes i plot both using a.hold(True)

# here is the masking part.
# sometimes i just want to see the boundary drawn without masking
# sometimes i want to see the boundary drawn with masking inside of the boundary
# sometimes i want to see the boundary drawn with masking outside of the boundary

# depending on the vectors that define x_bound and y_bound, sometimes the boundary
# is a circle, sometimes it is not.

path=Path(vpath)
patch=PathPatch(path,facecolor='none')
a.add_patch(patch) # just plots boundary if anything has been previously plotted on a
if ('I want to mask inside'):
    patch.set_facecolor('white') # masks(whitens) inside if pcolor is currently on a,
    # but if contour is on a, the contour part is not whitened out. 
else: # i want to mask outside 
    im.set_clip_path(patch) # masks outside only when im = a.pcolor(x,y,z)
    # the following commands don't update any masking but they don't produce errors?
    # patch.set_clip_on(True)
    # a.set_clip_on(True)
    # a.set_clip_path(patch)

a.show()

I use plot(x,y,'r') to plot a red circle. x and y are arrays such that when paired as (x,y) and plotted, all points form a circle-line.

fill(x,y,'r') plots a red circle that is filled in (or colored in) red.

How can I keep the circle white on the inside, but fill outside the circle out to the axis boundaries?

I looked into using fill_between(x_array, y1_array, y2_array, where) but after a little playing with it I don’t think that will work for my x,y arrays. I thought to fill_between() outside the circle, and inside a square that is defined by the axis boundaries, but I don’t think fill_between() is capable… I’m sure I could make it into an integral type of problem with delta x and delta y going to zero, but I’m not willing to.

If anyone can see that I’m missing something with fill_between() please let me know.

All I am really needing to do is mask out numbers in a 2d array that are located beyond this boundary of the circle created with x and y, such that when the 2D array is viewed as a color plot, or contour, inside the circle will be the image, and outside will be white-ed out.

Can this be accomplished by a masking technique of the 2D array instead? Like by using masked_where() ? I haven’t looked into it yet, but will.

Any ideas? Thanks

Edit 1: Here is what i have permission to show that I think will explain my problem.

from pylab import *
from matplotlib.path import Path
from matplotlib.patches import PathPatch

f=Figure()
a=f.add_subplot(111)

# x,y,z are 2d arrays

# sometimes i plot a color plot
# im = a.pcolor(x,y,z)
a.pcolor(x,y,z)

# sometimes i plot a contour
a.contour(x,y,z)

# sometimes i plot both using a.hold(True)

# here is the masking part.
# sometimes i just want to see the boundary drawn without masking
# sometimes i want to see the boundary drawn with masking inside of the boundary
# sometimes i want to see the boundary drawn with masking outside of the boundary

# depending on the vectors that define x_bound and y_bound, sometimes the boundary
# is a circle, sometimes it is not.

path=Path(vpath)
patch=PathPatch(path,facecolor='none')
a.add_patch(patch) # just plots boundary if anything has been previously plotted on a
if ('I want to mask inside'):
    patch.set_facecolor('white') # masks(whitens) inside if pcolor is currently on a,
    # but if contour is on a, the contour part is not whitened out. 
else: # i want to mask outside 
    im.set_clip_path(patch) # masks outside only when im = a.pcolor(x,y,z)
    # the following commands don't update any masking but they don't produce errors?
    # patch.set_clip_on(True)
    # a.set_clip_on(True)
    # a.set_clip_path(patch)

a.show()

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

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

发布评论

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

评论(3

我很OK 2024-09-18 07:39:03

我真正需要做的就是戴上面具
输出二维数组中的数字
位于该边界之外
用 x 和 y 创建的圆,这样
当二维数组被视为颜色时
圆内的绘图或轮廓
将是图像,而外部将是
白化。

您有两个选择:

首先,您可以对图像使用屏蔽数组。这更复杂,但更安全。要屏蔽圆外的数组,请生成距中心点的距离图,并屏蔽距离大于半径的位置。

更简单的选择是在绘制图像后使用 im.set_clip_path() 剪切补丁外部的区域。

请参阅来自 matplotlib 库的此示例。不幸的是,根据我的经验,对于某些轴(非笛卡尔轴),这可能会有点问题。但在其他所有情况下,它都应该完美地工作。

编辑:顺便说一句,这是如何执行您最初要求的操作:绘制多边形里面有一个洞。不过,如果您只想遮盖图像,那么最好使用上述两个选项之一。

Edit2:只是给出两种方式的快速示例...

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches

def main():
    # Generate some random data
    nx, ny = 100, 100
    data = np.random.random((ny,nx))

    # Define a circle in the center of the data with a radius of 20 pixels
    radius = 20
    center_x = nx // 2
    center_y = ny // 2

    plot_masked(data, center_x, center_y, radius)
    plot_clipped(data, center_x, center_y, radius)
    plt.show()

def plot_masked(data, center_x, center_y, radius):
    """Plots the image masked outside of a circle using masked arrays"""
    # Calculate the distance from the center of the circle
    ny, nx = data.shape
    ix, iy = np.meshgrid(np.arange(nx), np.arange(ny))
    distance = np.sqrt((ix - center_x)**2 + (iy - center_y)**2)

    # Mask portions of the data array outside of the circle
    data = np.ma.masked_where(distance > radius, data)

    # Plot
    plt.figure()
    plt.imshow(data)
    plt.title('Masked Array')

def plot_clipped(data, center_x, center_y, radius):
    """Plots the image clipped outside of a circle by using a clip path"""
    fig = plt.figure()
    ax = fig.add_subplot(111)

    # Make a circle
    circ = patches.Circle((center_x, center_y), radius, facecolor='none')
    ax.add_patch(circ) # Plot the outline

    # Plot the clipped image
    im = ax.imshow(data, clip_path=circ, clip_on=True)

    plt.title('Clipped Array')

main()

在此处输入图像描述
在此处输入图像描述

编辑 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()

剪裁轮廓图

All I am really needing to do is mask
out numbers in a 2d array that are
located beyond this boundary of the
circle created with x and y, such that
when the 2D array is viewed as a color
plot, or contour, inside the circle
will be the image, and outside will be
white-ed out.

You have two options:

First, you could use a masked array for the images. This is more complicated but a bit more failsafe. To mask an array outside of a circle, generate a distance map from the center point, and mask where distance is greater than the radius.

The easier option is to clip the areas ouside of the patch with im.set_clip_path() after you've plotted the image.

See this example from the matplotlib gallery. Unfortunately, with some axes (non-cartesian axes) this can be a bit glitchy, in my experience. In every other case it should work perfectly, though.

Edit: Incidentally, this is how to do what you originally asked: plot a polygon with a hole inside. If you just want to mask an image, though, you're better off with either of the two options above.

Edit2: Just to give a quick example of both ways...

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches

def main():
    # Generate some random data
    nx, ny = 100, 100
    data = np.random.random((ny,nx))

    # Define a circle in the center of the data with a radius of 20 pixels
    radius = 20
    center_x = nx // 2
    center_y = ny // 2

    plot_masked(data, center_x, center_y, radius)
    plot_clipped(data, center_x, center_y, radius)
    plt.show()

def plot_masked(data, center_x, center_y, radius):
    """Plots the image masked outside of a circle using masked arrays"""
    # Calculate the distance from the center of the circle
    ny, nx = data.shape
    ix, iy = np.meshgrid(np.arange(nx), np.arange(ny))
    distance = np.sqrt((ix - center_x)**2 + (iy - center_y)**2)

    # Mask portions of the data array outside of the circle
    data = np.ma.masked_where(distance > radius, data)

    # Plot
    plt.figure()
    plt.imshow(data)
    plt.title('Masked Array')

def plot_clipped(data, center_x, center_y, radius):
    """Plots the image clipped outside of a circle by using a clip path"""
    fig = plt.figure()
    ax = fig.add_subplot(111)

    # Make a circle
    circ = patches.Circle((center_x, center_y), radius, facecolor='none')
    ax.add_patch(circ) # Plot the outline

    # Plot the clipped image
    im = ax.imshow(data, clip_path=circ, clip_on=True)

    plt.title('Clipped Array')

main()

enter image description here
enter image description here

Edit 2: Plotting a mask polygon over the original plot:
Here's a bit more detail on how to plot a polygon that masks everything outside of it over the current plot. Apparently, there isn't a better way to clip contour plots (That I could find, anyway...).

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()

Clipped contour plot

半衬遮猫 2024-09-18 07:39:03

注意:此答案使用 MATLAB 语法,因为该问题最初是这样标记的。但是,即使您在 Python 中使用 matplotlib,即使语法略有不同,概念也应该是相同的。

您可以选择的一个选项是制作一个看起来具有它上面有一个洞,但实际上只有它的两个边缘包裹着一个空的空间并相互接触。您可以通过创建一组围绕圆边缘进行跟踪的 xy 坐标来实现此目的,然后从圆边缘跟踪到边界正方形的边缘,然后沿着该正方形的边缘追踪,并沿着同一条线回到圆形边缘。这是一个带有单位圆和以原点为中心的 4 x 4 正方形的示例:

theta = linspace(0,2*pi,100);      %# A vector of 100 angles from 0 to 2*pi
xCircle = cos(theta);              %# x coordinates for circle
yCircle = sin(theta);              %# y coordinates for circle
xSquare = [2 2 -2 -2 2 2];         %# x coordinates for square
ySquare = [0 -2 -2 2 2 0];         %# y coordinates for square
hp = fill([xCircle xSquare],...    %# Plot the filled polygon
          [yCircle ySquare],'r');
axis equal                         %# Make axes tick marks equal in size

这是您应该看到的图:

alt text

注意右侧连接圆形和正方形边缘的线。这是红色多边形的两条边相遇并相互接触的地方。如果您不希望边缘线可见,可以将其颜色更改为与多边形的填充颜色相同,如下所示:

set(hp,'EdgeColor','r');

Note: This answer uses MATLAB syntax, since the question was originally tagged as such. However, even if you're using matplotlib in Python the concept should be the same even if the syntax is slightly different.

One option you have is to make a polygon that appears to have a hole in it, but really just has two of its edges wrapping around an empty space and touching. You can do this by creating a set of x and y coordinates that track around the edge of the circle, then track from the circle edge to the edge of a bounding square, then track around the edge of that square and back to the circle edge along the same line. Here's an example with a unit circle and a 4 by 4 square centered at the origin:

theta = linspace(0,2*pi,100);      %# A vector of 100 angles from 0 to 2*pi
xCircle = cos(theta);              %# x coordinates for circle
yCircle = sin(theta);              %# y coordinates for circle
xSquare = [2 2 -2 -2 2 2];         %# x coordinates for square
ySquare = [0 -2 -2 2 2 0];         %# y coordinates for square
hp = fill([xCircle xSquare],...    %# Plot the filled polygon
          [yCircle ySquare],'r');
axis equal                         %# Make axes tick marks equal in size

And here is the figure you should see:

alt text

Notice the line on the right joining the edges of the circle and square. This is where two edges of the red polygon meet and touch each other. If you don't want the edge lines to be visible, you can change their color to be the same as the fill color for the polygon like so:

set(hp,'EdgeColor','r');
够钟 2024-09-18 07:39:03

由于这是在谷歌搜索 matplotlib fill Outside 时出现的第一个结果,我将回答标题中提出的内容。

背景

据我了解,matplotlib 不提供填充多边形外部区域的函数,而只能使用 Axes.fill 填充多边形内部的区域。如果我们创建一个包含较小多边形的更大的“外部”多边形,并将这两个多边形连接到一个不会产生任何交叉点的物体中,则可能会“欺骗”matplotlib,使其认为内部多边形是外部多边形的缝隙。如果外部多边形保持在视图限制之外,则这将具有填充内部多边形外部的整个空间的效果。

多边形设置

要记住的一件事是外部多边形的方向,因为连接到外部的通道不应与自身相交。为此,外部多晶硅的方向应与内部多晶硅的方向相反。

自相交path

解决方案

以下函数找到最靠近左下角的内部多边形的点,并在那里插入外部多边形的路径,并使用由向量创建的平行四边形的有符号面积来处理方向对于拼接点和下一个拼接点。

import numpy as np

def concat(*arrs) -> np.ndarray:
    return np.concatenate(tuple(map(np.asarray, arrs)))

def insert_at(outer_arr, arr, n) -> np.ndarray:
    outer_arr = np.asarray(outer_arr)
    prev, post = np.split(outer_arr, (n,))
    return concat(prev, arr, post)

def cross2d(x1, y1, x2, y2):
    return x1*y2-x2*y1

def is_clockwise(x1, y1, x2, y2):
    cp = cross2d(x1, y1, x2, y2)
    return cp < 0 if cp != 0 else None

def fill_outside(x, y, ll, ur, counter_clockwise=None):
    """
    Creates a polygon where x and y form a crevice of an outer
    rectangle with lower left and upper right corners `ll` and `ur`
    respectively. If `counter_clockwise` is `None` then the orientation
    of the outer polygon will be guessed to be the opposite of the
    inner connecting points.
    """
    x = np.asarray(x)
    y = np.asarray(y)
    xmin, ymin = ll
    xmax, ymax = ur
    xmin, ymin = min(xmin, min(x)), min(ymin, min(y))
    xmax, ymax = max(xmax, max(x)), max(ymax, max(y))
    corners = np.array([
        [xmin, ymin],
        [xmin, ymax],
        [xmax, ymax],
        [xmax, ymin],
        [xmin, ymin],
    ])
    lower_left = corners[0]
    # Get closest point to splicing corner
    x_off, y_off = x-lower_left[0], y-lower_left[1]
    closest_n = (x_off**2+y_off**2).argmin()
    # Guess orientation
    p = [x_off[closest_n], y_off[closest_n]]
    try:
        pn = [x_off[closest_n+1], y_off[closest_n+1]]
    except IndexError:
        # wrap around if we're at the end of the array
        pn = [x_off[0], y_off[0]]
    if counter_clockwise is None:
        counter_clockwise = not is_clockwise(*p, *pn)
    corners = corners[::-1] if counter_clockwise else corners
    # Join the arrays
    corners = concat(np.array([[x[closest_n], y[closest_n]]]), corners)
    xs, ys = np.transpose(corners)
    return insert_at(x, xs, closest_n), insert_at(y, ys, closest_n)

示例

在简单三角形外部填充

import matplotlib.pyplot as plt
fig, (ax1, ax2) = plt.subplots(1, 2)
fig.set_figwidth(10)

x = [0, 1, 2]
y = [0, 1, 0]
ll, ur = (-.5, -.25), (2.5, 1.25)
x, y = fill_outside(x, y, ll, ur)
ax1.fill(x, y)
ax1.plot(x, y, c="C1")
ax2.fill(x, y)
ax2.set_xlim((ll[0], ur[0]))
ax2.set_ylim((ll[1], ur[1]))

生成:

三角形外部填充

任意形状外部填充

import numpy as np

def concat(*arrs) -> np.ndarray:
    return np.concatenate(tuple(map(np.asarray, arrs)))

def z_eq_damping(damping, n=100):
    theta = np.arccos(damping)
    u = np.cos(theta)-np.sin(theta)*1j
    x = np.linspace(0, np.pi/u.imag, num=n)
    contour = np.exp(u*x)
    re, im = contour.real, contour.imag
    return concat(re, np.flip(re)), concat(im, np.flip(-im))

fig, (ax1, ax2) = plt.subplots(1, 2)
fig.set_figwidth(10)

x, y = z_eq_damping(.7)
ll, ur = (-1, -1), (1, 1)
x, y = fill_outside(x, y, ll, ur)
ax1.fill(x, y)
ax1.plot(x, y, c="C1")
ax2.fill(x, y)
ax2.set_xlim((ll[0], ur[0]))
ax2.set_ylim((ll[1], ur[1]))

生成:

< img src="https://i.sstatic.net/YTlel.png" alt="填充形状外部">

Since this is the first result that comes up when googling matplotlib fill outside, I'll answer what has been proposed in the title.

Background

From what I understand matplotlib does not provide a function to fill the area outside a polygon, but only inside it with Axes.fill. If we create a bigger "outside" polygon that contains the smaller one, and join the two in a matter that does not create any intersections, it's possible to "fool" matplotlib into thinking the inside polygon is a crevice of the outside polygon. If the outside polygon is kept outside the view limits, then this will have the effect of filling the entire space outside the inner polygon.

polygon setup

One thing to keep in mind is the orientation of the outside polygon, because the channel connecting to the outside should not intersect itself. For this the orientation of the outer poly should be the opposite of the inner poly.

self intersecting path

Solution

The following function finds the points of the inner poly closest to the lower left corner and inserts there the path for the outer poly, taking care of the orientation using the signed area of the parallelogram created by the vectors for the splice point and the next one.

import numpy as np

def concat(*arrs) -> np.ndarray:
    return np.concatenate(tuple(map(np.asarray, arrs)))

def insert_at(outer_arr, arr, n) -> np.ndarray:
    outer_arr = np.asarray(outer_arr)
    prev, post = np.split(outer_arr, (n,))
    return concat(prev, arr, post)

def cross2d(x1, y1, x2, y2):
    return x1*y2-x2*y1

def is_clockwise(x1, y1, x2, y2):
    cp = cross2d(x1, y1, x2, y2)
    return cp < 0 if cp != 0 else None

def fill_outside(x, y, ll, ur, counter_clockwise=None):
    """
    Creates a polygon where x and y form a crevice of an outer
    rectangle with lower left and upper right corners `ll` and `ur`
    respectively. If `counter_clockwise` is `None` then the orientation
    of the outer polygon will be guessed to be the opposite of the
    inner connecting points.
    """
    x = np.asarray(x)
    y = np.asarray(y)
    xmin, ymin = ll
    xmax, ymax = ur
    xmin, ymin = min(xmin, min(x)), min(ymin, min(y))
    xmax, ymax = max(xmax, max(x)), max(ymax, max(y))
    corners = np.array([
        [xmin, ymin],
        [xmin, ymax],
        [xmax, ymax],
        [xmax, ymin],
        [xmin, ymin],
    ])
    lower_left = corners[0]
    # Get closest point to splicing corner
    x_off, y_off = x-lower_left[0], y-lower_left[1]
    closest_n = (x_off**2+y_off**2).argmin()
    # Guess orientation
    p = [x_off[closest_n], y_off[closest_n]]
    try:
        pn = [x_off[closest_n+1], y_off[closest_n+1]]
    except IndexError:
        # wrap around if we're at the end of the array
        pn = [x_off[0], y_off[0]]
    if counter_clockwise is None:
        counter_clockwise = not is_clockwise(*p, *pn)
    corners = corners[::-1] if counter_clockwise else corners
    # Join the arrays
    corners = concat(np.array([[x[closest_n], y[closest_n]]]), corners)
    xs, ys = np.transpose(corners)
    return insert_at(x, xs, closest_n), insert_at(y, ys, closest_n)

Examples

Filling outside a simple triangle

import matplotlib.pyplot as plt
fig, (ax1, ax2) = plt.subplots(1, 2)
fig.set_figwidth(10)

x = [0, 1, 2]
y = [0, 1, 0]
ll, ur = (-.5, -.25), (2.5, 1.25)
x, y = fill_outside(x, y, ll, ur)
ax1.fill(x, y)
ax1.plot(x, y, c="C1")
ax2.fill(x, y)
ax2.set_xlim((ll[0], ur[0]))
ax2.set_ylim((ll[1], ur[1]))

Produces:

outside of triangle filled

Filling outside an arbitrary shape

import numpy as np

def concat(*arrs) -> np.ndarray:
    return np.concatenate(tuple(map(np.asarray, arrs)))

def z_eq_damping(damping, n=100):
    theta = np.arccos(damping)
    u = np.cos(theta)-np.sin(theta)*1j
    x = np.linspace(0, np.pi/u.imag, num=n)
    contour = np.exp(u*x)
    re, im = contour.real, contour.imag
    return concat(re, np.flip(re)), concat(im, np.flip(-im))

fig, (ax1, ax2) = plt.subplots(1, 2)
fig.set_figwidth(10)

x, y = z_eq_damping(.7)
ll, ur = (-1, -1), (1, 1)
x, y = fill_outside(x, y, ll, ur)
ax1.fill(x, y)
ax1.plot(x, y, c="C1")
ax2.fill(x, y)
ax2.set_xlim((ll[0], ur[0]))
ax2.set_ylim((ll[1], ur[1]))

Produces:

filled outside of shape

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