Matplotlib Advanced Path Tutorial

Path Tutorial

所有 patches 对象的基础就是 Path 对象
Path 初始化为 一个 (N, 2)的(x, y)顶点数组, 和一个长度为 N 的路径指令(path codes).

import matplotlib.pyplot as plt
from matplotlib.path import Path
import matplotlib.patches as patches

verts = [
   (0., 0.),  # left, bottom
   (0., 1.),  # left, top
   (1., 1.),  # right, top
   (1., 0.),  # right, bottom
   (0., 0.),  # ignored
]

codes = [
    Path.MOVETO,
    Path.LINETO,
    Path.LINETO,
    Path.LINETO,
    Path.CLOSEPOLY,
]

path = Path(verts, codes)

fig, ax = plt.subplots()
patch = patches.PathPatch(path, facecolor='orange', lw=2)
ax.add_patch(patch)
ax.set_xlim(-2, 2)
ax.set_ylim(-2, 2)
plt.show()

折线可以不在最后写上起始点, 但是 codes 必须在最后加上 Path.CLOSEPOLY.

CodeVerticesDescriptionValue
STOP1 (ignored)A marker for the end of the entire path (currently not required and ignored).0
MOVETO1Pick up the pen and move to the given vertex.1
LINETO1Draw a line from the current position to the given vertex.2
CURVE32: 1 control point, 1 end pointDraw a quadratic Bézier curve from the current position, with the given control point, to the given end point.3
CURVE43: 2 control points, 1 end pointDraw a cubic Bézier curve from the current position, with the given control points, to the given end point.4
CLOSEPOLY1 (the point is ignored)Draw a line segment to the start point of the current polyline.79

Bézier example

某些路径组件需要多个顶点来指定, 例如 CURVE 3 是一个贝塞尔曲线, 需要一个控制点和一个结束点, CURVE 4 需要两个控制点和一个结束点.
下例是 CURVE 4 贝塞尔样条(spline) 即贝塞尔曲线会被局限在由一个起点, 两个控制点, 一个终点组成的凸包上.

verts = [
   (0., 0.),   # P0
   (0.2, 1.),  # P1
   (1., 0.8),  # P2
   (0.8, 0.),  # P3
]

codes = [
    Path.MOVETO,
    Path.CURVE4,
    Path.CURVE4,
    Path.CURVE4,
]

path = Path(verts, codes)

fig, ax = plt.subplots()
patch = patches.PathPatch(path, facecolor='none', lw=2)
ax.add_patch(patch)

xs, ys = zip(*verts)
ax.plot(xs, ys, 'x--', lw=2, color='black', ms=10)

ax.text(-0.05, -0.05, 'P0')
ax.text(0.15, 1.05, 'P1')
ax.text(1.05, 0.85, 'P2')
ax.text(0.85, -0.05, 'P3')

ax.set_xlim(-0.1, 1.1)
ax.set_ylim(-0.1, 1.1)
plt.show()

Compound paths

复合路径
所有的简单 patch 原语例如 Rectangle, Circle, Polygon 都是由简单路径实现的. 但是 bar 会创建一个 Rectangle 列表而不是复合路径是有历史原因的, 因为 Path 指令相对较新, 而 bar 要早于它. 如果你要是为了效率的话, 也可以用复合路径.

我们先创建一些随机正态分布的数据, 然后计算直方图.

# histogram our data with numpy
import numpy as np
data = np.random.randn(1000)
n, bins = np.histogram(data, 100)
'''
np.histogram(
    a,
    bins=10, # bins 是给定范围的条的数量
    range=None,
    normed=None,
    weights=None,
    density=None,
)
'''
# n 每个区间的数量
# bins 区间划分
# len(bins) # numpy 会返回bin的边缘而不是中点所以bins个数会比n多一个 
# 101

提取矩形的角

# get the corners of the rectangles for the histogram
left = np.array(bins[:-1]) # 左下角的值, 
right = np.array(bins[1:]) # 右下角
bottom = np.zeros(len(left)) # 底部
top = bottom + n # 顶部

构建复合路径
由于每个矩形都需要一个 MOVETO, 三个 LINETO, 一个 COLSEPOLY , 所以每个矩形都需要五个顶点. 为 CLOSEPOLY 的顶点可以忽略, 但是我们还是需要让指令和顶点对上.
先创建全为 0 的顶点后续更改.
path.Path.LINETO 本质是 int 所以相乘没有问题.

nrects = len(left)
nverts = nrects*(1+3+1)
verts = np.zeros((nverts, 2))
# 先将所有codes都设置为LINETO 然后再改
codes = np.ones(nverts, int) * path.Path.LINETO
codes[0::5] = path.Path.MOVETO
codes[4::5] = path.Path.CLOSEPOLY

# 设置每个矩形左下角坐标
verts[0::5, 0] = left
verts[0::5, 1] = bottom
# 设置每个矩形左上角坐标
verts[1::5, 0] = left
verts[1::5, 1] = top

verts[2::5, 0] = right
verts[2::5, 1] = top

verts[3::5, 0] = right
verts[3::5, 1] = bottom

Path 初始化为 一个 (N, 2)的(x, y)顶点数组, 和一个长度为 N 的路径指令(path codes).
最后将路径添加到 PathPatch 里, 再加到 axes.

barpath = path.Path(verts, codes)
patch = patches.PathPatch(barpath, facecolor='green',
  edgecolor='yellow', alpha=0.5)
ax.add_patch(patch)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值