虽然我们可以使用函数来生成点,然后再通过画直线的函数把点连接起来,形成相应的图形,但是这样的绘制的速度比较慢,另外也会遇到各种不同图形的挑战。因此使用matplotlib里的patches模块,就可以去掉这些担忧。
在学习这个新模块时,先来一个简单的例子,比如画一个圆如下:
画这个圆时,调用了函数mpatches.Circle(),它是来自模块matplotlib.patches,通过下面的代码来引入:
import matplotlib.patches as mpatches
这时就把它命名为mpatches,就可以通过mpatches来访问这个模块里所有函数和名称了。
host.set_aspect("equal")
在这里又看到这行代码,你一定会想起前面学习过的,它就是用来指定X轴和Y轴的比例,如果不设置这行代码,你就会发现画出来的圆并不是圆形,而是椭圆。因此这里也得使用这行代码,才看到圆形图形是圆的。
cicle = mpatches.Circle(xy = (30, 30), # 圆心坐标
radius = 20, # 半径
fc = 'gray', # facecolor
ec = 'cornflowerblue', # 浅蓝色
)
这行代码就是生成一个圆形图形,mpatches.Circle函数定义如下:
class matplotlib.patches.Circle(xy, radius=5, **kwargs)
可以看到mpatches模块里都是使用类来描述这些几何图形,比如圆(Circle),椭圆(Ellipse),矩形(Rectangle),圆弧(Arc),楔形(Wedge)等等。
在圆的构造函数里,可以看到它参数定义,其意义如下:
-
xy: 表示圆心的位置。
-
radius:表示半径的长度。
-
facecolor or fc:表示圆内的颜色。
-
edgecolor or ec:表示圆弧线的颜色。
其实还有很多其它参数,这里就不介绍了。通过上面的例子,就可以学会使用模块patches的类。整个例子的代码如下:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
#
fig, host = plt.subplots() #创建子图
host.grid(False)
host.set_aspect("equal")
host.set_xlim(0, 100)
host.set_ylim(0, 100)
#
cicle = mpatches.Circle(xy = (30, 30), # 圆心坐标
radius = 20, # 半径
fc = 'gray', # facecolor
ec = 'cornflowerblue', # 浅蓝色
)
host.add_patch(p = cicle)
plt.show()
下面再介绍一个使用其它图形的例子:
其实只要理解第一个例子的内容,这个例子的内容也是很容易理解的,下面简单地介绍一下代码:
grid = np.mgrid[0.2:0.8:3j, 0.2:0.8:3j].reshape(2, -1).T
这行代码主要用来创建一个3X3的九宫格的坐标,以便画出9种图形。
def label(xy, text):
y = xy[1] - 0.15 # 偏移一下Y轴的坐标,以便在图形下面标记
plt.text(xy[0], y, text, ha="center", family='sans-serif', size=14)
这个是对每个图形写上标记用的。
这个例子的完整代码如下:
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.path as mpath
import matplotlib.lines as mlines
import matplotlib.patches as mpatches
from matplotlib.collections import PatchCollection
def label(xy, text):
y = xy[1] - 0.15 # 偏移一下Y轴的坐标,以便在图形下面标记
plt.text(xy[0], y, text, ha="center", family='sans-serif', size=14)
fig, ax = plt.subplots()
# 创建 3x3 网格坐标
grid = np.mgrid[0.2:0.8:3j, 0.2:0.8:3j].reshape(2, -1).T
patches = []
# 添加一个圆
circle = mpatches.Circle(grid[0], 0.1, ec="none")
patches.append(circle)
label(grid[0], "Circle")
# 添加一个长方形
rect = mpatches.Rectangle(grid[1] - [0.025, 0.05], 0.05, 0.1, ec="none")
patches.append(rect)
label(grid[1], "Rectangle")
# 添加一个扇形
wedge = mpatches.Wedge(grid[2], 0.1, 30, 270, ec="none")
patches.append(wedge)
label(grid[2], "Wedge")
# 添加一个多边形
polygon = mpatches.RegularPolygon(grid[3], 5, 0.1)
patches.append(polygon)
label(grid[3], "Polygon")
# 添加一个椭圆
ellipse = mpatches.Ellipse(grid[4], 0.2, 0.1)
patches.append(ellipse)
label(grid[4], "Ellipse")
# 添加一个箭头
arrow = mpatches.Arrow(grid[5, 0] - 0.05, grid[5, 1] - 0.05, 0.1, 0.1,
width=0.1)
patches.append(arrow)
label(grid[5], "Arrow")
# 添加一个路径对象
Path = mpath.Path
path_data = [
(Path.MOVETO, [0.018, -0.11]),
(Path.CURVE4, [-0.031, -0.051]),
(Path.CURVE4, [-0.115, 0.073]),
(Path.CURVE4, [-0.03, 0.073]),
(Path.LINETO, [-0.011, 0.039]),
(Path.CURVE4, [0.043, 0.121]),
(Path.CURVE4, [0.075, -0.005]),
(Path.CURVE4, [0.035, -0.027]),
(Path.CLOSEPOLY, [0.018, -0.11])]
codes, verts = zip(*path_data)
path = mpath.Path(verts + grid[6], codes)
patch = mpatches.PathPatch(path)
patches.append(patch)
label(grid[6], "PathPatch")
# 添加一个盒子,圆角
fancybox = mpatches.FancyBboxPatch(
grid[7] - [0.025, 0.05], 0.05, 0.1,
boxstyle = mpatches.BoxStyle("Round", pad=0.02))
patches.append(fancybox)
label(grid[7], "FancyBboxPatch")
# 添加2D的线
x, y = ([-0.06, 0.0, 0.1], [0.05, -0.05, 0.05])
line = mlines.Line2D(x + grid[8, 0], y + grid[8, 1], lw=5., alpha=0.3)
label(grid[8], "Line2D")
colors = np.linspace(0, 1, len(patches))
collection = PatchCollection(patches, cmap=plt.cm.hsv, alpha=0.3)
collection.set_array(colors)
ax.add_collection(collection)
ax.add_line(line)
plt.axis('equal')
plt.axis('off')
plt.tight_layout()
plt.show()