¿Cómo visualizar la triangulación de delaunay 3D en Python?

Tengo un conjunto de puntos 3D que he usado scipy.spatial.Delaunay para hacer la triangulación / tetraédrica. Ahora tengo un conjunto de caras únicas de todos los tetraedros, y me gustaría visualizarlas en 3D.

¿Hay alguna biblioteca de Python (o bibliotecas con un envoltorio de Python) que puedan hacer esto?

Prueba mayavi.mlab.triangular_mesh()

 import numpy as np from mayavi import mlab vertices = np.array([[0, 1, 0, 0],[0, 0, 1, 0],[0, 0, 0, 1]]) faces = np.array([[0, 1, 0, 0],[1, 2, 1, 2],[2, 3, 3, 3]]) mlab.triangular_mesh(vertices[0,:], vertices[1,:], vertices[2,:], faces.T) mlab.show() 

También se puede hacer utilizando el trazado tridimensional de matplotlib (sin la necesidad del paquete mayavi).

El siguiente código es una implementación simple inicial de dicha función.

 import numpy as np import matplotlib.pyplot as plt from mpl_toolkits import mplot3d from scipy.spatial import Delaunay def plot_tri_simple(ax, points, tri): for tr in tri.simplices: pts = points[tr, :] ax.plot3D(pts[[0,1],0], pts[[0,1],1], pts[[0,1],2], color='g', lw='0.1') ax.plot3D(pts[[0,2],0], pts[[0,2],1], pts[[0,2],2], color='g', lw='0.1') ax.plot3D(pts[[0,3],0], pts[[0,3],1], pts[[0,3],2], color='g', lw='0.1') ax.plot3D(pts[[1,2],0], pts[[1,2],1], pts[[1,2],2], color='g', lw='0.1') ax.plot3D(pts[[1,3],0], pts[[1,3],1], pts[[1,3],2], color='g', lw='0.1') ax.plot3D(pts[[2,3],0], pts[[2,3],1], pts[[2,3],2], color='g', lw='0.1') ax.scatter(points[:,0], points[:,1], points[:,2], color='b') 

El resultado de llamar a esta función con el siguiente código de prueba da como resultado la siguiente figura: introduzca la descripción de la imagen aquí

 np.random.seed(0) x = 2.0 * np.random.rand(20) - 1.0 y = 2.0 * np.random.rand(20) - 1.0 z = 2.0 * np.random.rand(20) - 1.0 points = np.vstack([x, y, z]).T tri = Delaunay(points) fig = plt.figure() ax = plt.axes(projection='3d') plot_tri(ax, points, tri) 

El código anterior es lento porque la ttwig se realiza dentro del bucle. Además, funciona en cada simplex por separado, por lo que los bordes se renderizan más de una vez. Sigue una implementación más eficiente, que utiliza una función auxiliar collect_edges para tomar cada borde solo una vez, y usa los valores np.nan en la función de trazado para dibujar los segmentos de borde en un solo comando de trazado.

El resultado de ejecutar el código de prueba anterior con la nueva función da una cifra idéntica, pero el tiempo de ejecución se mejora en un factor de x80 en mi máquina (300 ms en comparación con 3,6 ms).

 def plot_tri_2(ax, points, tri): edges = collect_edges(tri) x = np.array([]) y = np.array([]) z = np.array([]) for (i,j) in edges: x = np.append(x, [points[i, 0], points[j, 0], np.nan]) y = np.append(y, [points[i, 1], points[j, 1], np.nan]) z = np.append(z, [points[i, 2], points[j, 2], np.nan]) ax.plot3D(x, y, z, color='g', lw='0.1') ax.scatter(points[:,0], points[:,1], points[:,2], color='b') def collect_edges(tri): edges = set() def sorted_tuple(a,b): return (a,b) if a < b else (b,a) # Add edges of tetrahedron (sorted so we don't add an edge twice, even if it comes in reverse order). for (i0, i1, i2, i3) in tri.simplices: edges.add(sorted_tuple(i0,i1)) edges.add(sorted_tuple(i0,i2)) edges.add(sorted_tuple(i0,i3)) edges.add(sorted_tuple(i1,i2)) edges.add(sorted_tuple(i1,i3)) edges.add(sorted_tuple(i2,i3)) return edges