如何在matplotlib中绘制填充弧

2024-09-28 23:16:08 发布

您现在位置:Python中文网/ 问答频道 /正文

在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表示填充弧是不可能的。 画一张最好的方法是什么?


Tags: 代码importmatplotlibaspltax直线pac
3条回答

您可以使用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

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

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

高温高压

@jeanrjc's solution几乎可以让您到达目的地,但它添加了一个完全不必要的白色三角形,这也将隐藏其他对象(参见下图,版本1)。

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

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

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

相关问题 更多 >