如何在matplotlib中绘制填充弧

时间:2015-06-04 11:14:40

标签: python matplotlib

在matplotlib中,我想绘制一个看起来像这样的填充弧:

Filled Arc Example

以下代码会产生未填充的线弧:

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

documentation表示无法填充弧线。 绘制一个最好的方法是什么?

5 个答案:

答案 0 :(得分:5)

@jeanrjc's solution几乎可以让你到达那里,但它增加了一个完全不必要的白色三角形,它也会隐藏其他物体(见下图,版本1)。

这是一种更简单的方法,它只添加弧的多边形:

基本上我们会在圆的边缘(从pointstheta1)创建一系列点(theta2)。这已经足够了,因为我们可以在close构造函数中设置Polygon标志,该标志将添加从最后一个到第一个点的线(创建一个闭合弧)。

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

然后我们应用它:

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

结果(第2版):

enter image description here

答案 1 :(得分:4)

您可以使用fill_between来实现此目标

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

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

 r=2.
 yoff=-1
 x=np.arange(-1.,1.05,0.05)
 y=np.sqrt(r-x**2)+yoff

 ax.fill_between(x,y,0)

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

使用r和yoff来移动弧

enter image description here

修改

好的,你想要能够绘制任意角度吗?你只需要找到和弦的方程式,而不是像上面那样使用扁平线。这是一个功能:

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

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

col='rgbkmcyk'

def filled_arc(center,r,theta1,theta2):

    # Range of angles
    phi=np.linspace(theta1,theta2,100)

    # x values
    x=center[0]+r*np.sin(np.radians(phi))

    # y values. need to correct for negative values in range theta=90--270
    yy = np.sqrt(r-x**2)
    yy = [-yy[i] if phi[i] > 90 and phi[i] < 270 else yy[i] for i in range(len(yy))]

    y = center[1] + np.array(yy)

    # Equation of the chord
    m=(y[-1]-y[0])/(x[-1]-x[0])
    c=y[0]-m*x[0]
    y2=m*x+c

    # Plot the filled arc
    ax.fill_between(x,y,y2,color=col[theta1/45])

# Lets plot a whole range of arcs
for i in [0,45,90,135,180,225,270,315]:
    filled_arc([0,0],1,i,i+45)

ax.axis([-2, 2, -2, 2])
ax.set_aspect("equal")
fg.savefig('filled_arc.png')

这是输出:

enter image description here

答案 2 :(得分:3)

你可以绘制一个楔形,然后用三角形隐藏它的一部分:

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

def filled_arc(center, radius, theta1, theta2, ax, color):

    circ = mpatches.Wedge(center, radius, theta1, theta2, fill=True, color=color)
    pt1 = (radius * (np.cos(theta1*np.pi/180.)) + center[0],
           radius * (np.sin(theta1*np.pi/180.)) + center[1])
    pt2 = (radius * (np.cos(theta2*np.pi/180.)) + center[0],
           radius * (np.sin(theta2*np.pi/180.)) + center[1])
    pt3 = center
    pol = mpatches.Polygon([pt1, pt2, pt3], color=ax.get_axis_bgcolor(),
                           ec=ax.get_axis_bgcolor(), lw=2 )
    ax.add_patch(circ)
    ax.add_patch(pol)

然后你可以称之为:

fig, ax = plt.subplots(1,2)
filled_arc((0,0), 1, 45, 135, ax[0], "blue")
filled_arc((0,0), 1, 0, 40, ax[1], "blue")

你得到:

filled_arc

或:

fig, ax = plt.subplots(1, 1)
for i in range(0,360,45):
    filled_arc((0,0), 1, i, i+45, ax, plt.cm.jet(i))

你得到:

enter image description here

HTH

答案 3 :(得分:2)

这是一个更简单的解决方法。在mpatches.Arc命令中使用hatch参数。如果使用影线参数重复符号,则会增加图案的密度。我发现如果你使用6个破折号,' - '或6个点,'。' (其他人也可能会工作),然后根据需要稳固地填充弧线。当我运行这个

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

plt.axes()
pac = mpatches.Arc([0, -2.5], 5, 5, 45, theta1=45, theta2=135, hatch = '......')
plt.gca().add_patch(pac)
pac.set_color('cyan')
plt.axis('equal')
plt.show()

我明白了:

Arc filled with dense dot hatch and rotated 45 degrees just for show

答案 4 :(得分:0)

对于较新的 matplotlib,命令 ax.get_axis_bgcolor() 需要替换为 ax.get_fc()