That is why you have to work with the 3D objects from

mpl_toolkits.mplot3d.art3d directly. There isn't a lot of documentation, so

your best bet is to look at the source code of the module.

Indeed, I was able to extract the necessary pieces from the source

code. In fact I split the function `plot_surface` into two functions

`polyMeshFromMeshGrid` and `plot_surfaceMesh`. The first functions

takes the meshgrid arguments and produces a list of polygons that

should be drawn, the second functions finally displays them (the code

in plot_surface is already structured like this). With this approach I

can plot functions which are made up of several parts which each have

meshgrid structure. Also I can add raw polygons to the mesh.

Maybe this splitting makes sense in the online code as well?

-Holger

def polyMeshFromMeshGrid(self, X, Y, Z, *args, **kwargs):

rows, cols = Z.shape

tX, tY, tZ = np.transpose(X), np.transpose(Y), np.transpose(Z)

rstride = kwargs.pop('rstride', 10)

cstride = kwargs.pop('cstride', 10)

if 'facecolors' in kwargs:

fcolors = kwargs.pop('facecolors')

else:

color = np.array(colorConverter.to_rgba(kwargs.pop('color', 'b')))

fcolors = None

cmap = kwargs.get('cmap', None)

norm = kwargs.pop('norm', None)

vmin = kwargs.pop('vmin', None)

vmax = kwargs.pop('vmax', None)

shade = kwargs.pop('shade', cmap is None)

lightsource = kwargs.pop('lightsource', None)

# Shade the data

if shade and cmap is not None and fcolors is not None:

fcolors = self._shade_colors_lightsource(Z, cmap, lightsource)

polys = kwargs.pop('polys', [])

normals = kwargs.pop('normals', [])

#colset contains the data for coloring: either average z or the facecolor

colset = kwargs.pop('colset', [])

for rs in np.arange(0, rows-1, rstride):

for cs in np.arange(0, cols-1, cstride):

ps = []

corners = []

for a, ta in [(X, tX), (Y, tY), (Z, tZ)]:

ztop = a[rs][cs:min(cols, cs+cstride+1)]

zleft = ta[min(cols-1, cs+cstride)][rs:min(rows, rs+rstride+1)]

zbase = a[min(rows-1, rs+rstride)][cs:min(cols, cs+cstride+1):]

zbase = zbase[::-1]

zright = ta[cs][rs:min(rows, rs+rstride+1):]

zright = zright[::-1]

corners.append([ztop[0], ztop[-1], zbase[0], zbase[-1]])

z = np.concatenate((ztop, zleft, zbase, zright))

ps.append(z)

# The construction leaves the array with duplicate points, which

# are removed here.

ps = zip(*ps)

lastp = np.array([])

ps2 = []

avgzsum = 0.0

for p in ps:

if p != lastp:

ps2.append(p)

lastp = p

avgzsum += p[2]

polys.append(ps2)

if fcolors is not None:

colset.append(fcolors[rs][cs])

else:

colset.append(avgzsum / len(ps2))

# Only need vectors to shade if no cmap

if cmap is None and shade:

v1 = np.array(ps2[0]) - np.array(ps2[1])

v2 = np.array(ps2[2]) - np.array(ps2[0])

normals.append(np.cross(v1, v2))

return polys, normals, colset

def plot_surfaceMesh(self, polys, normals, colset, *args, **kwargs):

had_data = self.has_data()

rows, cols = Z.shape

rstride = kwargs.pop('rstride', 10)

cstride = kwargs.pop('cstride', 10)

if 'facecolors' in kwargs:

fcolors = kwargs.pop('facecolors')

else:

color = np.array(colorConverter.to_rgba(kwargs.pop('color', 'b')))

fcolors = None

cmap = kwargs.get('cmap', None)

norm = kwargs.pop('norm', None)

vmin = kwargs.pop('vmin', None)

vmax = kwargs.pop('vmax', None)

linewidth = kwargs.get('linewidth', None)

shade = kwargs.pop('shade', cmap is None)

lightsource = kwargs.pop('lightsource', None)

polyc = art3d.Poly3DCollection(polys, *args, **kwargs)

if fcolors is not None:

if shade:

colset = self._shade_colors(colset, normals)

polyc.set_facecolors(colset)

polyc.set_edgecolors(colset)

elif cmap:

colset = np.array(colset)

polyc.set_array(colset)

if vmin is not None or vmax is not None:

polyc.set_clim(vmin, vmax)

if norm is not None:

polyc.set_norm(norm)

else:

if shade:

colset = self._shade_colors(color, normals)

else:

colset = color

polyc.set_facecolors(colset)

self.add_collection(polyc)

x, y, z = [], [], [];

for pol in polys:

for p in pol:

x.append(p[0])

y.append(p[1])

z.append(p[2])

self.auto_scale_xyz(x, y, z, had_data)

return polyc