python matplotlib plot_trisurf polygon data

1.1k views Asked by At

Is there anyway to get the polygon data (i.e triangle edges) from the plot_trisurf function? Since it takes x,y and z data and creates a Delaunay triangulation it must have this data somewhere...?

Something that can be used with the below example would be great.

from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
import matplotlib.pyplot as plt
import numpy as np

n_angles = 36

n_radii = 8

radii = np.linspace(0.125, 1.0, n_radii)

angles = np.linspace(0, 2*np.pi, n_angles, endpoint=False)

angles = np.repeat(angles[..., np.newaxis], n_radii, axis=1)

x = np.append(0, (radii*np.cos(angles)).flatten())
y = np.append(0, (radii*np.sin(angles)).flatten())


z = np.sin(-x*y)

fig = plt.figure()
ax = fig.gca(projection='3d')

ax.plot_trisurf(x, y, z, cmap=cm.jet, linewidth=0.2)


plt.show()

I'd like to use matplotlib for this, as it uses a Delaunay algorithm that is more suited to 3D data. From what I can workout, doesn't parametrise it into 2D, and is easily available on a much wider range of hardware without anything close to the same amount of faff, unlike mayavi. Plotly could also be an option, although I believe this requires the data to be parametrised into 2D, which is not ideal for my application. I'm aware there are Delaunay libraries in python scipy that will do this, but again the parametrisation of the data is the problem.

2

There are 2 answers

3
ImportanceOfBeingErnest On

You can look at the source code of plot_trisurf to find out how matplotlib does the triangulation.
It basically performs a triangulation on a 2D grid and takes over the z component from the input.
The 2D triangulation is done by the matplotlib.tri.triangulation.Triangulation class.

The following could do what you want, giving you an array of the vertices.

from matplotlib.tri.triangulation import Triangulation
import numpy as np

n_angles = 36
n_radii = 8

radii = np.linspace(0.125, 1.0, n_radii)
angles = np.linspace(0, 2*np.pi, n_angles, endpoint=False)
angles = np.repeat(angles[..., np.newaxis], n_radii, axis=1)

x = np.append(0, (radii*np.cos(angles)).flatten())
y = np.append(0, (radii*np.sin(angles)).flatten())
z = np.sin(-x*y)


tri, args, kwargs = Triangulation.get_from_args_and_kwargs(x, y, z)
triangles = tri.get_masked_triangles()
xt = tri.x[triangles][..., np.newaxis]
yt = tri.y[triangles][..., np.newaxis]
zt = z[triangles][..., np.newaxis]

verts = np.concatenate((xt, yt, zt), axis=2)

print verts
0
npnmodp On

Poly3DCollection is for this purpose, plotting 3D polygons without interpolation. It accepts a list of the Polygon vertices' coordinates, and you simply call ax.add_collection3d(collection) to add them to the axes.