路徑教學#

在您的 Matplotlib 可視化中定義路徑。

所有 matplotlib.patches 物件的底層物件是 Path,它支援標準的 moveto、lineto、curveto 命令集,以繪製由線段和樣條組成的簡單和複合輪廓。Path 是用 (N, 2) 的 (x, y) 頂點陣列和 N 長度的路徑代碼陣列來實例化的。例如,要繪製從 (0, 0) 到 (1, 1) 的單位矩形,我們可以使用此程式碼

import numpy as np

import matplotlib.pyplot as plt

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

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

以下路徑代碼被識別

代碼

頂點

描述

STOP

1 (忽略)

整個路徑結束的標記(目前不需要且被忽略)。

MOVETO

1

拿起筆並移動到給定的頂點。

LINETO

1

從目前位置繪製一條線到給定的頂點。

CURVE3

2:1 個控制點,1 個終點

從目前位置繪製一條二次貝茲曲線,其具有給定的控制點,到給定的終點。

CURVE4

3:2 個控制點,1 個終點

從目前位置繪製一條三次貝茲曲線,其具有給定的控制點,到給定的終點。

CLOSEPOLY

1 (該點被忽略)

繪製一條線段到目前折線的起點。

貝茲曲線範例#

一些路徑組件需要多個頂點來指定它們:例如 CURVE 3 是一個具有一個控制點和一個終點的 貝茲曲線,而 CURVE4 則有三個頂點用於兩個控制點和終點。下面的範例顯示了一個 CURVE4 貝茲樣條 -- 貝茲曲線將包含在起點、兩個控制點和終點的凸包中

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

複合路徑#

matplotlib 中所有簡單的 patch 原語,Rectangle、Circle、Polygon 等,都是用簡單路徑實作的。像 hist()bar() 這樣的繪圖函式,它會建立許多原語,例如,一堆 Rectangle,通常可以使用複合路徑更有效率地實作。 bar 建立一個矩形列表而不是複合路徑的原因主要是歷史性的:Path 程式碼相對較新,並且 bar 早於它。雖然我們現在可以更改它,但它會破壞舊程式碼,因此在這裡,我們將介紹如何建立複合路徑,取代 bar 中的功能,以防您出於效率原因需要在您自己的程式碼中這樣做,例如,您正在建立動畫長條圖。

我們將透過為每個長條圖建立一系列矩形來製作直方圖:矩形寬度是 bin 寬度,矩形高度是該 bin 中資料點的數量。首先,我們將建立一些隨機常態分佈資料並計算直方圖。由於 NumPy 返回 bin 邊緣而不是中心,因此在下面的範例中,bins 的長度比 n 的長度大 1

# histogram our data with numpy
data = np.random.randn(1000)
n, bins = np.histogram(data, 100)

我們現在將提取矩形的角。下面的每個 leftbottom 等陣列都是 len(n),其中 n 是每個長條圖的計數陣列

# 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

現在我們必須建構我們的複合路徑,它將由一系列每個矩形的 MOVETOLINETOCLOSEPOLY 組成。對於每個矩形,我們需要五個頂點:一個用於 MOVETO,三個用於 LINETO,一個用於 CLOSEPOLY。如上表所示,closepoly 的頂點被忽略,但我們仍然需要它來使程式碼與頂點對齊

nverts = nrects*(1+3+1)
verts = np.zeros((nverts, 2))
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

剩下的就是建立路徑,將其附加到 PathPatch,並將其新增到我們的軸

barpath = path.Path(verts, codes)
patch = patches.PathPatch(barpath, facecolor='green',
  edgecolor='yellow', alpha=0.5)
ax.add_patch(patch)
fig, ax = plt.subplots()
# Fixing random state for reproducibility
np.random.seed(19680801)

# histogram our data with numpy
data = np.random.randn(1000)
n, bins = np.histogram(data, 100)

# 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
nrects = len(left)

nverts = nrects*(1+3+1)
verts = np.zeros((nverts, 2))
codes = np.full(nverts, Path.LINETO, dtype=int)
codes[0::5] = Path.MOVETO
codes[4::5] = 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

barpath = Path(verts, codes)
patch = patches.PathPatch(barpath, facecolor='green',
                          edgecolor='yellow', alpha=0.5)
ax.add_patch(patch)

ax.set_xlim(left[0], right[-1])
ax.set_ylim(bottom.min(), top.max())

plt.show()
paths

由 Sphinx-Gallery 產生的圖庫