Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ad423bd

Browse files
committed
added path tut
svn path=/branches/v0_99_maint/; revision=7498
1 parent 0473bb1 commit ad423bd

3 files changed

Lines changed: 230 additions & 0 deletions

File tree

doc/pyplots/compound_path_demo.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import numpy as np
2+
3+
import matplotlib.pyplot as plt
4+
import matplotlib.patches as patches
5+
import matplotlib.path as path
6+
7+
fig = plt.figure()
8+
ax = fig.add_subplot(111)
9+
10+
# histogram our data with numpy
11+
data = np.random.randn(1000)
12+
n, bins = np.histogram(data, 100)
13+
14+
# get the corners of the rectangles for the histogram
15+
left = np.array(bins[:-1])
16+
right = np.array(bins[1:])
17+
bottom = np.zeros(len(left))
18+
top = bottom + n
19+
nrects = len(left)
20+
21+
nverts = nrects*(1+3+1)
22+
verts = np.zeros((nverts, 2))
23+
codes = np.ones(nverts, int) * path.Path.LINETO
24+
codes[0::5] = path.Path.MOVETO
25+
codes[4::5] = path.Path.CLOSEPOLY
26+
verts[0::5,0] = left
27+
verts[0::5,1] = bottom
28+
verts[1::5,0] = left
29+
verts[1::5,1] = top
30+
verts[2::5,0] = right
31+
verts[2::5,1] = top
32+
verts[3::5,0] = right
33+
verts[3::5,1] = bottom
34+
35+
barpath = path.Path(verts, codes)
36+
patch = patches.PathPatch(barpath, facecolor='green', edgecolor='yellow', alpha=0.5)
37+
ax.add_patch(patch)
38+
39+
ax.set_xlim(left[0], right[-1])
40+
ax.set_ylim(bottom.min(), top.max())
41+
42+
plt.show()

doc/users/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ User's Guide
2525
annotations_guide.rst
2626
legend.rst
2727
transforms_tutorial.rst
28+
path_tutorial.rst
2829
toolkits.rst
2930
screenshots.rst
3031
whats_new.rst

doc/users/path_tutorial.rst

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
.. _path_tutorial:
2+
3+
*************
4+
Path Tutorial
5+
*************
6+
7+
The object underlying all of the :mod:`matplotlib.patch` objects is
8+
the :class:`~matplotlib.path.Path`, which supports the standard set of
9+
moveto, lineto, curveto commands to draw simple and compoud outlines
10+
consisting of line segments and splines. The ``Path`` is instantiated
11+
with a (N,2) array of (x,y) vertices, and a N length array of path
12+
codes. For example to draw the unit rectangle from (0,0) to (1,1), we
13+
could use this code
14+
15+
.. plot::
16+
:include-source:
17+
18+
import matplotlib.pyplot as plt
19+
from matplotlib.path import Path
20+
import matplotlib.patches as patches
21+
22+
verts = [
23+
(0., 0.), # left, bottom
24+
(0., 1.), # left, top
25+
(1., 1.), # right, top
26+
(1., 0.), # right, bottom
27+
(0., 0.), # ignored
28+
]
29+
30+
codes = [Path.MOVETO,
31+
Path.LINETO,
32+
Path.LINETO,
33+
Path.LINETO,
34+
Path.CLOSEPOLY,
35+
]
36+
37+
path = Path(verts, codes)
38+
39+
fig = plt.figure()
40+
ax = fig.add_subplot(111)
41+
patch = patches.PathPatch(path, facecolor='orange', lw=2)
42+
ax.add_patch(patch)
43+
ax.set_xlim(-2,2)
44+
ax.set_ylim(-2,2)
45+
plt.show()
46+
47+
48+
The following path codes are recognized
49+
50+
============== ================================= ====================================================================================================================
51+
Code Vertices Description
52+
============== ================================= ====================================================================================================================
53+
``STOP`` 1 (ignored) A marker for the end of the entire path (currently not required and ignored)
54+
``MOVETO`` 1 Pick up the pen and move to the given vertex.
55+
``LINETO`` 1 Draw a line from the current position to the given vertex.
56+
``CURVE3`` 2 (1 control point, 1 endpoint) Draw a quadratic Bezier curve from the current position, with the given control point, to the given end point.
57+
``CURVE4`` 3 (2 control points, 1 endpoint) Draw a cubic Bezier curve from the current position, with the given control points, to the given end point.
58+
``CLOSEPOLY`` 1 (ignored) Draw a line segment to the start point of the current polyline.
59+
============== ================================= ====================================================================================================================
60+
61+
62+
.. path-curves:
63+
64+
65+
Bezier example
66+
==============
67+
68+
Some of the path components require multiple vertices to specify them:
69+
for example CURVE 3 is a `bezier
70+
<http://en.wikipedia.org/wiki/B%C3%A9zier_curve>`_ curve with one
71+
control point and one end point, and CURVE4 has three vertices for the
72+
two control points and the end point. The example below shows a
73+
CURVE4 Bezier spline -- the bezier curve will be contained in the
74+
convex hul of the start point, the two control points, and the end
75+
point
76+
77+
.. plot::
78+
:include-source:
79+
80+
import matplotlib.pyplot as plt
81+
from matplotlib.path import Path
82+
import matplotlib.patches as patches
83+
84+
verts = [
85+
(0., 0.), # P0
86+
(0.2, 1.), # P1
87+
(1., 0.8), # P2
88+
(0.8, 0.), # P3
89+
]
90+
91+
codes = [Path.MOVETO,
92+
Path.CURVE4,
93+
Path.CURVE4,
94+
Path.CURVE4,
95+
]
96+
97+
path = Path(verts, codes)
98+
99+
fig = plt.figure()
100+
ax = fig.add_subplot(111)
101+
patch = patches.PathPatch(path, facecolor='none', lw=2)
102+
ax.add_patch(patch)
103+
104+
xs, ys = zip(*verts)
105+
ax.plot(xs, ys, 'x--', lw=2, color='black', ms=10)
106+
107+
ax.text(-0.05, -0.05, 'P0')
108+
ax.text(0.15, 1.05, 'P1')
109+
ax.text(1.05, 0.85, 'P2')
110+
ax.text(0.85, -0.05, 'P3')
111+
112+
ax.set_xlim(-0.1, 1.1)
113+
ax.set_ylim(-0.1, 1.1)
114+
plt.show()
115+
116+
.. compound_paths:
117+
118+
Compound paths
119+
==============
120+
121+
All of the simple patch primitives in matplotlib, Rectangle, Circle,
122+
Polygon, etc, are implemented with simple path. Plotting functions
123+
like :meth:`~matplotlib.axes.Axes.hist` and
124+
:meth:`~matplotlib.axes.Axes.bar`, which create a number of
125+
primitives, eg a bunch of Rectangles, can usually be implemented more
126+
efficiently using a compund path. The reason ``bar`` creates a list
127+
of rectangles and not a compound path is largely historical: the
128+
:class:`~matplotlib.path.Path` code is comparatively new and ``bar``
129+
predates it. While we could change it now, it would break old code,
130+
so here we will cover how to create compound paths, replacing the
131+
functionality in bar, in case you need to do so in your own code for
132+
efficiency reasons, eg you are creating an animated bar plot.
133+
134+
We will make the histogram chart by creating a series of rectangles
135+
for each histogram bar: the rectangle width is the bin width and the
136+
rectangle height is the number of datapoints in that bin. First we'll
137+
create some random normally distributed data and compute the
138+
histogram. Because numpy returns the bin edges and not centers, the
139+
length of ``bins`` is 1 greater than the length of ``n`` in the
140+
example below::
141+
142+
# histogram our data with numpy
143+
data = np.random.randn(1000)
144+
n, bins = np.histogram(data, 100)
145+
146+
We'll now extract the corners of the rectangles. Each of the
147+
``left``, ``bottom``, etc, arrays below is ``len(n)``, where ``n`` is
148+
the array of counts for each histogram bar::
149+
150+
# get the corners of the rectangles for the histogram
151+
left = np.array(bins[:-1])
152+
right = np.array(bins[1:])
153+
bottom = np.zeros(len(left))
154+
top = bottom + n
155+
156+
Now we have to construct our compound path, which will consist of a
157+
series of ``MOVETO``, ``LINETO`` and ``CLOSEPOLY`` for each rectangle.
158+
For each rectangle, we need 5 vertices: 1 for the ``MOVETO``, 3 for
159+
the ``LINETO``, and 1 for the ``CLOSEPOLY``. As indicated in the
160+
table above, the vertex for the closepoly is ignored but we still need
161+
it to keep the codes aligned with the vertices::
162+
163+
nverts = nrects*(1+3+1)
164+
verts = np.zeros((nverts, 2))
165+
codes = np.ones(nverts, int) * path.Path.LINETO
166+
codes[0::5] = path.Path.MOVETO
167+
codes[4::5] = path.Path.CLOSEPOLY
168+
verts[0::5,0] = left
169+
verts[0::5,1] = bottom
170+
verts[1::5,0] = left
171+
verts[1::5,1] = top
172+
verts[2::5,0] = right
173+
verts[2::5,1] = top
174+
verts[3::5,0] = right
175+
verts[3::5,1] = bottom
176+
177+
All that remains is to create the path, attach it to a
178+
:class:`~matplotlib.patch.PathPatch`, and ad it to our axes::
179+
180+
barpath = path.Path(verts, codes)
181+
patch = patches.PathPatch(barpath, facecolor='green',
182+
edgecolor='yellow', alpha=0.5)
183+
ax.add_patch(patch)
184+
185+
Here is the result
186+
187+
.. plot:: pyplots/compound_path_demo.py

0 commit comments

Comments
 (0)