Skip to content

Enable choosing the even-odd rule for filling shapes - #32253

Draft
ayshih wants to merge 2 commits into
matplotlib:mainfrom
ayshih:fill_rule
Draft

Enable choosing the even-odd rule for filling shapes#32253
ayshih wants to merge 2 commits into
matplotlib:mainfrom
ayshih:fill_rule

Conversation

@ayshih

@ayshih ayshih commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

PR summary

This PR enables choosing the even-odd rule for filling a shape, as an alternative to the existing behavior of the non-zero winding rule. The choice of fill rule is implemented as an Patch property, and defaults to the non-zero winding rule. All backends are supported.

Examples

Agg
agg

Cairo
cairo

SVG
Figure_1

PDF
Figure_1.pdf

PGF
Figure_1.pgf.pdf

PS
Figure_1.ps.pdf

Generating script

import matplotlib
#matplotlib.use('TkCairo')

import numpy as np

import matplotlib.pyplot as plt
from matplotlib.patches import PathPatch, Polygon
from matplotlib.path import Path

deg = np.arange(6) * 144
x = np.sin(deg * np.pi / 180)
y = np.cos(deg * np.pi / 180)
star = np.stack([x, y], axis=1)

square_vertices = np.array([[-1, -1], [-1, 1], [1, 1], [1, -1], [-1, -1]])
square_codes = [Path.MOVETO, Path.LINETO, Path.LINETO, Path.LINETO, Path.LINETO]

fig, axs = plt.subplots(1, 2, figsize=(4, 5))

for ax, fill_rule in zip(axs, ['nonzero', 'evenodd']):
    stroked_star = Polygon(star + [0, 4], closed=False, ec='b', lw=5, ls=(0, (5, 1)),
                           fc='r', hatch='xx', fill_rule=fill_rule)
    ax.add_patch(stroked_star)

    nonstroked_star = Polygon(star + [0, 2], closed=False, ec='none',
                              fc='r', hatch='xx', fill_rule=fill_rule)
    ax.add_patch(nonstroked_star)

    squares = Path(np.vstack([square_vertices * 0.9,
                              square_vertices / 3 + [0, 0.5],
                              square_vertices / 3 + [0.3, 0],
                              (square_vertices / 3)[::-1, :] + [0, -0.5]]),
                   square_codes * 4)
    
    ax.add_patch(PathPatch(squares, fc='g', ec='m', fill_rule=fill_rule))

    ax.set_xlim(-1, 1)
    ax.set_ylim(-1, 5.1)
    ax.set_aspect('equal')
    ax.set_axis_off()
    ax.set_title(f'fill_rule={fill_rule}')

plt.show()

AI Disclosure

No AI was used

PR quality check

  • Use an expressive title, e.g. "Fix title font property precedence"
  • New and changed code is tested
  • Plotting related features are demonstrated in an example
  • New features and API changes have release notes
  • Documentation complies with general and docstring guidelines

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant