pythonmatplotlib

How to draw a filled arc in matplotlib


In matplotlib, I would like draw an filled arc which looks like this:

Filled Arc Example

The following code results in an unfilled line arc:

import matplotlib.patches as mpatches
import matplotlib.pyplot as plt

fg, ax = plt.subplots(1, 1)

pac = mpatches.Arc([0, -2.5], 5, 5, angle=0, theta1=45, theta2=135)
ax.add_patch(pac)

ax.axis([-2, 2, -2, 2])
ax.set_aspect("equal")
fg.canvas.draw()

The documentation says that filled arcs are not possible. What would be the best way to draw one?


Solution

  • @jeanrjc's solution almost gets you there, but it adds a completely unnecessary white triangle, which will hide other objects as well (see figure below, version 1).

    This is a simpler approach, which only adds a polygon of the arc:

    Basically we create a series of points (points) along the edge of the circle (from theta1 to theta2). This is already enough, as we can set the close flag in the Polygon constructor which will add the line from the last to the first point (creating a closed arc).

    import matplotlib.patches as mpatches
    import matplotlib.pyplot as plt
    import numpy as np
    
    def arc_patch(center, radius, theta1, theta2, ax=None, resolution=50, **kwargs):
        # make sure ax is not empty
        if ax is None:
            ax = plt.gca()
        # generate the points
        theta = np.linspace(np.radians(theta1), np.radians(theta2), resolution)
        points = np.vstack((radius*np.cos(theta) + center[0], 
                            radius*np.sin(theta) + center[1]))
        # build the polygon and add it to the axes
        poly = mpatches.Polygon(points.T, closed=True, **kwargs)
        ax.add_patch(poly)
        return poly
    

    And then we apply it:

    fig, ax = plt.subplots(1,2)
    
    # @jeanrjc solution, which might hide other objects in your plot
    ax[0].plot([-1,1],[1,-1], 'r', zorder = -10)
    filled_arc((0.,0.3), 1, 90, 180, ax[0], 'blue')
    ax[0].set_title('version 1')
    
    # simpler approach, which really is just the arc
    ax[1].plot([-1,1],[1,-1], 'r', zorder = -10)
    arc_patch((0.,0.3), 1, 90, 180, ax=ax[1], fill=True, color='blue')
    ax[1].set_title('version 2')
    
    # axis settings
    for a in ax:
        a.set_aspect('equal')
        a.set_xlim(-1.5, 1.5)
        a.set_ylim(-1.5, 1.5)
    
    plt.show()
    

    Result (version 2):

    enter image description here