Revision: 7265
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7265&view=rev
Author: heeres
Date: 2009-07-17 07:24:06 +0000 (Fri, 17 Jul 2009)
Log Message:
-----------
mplot3d: add bar3d, improve z-sort, hist3d example
Modified Paths:
--------------
trunk/matplotlib/lib/mpl_toolkits/mplot3d/art3d.py
trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py
Added Paths:
-----------
trunk/matplotlib/examples/mplot3d/hist3d_demo.py
Added: trunk/matplotlib/examples/mplot3d/hist3d_demo.py
===================================================================
--- trunk/matplotlib/examples/mplot3d/hist3d_demo.py
(rev 0)
+++ trunk/matplotlib/examples/mplot3d/hist3d_demo.py 2009-07-17 07:24:06 UTC
(rev 7265)
@@ -0,0 +1,27 @@
+from mpl_toolkits.mplot3d import Axes3D
+from matplotlib.collections import PolyCollection
+from matplotlib.colors import colorConverter
+import pylab
+import random
+import numpy as np
+
+fig = pylab.figure()
+ax = Axes3D(fig)
+x = np.random.rand(100) * 4
+y = np.random.rand(100) * 4
+hist, xedges, yedges = np.histogram2d(x, y, bins=4)
+
+elements = (len(xedges) - 1) * (len(yedges) - 1)
+xpos, ypos = np.meshgrid(
+ [xedges[i] + 0.25 for i in range(len(xedges) - 1)],
+ [yedges[i] + 0.25 for i in range(len(yedges) - 1)])
+xpos = xpos.flatten()
+ypos = ypos.flatten()
+zpos = [0] * elements
+dx = [0.5] * elements
+dy = [0.5] * elements
+dz = hist.flatten()
+ax.bar3d(xpos, ypos, zpos, dx, dy, dz, color='b')
+
+pylab.show()
+
Modified: trunk/matplotlib/lib/mpl_toolkits/mplot3d/art3d.py
===================================================================
--- trunk/matplotlib/lib/mpl_toolkits/mplot3d/art3d.py 2009-07-16 20:53:24 UTC
(rev 7264)
+++ trunk/matplotlib/lib/mpl_toolkits/mplot3d/art3d.py 2009-07-17 07:24:06 UTC
(rev 7265)
@@ -271,6 +271,7 @@
PolyCollection.__init__(self, verts, *args, **kwargs)
self._zsort = 1
+ self._sort_zpos = None
def get_vector(self, segments3d):
"""Optimize points for projection"""
@@ -287,7 +288,6 @@
ones = np.ones(len(xs))
self._vec = np.array([xs, ys, zs, ones])
self._segis = segis
- self._sort_zpos = min(zs)
def set_verts(self, verts, closed=True):
'''Set 3D vertices.'''
@@ -297,9 +297,13 @@
def set_3d_properties(self):
self._zsort = 1
+ self._sort_zpos = None
self._facecolors3d = PolyCollection.get_facecolors(self)
self._edgecolors3d = PolyCollection.get_edgecolors(self)
+ def set_sort_zpos(self, val):
+ self._sort_zpos = val
+
def do_3d_projection(self, renderer):
'''
Perform the 3D projection for this object.
@@ -315,17 +319,19 @@
# This extra fuss is to re-order face / edge colors
cface = self._facecolors3d
- if len(self._edgecolors3d) != len(cface):
- cedge = cface
- else:
- cedge = self._edgecolors3d
+ cedge = self._edgecolors3d
+ if len(cface) != len(xyzlist):
+ cface = cface.repeat(len(xyzlist), axis=0)
+ if len(cedge) != len(xyzlist):
+ if len(cedge) == 0:
+ cedge = cface
+ cedge = cedge.repeat(len(xyzlist), axis=0)
# if required sort by depth (furthest drawn first)
if self._zsort:
- z_segments_2d = [(min(zs), zip(xs, ys), fc, ec) for
+ z_segments_2d = [(np.average(zs), zip(xs, ys), fc, ec) for
(xs, ys, zs), fc, ec in zip(xyzlist, cface, cedge)]
- z_segments_2d.sort()
- z_segments_2d.reverse()
+ z_segments_2d.sort(reverse=True)
else:
raise ValueError, "whoops"
@@ -339,9 +345,12 @@
self._edgecolors2d = self._edgecolors3d
# Return zorder value
- zvec = np.array([[0], [0], [self._sort_zpos], [1]])
- ztrans = proj3d.proj_transform_vec(zvec, renderer.M)
- return ztrans[2][0]
+ if self._sort_zpos is not None:
+ zvec = np.array([[0], [0], [self._sort_zpos], [1]])
+ ztrans = proj3d.proj_transform_vec(zvec, renderer.M)
+ return ztrans[2][0]
+ else:
+ return np.min(tzs)
def set_facecolor(self, colors):
PolyCollection.set_facecolor(self, colors)
Modified: trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py
===================================================================
--- trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py 2009-07-16 20:53:24 UTC
(rev 7264)
+++ trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py 2009-07-17 07:24:06 UTC
(rev 7265)
@@ -625,6 +625,20 @@
return polyc
+ def _generate_normals(self, polygons):
+ '''
+ Generate normals for polygons by using the first three points.
+ This normal of course might not make sense for polygons with
+ more than three points not lying in a plane.
+ '''
+
+ normals = []
+ for verts in polygons:
+ v1 = np.array(verts[0]) - np.array(verts[1])
+ v2 = np.array(verts[2]) - np.array(verts[0])
+ normals.append(np.cross(v1, v2))
+ return normals
+
def _shade_colors(self, color, normals):
shade = []
for n in normals:
@@ -733,6 +747,7 @@
colors2 = self._shade_colors(color, normals)
polycol = art3d.Poly3DCollection(polyverts, facecolors=colors,
edgecolors=colors2)
+ polycol.set_sort_zpos(z)
self.add_collection3d(polycol)
for col in colls:
@@ -792,6 +807,7 @@
colls = cset.collections
for z1, z2, linec in zip(levels, levels[1:], colls):
art3d.poly_collection_2d_to_3d(linec, z1)
+ linec.set_sort_zpos(z1)
self.auto_scale_xyz(X, Y, Z, had_data)
return cset
@@ -813,10 +829,13 @@
if type(col) is collections.PolyCollection:
art3d.poly_collection_2d_to_3d(col, zs=zs, zdir=zdir)
+ col.set_sort_zpos(min(zs))
elif type(col) is collections.LineCollection:
art3d.line_collection_2d_to_3d(col, zs=zs, zdir=zdir)
+ col.set_sort_zpos(min(zs))
elif type(col) is collections.PatchCollection:
art3d.patch_collection_2d_to_3d(col, zs=zs, zdir=zdir)
+ col.set_sort_zpos(min(zs))
Axes.add_collection(self, col)
@@ -902,6 +921,64 @@
return patches
+ def bar3d(self, x, y, z, dx, dy, dz, color='b'):
+ '''
+ Generate a 3D bar, or multiple bars.
+
+ When generating multiple bars, x, y, z have to be arrays.
+ dx, dy, dz can still be scalars.
+ '''
+
+ had_data = self.has_data()
+
+ if not cbook.iterable(x):
+ print 'not interable'
+ x, y, z = [x], [y], [z]
+ if not cbook.iterable(dx):
+ dx, dy, dz = [dx], [dy], [dz]
+ if len(dx) == 1:
+ dx = dx * len(x)
+ dy = dy * len(x)
+ dz = dz * len(x)
+
+ minx, miny, minz = 1e20, 1e20, 1e20
+ maxx, maxy, maxz = -1e20, -1e20, -1e20
+
+ polys = []
+ for xi, yi, zi, dxi, dyi, dzi in zip(x, y, z, dx, dy, dz):
+ minx = min(xi, minx)
+ maxx = max(xi + dxi, maxx)
+ miny = min(yi, miny)
+ maxy = max(yi + dyi, maxy)
+ minz = min(zi, minz)
+ maxz = max(zi + dzi, maxz)
+
+ polys.extend([
+ ((xi, yi, zi), (xi + dxi, yi, zi),
+ (xi + dxi, yi + dyi, zi), (xi, yi + dyi, zi)),
+ ((xi, yi, zi + dzi), (xi + dxi, yi, zi + dzi),
+ (xi + dxi, yi + dyi, zi + dzi), (xi, yi + dyi, zi + dzi)),
+
+ ((xi, yi, zi), (xi + dxi, yi, zi),
+ (xi + dxi, yi, zi + dzi), (xi, yi, zi + dzi)),
+ ((xi, yi + dyi, zi), (xi + dxi, yi + dyi, zi),
+ (xi + dxi, yi + dyi, zi + dzi), (xi, yi + dyi, zi + dzi)),
+
+ ((xi, yi, zi), (xi, yi + dyi, zi),
+ (xi, yi + dyi, zi + dzi), (xi, yi, zi + dzi)),
+ ((xi + dxi, yi, zi), (xi + dxi, yi + dyi, zi),
+ (xi + dxi, yi + dyi, zi + dzi), (xi + dxi, yi, zi + dzi)),
+ ])
+
+ color = np.array(colorConverter.to_rgba(color))
+ normals = self._generate_normals(polys)
+ colors = self._shade_colors(color, normals)
+
+ col = art3d.Poly3DCollection(polys, facecolor=colors)
+ self.add_collection(col)
+
+ self.auto_scale_xyz((minx, maxx), (miny, maxy), (minz, maxz), had_data)
+
def get_test_data(delta=0.05):
'''
Return a tuple X, Y, Z with a test data set.
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
------------------------------------------------------------------------------
Enter the BlackBerry Developer Challenge
This is your chance to win up to $100,000 in prizes! For a limited time,
vendors submitting new applications to BlackBerry App World(TM) will have
the opportunity to enter the BlackBerry Developer Challenge. See full prize
details at: http://p.sf.net/sfu/Challenge
_______________________________________________
Matplotlib-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins