Revision: 6664
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6664&view=rev
Author: leejjoon
Date: 2008-12-18 15:38:33 +0000 (Thu, 18 Dec 2008)
Log Message:
-----------
add new arrow style (a line + filled triangles)
Modified Paths:
--------------
trunk/matplotlib/CHANGELOG
trunk/matplotlib/examples/pylab_examples/fancyarrow_demo.py
trunk/matplotlib/examples/pylab_examples/fancybox_demo2.py
trunk/matplotlib/lib/matplotlib/bezier.py
trunk/matplotlib/lib/matplotlib/patches.py
Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG 2008-12-18 13:47:19 UTC (rev 6663)
+++ trunk/matplotlib/CHANGELOG 2008-12-18 15:38:33 UTC (rev 6664)
@@ -1,3 +1,5 @@
+2008-12-18 add new arrow style, a line + filled triangles. -JJL
+
2008-12-18 Fix bug where a line with NULL data limits prevents
subsequent data limits from calculating correctly - MGD
Modified: trunk/matplotlib/examples/pylab_examples/fancyarrow_demo.py
===================================================================
--- trunk/matplotlib/examples/pylab_examples/fancyarrow_demo.py 2008-12-18
13:47:19 UTC (rev 6663)
+++ trunk/matplotlib/examples/pylab_examples/fancyarrow_demo.py 2008-12-18
15:38:33 UTC (rev 6664)
@@ -3,23 +3,26 @@
styles = mpatches.ArrowStyle.get_styles()
-figheight = (len(styles)+.5)
-fig1 = plt.figure(1, (4, figheight))
-fontsize = 0.3 * fig1.dpi
+ncol=2
+nrow = len(styles) // ncol + 1
+figheight = (nrow+0.5)
+fig1 = plt.figure(1, (4.*ncol/1.5, figheight/1.5))
+fontsize = 0.2 * 70
ax = fig1.add_axes([0, 0, 1, 1], frameon=False, aspect=1.)
-ax.set_xlim(0, 4)
+ax.set_xlim(0, 4*ncol)
ax.set_ylim(0, figheight)
for i, (stylename, styleclass) in enumerate(sorted(styles.items())):
- y = (float(len(styles)) -0.25 - i) # /figheight
- p = mpatches.Circle((3.2, y), 0.2, fc="w")
+ x = 3.2 + (i//nrow)*4
+ y = (figheight - 0.7 - i%nrow) # /figheight
+ p = mpatches.Circle((x, y), 0.2, fc="w")
ax.add_patch(p)
- ax.annotate(stylename, (3.2, y),
- (2., y),
+ ax.annotate(stylename, (x, y),
+ (x-1.2, y),
#xycoords="figure fraction", textcoords="figure fraction",
ha="right", va="center",
size=fontsize,
Modified: trunk/matplotlib/examples/pylab_examples/fancybox_demo2.py
===================================================================
--- trunk/matplotlib/examples/pylab_examples/fancybox_demo2.py 2008-12-18
13:47:19 UTC (rev 6663)
+++ trunk/matplotlib/examples/pylab_examples/fancybox_demo2.py 2008-12-18
15:38:33 UTC (rev 6664)
@@ -4,8 +4,8 @@
styles = mpatch.BoxStyle.get_styles()
figheight = (len(styles)+.5)
-fig1 = plt.figure(1, (4, figheight))
-fontsize = 0.4 * fig1.dpi
+fig1 = plt.figure(1, (4/1.5, figheight/1.5))
+fontsize = 0.3 * 72
for i, (stylename, styleclass) in enumerate(styles.items()):
fig1.text(0.5, (float(len(styles)) - 0.5 - i)/figheight, stylename,
@@ -15,3 +15,4 @@
bbox=dict(boxstyle=stylename, fc="w", ec="k"))
plt.draw()
plt.show()
+
Modified: trunk/matplotlib/lib/matplotlib/bezier.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/bezier.py 2008-12-18 13:47:19 UTC (rev
6663)
+++ trunk/matplotlib/lib/matplotlib/bezier.py 2008-12-18 15:38:33 UTC (rev
6664)
@@ -468,6 +468,38 @@
+def make_path_regular(p):
+ """
+ fill in the codes if None.
+ """
+ c = p.codes
+ if c is None:
+ c = np.empty(p.vertices.shape, "i")
+ c.fill(Path.LINETO)
+ c[0] = Path.MOVETO
+
+ return Path(p.vertices, c)
+ else:
+ return p
+
+def concatenate_paths(paths):
+ """
+ concatenate list of paths into a single path.
+ """
+
+ vertices = []
+ codes = []
+ for p in paths:
+ p = make_path_regular(p)
+ vertices.append(p.vertices)
+ codes.append(p.codes)
+
+ _path = Path(np.concatenate(vertices),
+ np.concatenate(codes))
+ return _path
+
+
+
if 0:
path = Path([(0, 0), (1, 0), (2, 2)],
[Path.MOVETO, Path.CURVE3, Path.CURVE3])
@@ -476,3 +508,4 @@
ax = gca()
+
Modified: trunk/matplotlib/lib/matplotlib/patches.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/patches.py 2008-12-18 13:47:19 UTC (rev
6663)
+++ trunk/matplotlib/lib/matplotlib/patches.py 2008-12-18 15:38:33 UTC (rev
6664)
@@ -2176,6 +2176,7 @@
from matplotlib.bezier import get_intersection, inside_circle, get_parallels
from matplotlib.bezier import make_wedged_bezier2
from matplotlib.bezier import split_path_inout, get_cos_sin
+from matplotlib.bezier import make_path_regular, concatenate_paths
class ConnectionStyle(_Style):
@@ -2627,12 +2628,15 @@
def transmute(self, path, mutation_size, linewidth):
"""
The transmute method is a very core of the ArrowStyle
- class and must be overriden in the subclasses. It receives the
- path object along which the arrow will be drawn, and the
- mutation_size, with which the amount arrow head and etc. will
- be scaled. It returns a Path instance. The linewidth may be
- used to adjust the the path so that it does not pass beyond
- the given points.
+ class and must be overriden in the subclasses. It receives
+ the path object along which the arrow will be drawn, and
+ the mutation_size, with which the amount arrow head and
+ etc. will be scaled. The linewidth may be used to adjust
+ the the path so that it does not pass beyond the given
+ points. It returns a tuple of a Path instance and a
+ boolean. The boolean value indicate whether the path can
+ be filled or not. The return value can also be a list of paths
+ and list of booleans of a same length.
"""
raise NotImplementedError('Derived must override')
@@ -2646,6 +2650,8 @@
and take care of the aspect ratio.
"""
+ path = make_path_regular(path)
+
if aspect_ratio is not None:
# Squeeze the given height by the aspect_ratio
@@ -2654,12 +2660,19 @@
vertices[:,1] = vertices[:,1] / aspect_ratio
path_shrinked = Path(vertices, codes)
# call transmute method with squeezed height.
- path_mutated, closed = self.transmute(path_shrinked, linewidth,
- mutation_size)
- vertices, codes = path_mutated.vertices, path_mutated.codes
- # Restore the height
- vertices[:,1] = vertices[:,1] * aspect_ratio
- return Path(vertices, codes), closed
+ path_mutated, fillable = self.transmute(path_shrinked,
+ linewidth,
+ mutation_size)
+ if cbook.iterable(fillable):
+ path_list = []
+ for p in zip(path_mutated):
+ v, c = p.vertices, p.codes
+ # Restore the height
+ v[:,1] = v[:,1] * aspect_ratio
+ path_list.append(Path(v, c))
+ return path_list, fillable
+ else:
+ return path_mutated, fillable
else:
return self.transmute(path, mutation_size, linewidth)
@@ -2669,21 +2682,24 @@
"""
A simple arrow which will work with any path instance. The
returned path is simply concatenation of the original path + at
- most two paths representing the arrow at the begin point and the
- at the end point. The returned path is not closed and only meant
- to be stroked.
+ most two paths representing the arrow head at the begin point and the
+ at the end point. The arrow heads can be either open or closed.
"""
def __init__(self, beginarrow=None, endarrow=None,
+ fillbegin=False, fillend=False,
head_length=.2, head_width=.1):
"""
The arrows are drawn if *beginarrow* and/or *endarrow* are
- true. *head_length* and *head_width* determines the size of
- the arrow relative to the *mutation scale*.
+ true. *head_length* and *head_width* determines the size
+ of the arrow relative to the *mutation scale*. The
+ arrowhead at the begin (or end) is closed if fillbegin (or
+ fillend) is True.
"""
self.beginarrow, self.endarrow = beginarrow, endarrow
self.head_length, self.head_width = \
head_length, head_width
+ self.fillbegin, self.fillend = fillbegin, fillend
super(ArrowStyle._Curve, self).__init__()
@@ -2783,18 +2799,35 @@
# this simple code will not work if ddx, ddy is greater than
# separation bettern vertices.
- vertices = np.concatenate([verticesA + [(x0+ddxA, y0+ddyA)],
- path.vertices[1:-1],
- [(x3+ddxB, y3+ddyB)] + verticesB])
- codes = np.concatenate([codesA,
- path.codes,
- codesB])
+ _path = [Path(np.concatenate([[(x0+ddxA, y0+ddyA)],
+ path.vertices[1:-1],
+ [(x3+ddxB, y3+ddyB)]]),
+ path.codes)]
+ _fillable = [False]
+
+ if self.beginarrow:
+ if self.fillbegin:
+ p = np.concatenate([verticesA, [verticesA[0],
verticesA[0]], ])
+ c = np.concatenate([codesA, [Path.LINETO,
Path.CLOSEPOLY]])
+ _path.append(Path(p, c))
+ _fillable.append(True)
+ else:
+ _path.append(Path(verticesA, codesA))
+ _fillable.append(False)
+
+ if self.endarrow:
+ if self.fillend:
+ _fillable.append(True)
+ p = np.concatenate([verticesB, [verticesB[0],
verticesB[0]], ])
+ c = np.concatenate([codesB, [Path.LINETO,
Path.CLOSEPOLY]])
+ _path.append(Path(p, c))
+ else:
+ _fillable.append(False)
+ _path.append(Path(verticesB, codesB))
+
+ return _path, _fillable
- p = Path(vertices, codes)
- return p, False
-
-
class Curve(_Curve):
"""
A simple curve without any arrow head.
@@ -2872,6 +2905,73 @@
_style_list["<->"] = CurveAB
+
+ class CurveFilledA(_Curve):
+ """
+ An arrow with filled triangle head at the begin.
+ """
+
+ def __init__(self, head_length=.4, head_width=.2):
+ """
+ *head_length*
+ length of the arrow head
+
+ *head_width*
+ width of the arrow head
+ """
+
+ super(ArrowStyle.CurveFilledA, self).__init__( \
+ beginarrow=True, endarrow=False,
+ fillbegin=True, fillend=False,
+ head_length=head_length, head_width=head_width )
+
+ _style_list["<|-"] = CurveFilledA
+
+
+ class CurveFilledB(_Curve):
+ """
+ An arrow with filled triangle head at the end.
+ """
+
+ def __init__(self, head_length=.4, head_width=.2):
+ """
+ *head_length*
+ length of the arrow head
+
+ *head_width*
+ width of the arrow head
+ """
+
+ super(ArrowStyle.CurveFilledB, self).__init__( \
+ beginarrow=False, endarrow=True,
+ fillbegin=False, fillend=True,
+ head_length=head_length, head_width=head_width )
+
+ _style_list["-|>"] = CurveFilledB
+
+
+ class CurveFilledAB(_Curve):
+ """
+ An arrow with filled triangle heads both at the begin and the end
point.
+ """
+
+ def __init__(self, head_length=.4, head_width=.2):
+ """
+ *head_length*
+ length of the arrow head
+
+ *head_width*
+ width of the arrow head
+ """
+
+ super(ArrowStyle.CurveFilledAB, self).__init__( \
+ beginarrow=True, endarrow=True,
+ fillbegin=True, fillend=True,
+ head_length=head_length, head_width=head_width )
+
+ _style_list["<|-|>"] = CurveFilledAB
+
+
class _Bracket(_Base):
def __init__(self, bracketA=None, bracketB=None,
@@ -3201,6 +3301,7 @@
+
class FancyArrowPatch(Patch):
"""
A fancy arrow patch. It draws an arrow using the :class:ArrowStyle.
@@ -3423,9 +3524,14 @@
get_path_in_displaycoord() medthod to retrieve the arrow path
in the disaply coord.
"""
- _path = self.get_path_in_displaycoord()
+ _path, fillable = self.get_path_in_displaycoord()
+
+ if cbook.iterable(fillable):
+ _path = concatenate_paths(_path)
+
return self.get_transform().inverted().transform_path(_path)
+
def get_path_in_displaycoord(self):
"""
Return the mutated path of the arrow in the display coord
@@ -3445,16 +3551,16 @@
- _path, closed = self.get_arrowstyle()(_path,
- self.get_mutation_scale(),
- self.get_linewidth(),
- self.get_mutation_aspect()
- )
+ _path, fillable = self.get_arrowstyle()(_path,
+ self.get_mutation_scale(),
+ self.get_linewidth(),
+ self.get_mutation_aspect()
+ )
- if not closed:
- self.fill = False
+ #if not fillable:
+ # self.fill = False
- return _path
+ return _path, fillable
@@ -3463,12 +3569,7 @@
#renderer.open_group('patch')
gc = renderer.new_gc()
- fill_orig = self.fill
- path = self.get_path_in_displaycoord()
- affine = transforms.IdentityTransform()
-
-
if cbook.is_string_like(self._edgecolor) and
self._edgecolor.lower()=='none':
gc.set_linewidth(0)
else:
@@ -3494,8 +3595,22 @@
gc.set_hatch(self._hatch )
- renderer.draw_path(gc, path, affine, rgbFace)
+ path, fillable = self.get_path_in_displaycoord()
- self.fill = fill_orig
+ if not cbook.iterable(fillable):
+ path = [path]
+ fillable = [fillable]
+
- #renderer.close_group('patch')
+ affine = transforms.IdentityTransform()
+
+ renderer.open_group('patch', self.get_gid())
+
+ for p, f in zip(path, fillable):
+ if f:
+ renderer.draw_path(gc, p, affine, rgbFace)
+ else:
+ renderer.draw_path(gc, p, affine, None)
+
+
+ renderer.close_group('patch')
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
------------------------------------------------------------------------------
SF.Net email is Sponsored by MIX09, March 18-20, 2009 in Las Vegas, Nevada.
The future of the web can't happen without you. Join us at MIX09 to help
pave the way to the Next Web now. Learn more and register at
http://ad.doubleclick.net/clk;208669438;13503038;i?http://2009.visitmix.com/
_______________________________________________
Matplotlib-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins