【问题标题】:Matplotlib patch with holes带孔的 Matplotlib 补丁
【发布时间】:2017-01-06 06:47:00
【问题描述】:

以下代码有效。问题是我不知道它为什么会起作用。该代码从中心绘制一个带有三角形切口的圆形补丁(使用 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()

现在作为一个更复杂的示例,从主圆切出五边形,并且从与五边形部分相交的主圆也切出小圆。如果小圆圈是顺时针绘制的,它们在与五边形相交的地方被填充,在不与五边形相交的地方不被填充。这种方式符合上面的规则。但是如果逆时针绘制,则完全填充,不符合上述规则。

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

【问题讨论】:

    标签: python matplotlib


    【解决方案1】:

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

    【讨论】:

    • 不要链接,请在答案中添加相关代码和示例。
    【解决方案2】:

    基于您的第一个示例,我添加了更多的 cmets,这应该很清楚。 PathPath 的关键是获取 verticescodes。有关顶点和代码的更多详细信息可以找到here

    虽然这是一个很老的问题,但我希望我在这里的回答对需要它的人有用。

    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)
    
    ## generate circle vertices --> "circleV"
    circleV = [[p.real, p.imag] for p in circle]
    
    phi = numpy.linspace(0, 2*numpy.pi, 4)
    triangle = 2 * numpy.exp(1j * phi)
    ## generate triangle vertices --> "triangleV"
    triangleV = [[p.real, p.imag] for p in triangle]
    
    # generate codes for patch, "C" means "codes"
    # codes for circle
    circleC = [Path.LINETO for p in circleV]
    circleC[0] = Path.MOVETO
    # codes for triangle
    triangleC = [Path.LINETO for p in triangleV]
    triangleC[0] = Path.MOVETO
    
    # combine vertices
    vertices = []
    vertices.extend(circleV)
    vertices.extend(triangleV[::-1])
    # combine codes
    codes = []
    codes.extend(circleC)
    codes.extend(triangleC)
    
    # create Path object from vertices and codes
    path = Path(vertices, codes)
    # create patch from path
    patch = PathPatch(path, facecolor="#aa6677")
    
    # plot fig and add patch
    fig, ax = pyplot.subplots()
    ax.add_patch(patch)
    ax.set_xlim([-5, 5])
    ax.set_ylim([-5, 5])
    ax.set_aspect(1.0)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-24
      • 2019-02-20
      • 2020-12-11
      • 1970-01-01
      • 2014-03-08
      • 2014-10-30
      • 1970-01-01
      • 2015-04-08
      相关资源
      最近更新 更多