带孔的Matplotlib补丁

Mar*_*ark 5 python matplotlib

以下代码有效。问题是我不知道它为什么起作用。该代码绘制了一个圆形补丁(使用PathPatch),该补丁的中心为三角形。我的猜测是切掉了内部三角形,因为它是顺时针绘制的,而外部圆是逆时针绘制的。如果方向不反向,三角形将不会被切除。我没有在文档中找到有关所使用规则的任何信息。那为什么行得通呢?

from matplotlib import pyplot
from matplotlib.path import Path
from matplotlib.patches import PathPatch
import numpy

#
# draw a triangle within a circle using PathPatch
#
phi = numpy.linspace(0, 2*numpy.pi, 100)
circle = 4 * numpy.exp(1j * phi)
circleV = [[p.real, p.imag] for p in circle]

phi = numpy.linspace(0, 2*numpy.pi, 4)
triangle = 2 * numpy.exp(1j * phi)
triangleV = [[p.real, p.imag] for p in triangle]

circleC = [Path.LINETO for p in circleV]
circleC[0] = Path.MOVETO
triangleC = [Path.LINETO for p in triangleV]
triangleC[0] = Path.MOVETO

vertices = []
vertices.extend(circleV)
vertices.extend(triangleV[::-1])

codes = []
codes.extend(circleC)
codes.extend(triangleC)

path = Path(vertices, codes)
patch = PathPatch(path, facecolor="#aa6677")

fig, ax = pyplot.subplots()
ax.add_patch(patch)
ax.set_xlim([-5, 5])
ax.set_ylim([-5, 5])
ax.set_aspect(1.0)
pyplot.show()
Run Code Online (Sandbox Code Playgroud)

现在作为一个更复杂的示例,从主圆切出一个五边形,从主圆切出一个与五边形部分相交的小圆。如果顺时针绘制小圆圈,则它们在与五边形相交的位置处被填充,而在未与五角形相交的位置处被填充。这种同意上述规则。但是,如果按逆时针方向绘制它们,它们将被完全填充,这与上述规则不符。

from matplotlib import pyplot
from matplotlib.path import Path
from matplotlib.patches import PathPatch
import numpy

clockwise_inner_circles = True

#
# draw a pentagon within a circle using PathPatch
#
phi = numpy.linspace(0, 2*numpy.pi, 100)
circle = 4 * numpy.exp(1j * phi)
circleV = [[p.real, p.imag] for p in circle]

phi = numpy.linspace(0, 2*numpy.pi, 6)
triangle = 2 * numpy.exp(1j * phi)
triangleV = [[p.real, p.imag] for p in triangle]

circleC = [Path.LINETO for p in circleV]
circleC[0] = Path.MOVETO
triangleC = [Path.LINETO for p in triangleV]
triangleC[0] = Path.MOVETO

vertices = []
vertices.extend(circleV)
vertices.extend(triangleV[::-1])

codes = []
codes.extend(circleC)
codes.extend(triangleC)

#
# draw circles in a circular pattern
#
phi = numpy.linspace(0, 2*numpy.pi, 100)
for theta in 2*numpy.pi*numpy.arange(5)/5:
    circle = 2*numpy.exp(1j*theta) + 0.5*numpy.exp(1j*phi)
    circleV = [[p.real, p.imag] for p in circle]
    circleC = [Path.LINETO for p in circleV]
    circleC[0] = Path.MOVETO
    if clockwise_inner_circles:
        vertices.extend(circleV[::-1])
    else:
        vertices.extend(circleV[::1])
    codes.extend(circleC)

path = Path(vertices, codes)
patch = PathPatch(path, facecolor="#aa6677")

fig, ax = pyplot.subplots()
ax.add_patch(patch)
ax.set_xlim([-5, 5])
ax.set_ylim([-5, 5])
ax.set_aspect(1.0)
pyplot.show()
Run Code Online (Sandbox Code Playgroud)

小智 -1

这不是此代码为何有效的答案,但现在https://matplotlib.org/gallery/shapes_and_collections/donut.html中有一个示例代码。这似乎遵循 SVG 实现。