The following code works. The problem is I dont know exactly why it works. The code draws a circle patch (using PathPatch) with a triangle cutout from the centre. My guess is that the inner triangle is cut out because it is drawn clockwise while the outer circle is drawn counter-clockwise. The triangle would not get cutout if the direction were not reversed. I have not found anything in the documentation about the rule employed. So why does this work?
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.MOVETOvertices = []
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()
Now as a more complicated example, a pentagon is cutout from the main circle and small circles are also cutout from the main circle that partially intersect the pentagon. If the small circles are drawn clockwise, they are filled where they intersect the pentagon and not filled where they do not. This sort of agrees with the rule above. However if they are drawn counter-clockwise, they are completely filled, which does not agree with the rule above.
from matplotlib import pyplot
from matplotlib.path import Path
from matplotlib.patches import PathPatch
import numpyclockwise_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.MOVETOvertices = []
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.MOVETOif 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()