# 路徑教程
> 原文:[Path Tutorial](http://matplotlib.org/users/path_tutorial.html)
> 譯者:[飛龍](https://github.com/)
> 協議:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/)
位于所有`matplotlib.patch`對象底層的對象是`Path`,它支持`moveto`,`lineto`,`curveto`命令的標準幾個,來繪制由線段和樣條組成的簡單和復合輪廓。 路徑由`(x,y)`頂點的`(N,2)`數組,以及路徑代碼的長度為 N 的數組實例化。 例如,為了繪制`(0,0)`到`(1,1)`的單位矩形,我們可以使用這個代碼:
```py
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 = plt.figure()
ax = fig.add_subplot(111)
patch = patches.PathPatch(path, facecolor='orange', lw=2)
ax.add_patch(patch)
ax.set_xlim(-2,2)
ax.set_ylim(-2,2)
plt.show()
```

下面的路徑代碼會被接受:
| 代碼 | 頂點 | 描述 |
| --- | --- |
| `STOP` | 1 (被忽略) | 標志整個路徑終點的標記(當前不需要或已忽略) |
| `MOVETO` | 1 | 提起筆并移動到指定頂點 |
| `LINETO` | 1 | 從當前位置向指定頂點畫線 |
| `CURVE3` | 2 (一個控制點,一個終點) | 從當前位置,以給定控制點向給定端點畫貝塞爾曲線 |
| `CURVE4` | 3 (兩個控制點,一個終點) | 從當前位置,以給定控制點向給定端點畫三次貝塞爾曲線 |
| `CLOSEPOLY` | 1 (點自身被忽略) | 向當前折線的起點畫線 |
## 貝塞爾示例
一些路徑組件需要以多個頂點來指定:例如`CURVE3`是具有一個控制點和一個端點的貝塞爾曲線,`CURVE4`具有用做兩個控制點和端點的三個頂點。 下面的示例顯示了`CURVE4`貝塞爾曲線 - 貝塞爾曲線將包含在起始點,兩個控制點和終點的凸包中:
```py
import matplotlib.pyplot as plt
from matplotlib.path import Path
import matplotlib.patches as patches
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 = plt.figure()
ax = fig.add_subplot(111)
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()
```

## 復合路徑
所有在 matplotlib,Rectangle,Circle,Polygon 等中的簡單補丁原語都是用簡單的路徑實現的。通過使用復合路徑,通常可以更有效地實現繪制函數,如`hist()`和`bar()`,它們創建了許多原語,例如一堆`Rectangle`,通常可使用復合路徑來實現。`bar`創建一個矩形列表,而不是一個復合路徑,很大程度上出于歷史原因:路徑代碼是比較新的,`bar `在它之前就存在。雖然我們現在可以改變它,但它會破壞舊的代碼,所以如果你需要為了效率,在你自己的代碼中這樣做,例如,創建動畫條形圖,在這里我們將介紹如何創建復合路徑,替換`bar`中的功能。
我們將通過為每個直方圖的條形創建一系列矩形,來創建直方圖圖表:矩形寬度是條形的寬度,矩形高度是該條形中的數據點數量。首先,我們將創建一些隨機的正態分布數據并計算直方圖。因為 numpy 返回條形邊緣而不是中心,所以下面的示例中`bins`的長度比`n`的長度大 1:
```py
# histogram our data with numpy
data = np.random.randn(1000)
n, bins = np.histogram(data, 100)
```
我們現在將提取矩形的角。 下面的每個`left`,`bottom`等數組長度為`len(n)`,其中`n`是每個直方圖條形的計數數組:
```py
# 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`和`CLOSEPOLY`組成。 對于每個矩形,我們需要 5 個頂點:一個代表`MOVETO`,三個代表`LINETO`,一個代表`CLOSEPOLY`。 如上表所示,`closepoly`的頂點被忽略,但我們仍然需要它來保持代碼與頂點對齊:
```py
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`,將其添加到我們的軸域:
```py
barpath = path.Path(verts, codes)
patch = patches.PathPatch(barpath, facecolor='green',
edgecolor='yellow', alpha=0.5)
ax.add_patch(patch)
```
結果為:
