Anyone can suggest the equivalent function of MATLAB's "isosurface" function in python/numpy. The MATLAB isosurface returns the faces and vertices. I need the faces and vertices to create .stl files. MATLAB isosurface function looks like this:
[f,v] = isosurface(X,Y,Z,V,isovalue)
in python I have found this one method in plotly which works as follows:
import plotly.graph_objects as go
import numpy as np
X, Y, Z = np.mgrid[-5:5:40j, -5:5:40j, -5:5:40j]
# ellipsoid
values = X * X * 0.5 + Y * Y + Z * Z * 2
fig = go.Figure(data=go.Isosurface(
x=X.flatten(),
y=Y.flatten(),
z=Z.flatten(),
value=values.flatten(),
isomin=10,
isomax=40,
caps=dict(x_show=False, y_show=False)
))
fig.show()
the problem with this method is that it only plots isosurfaces and doesn't return faces and vertices as the MATLAB isosurface function does and I need those faces and vertices.
Any help would be greatly appreciated.
Although it wasn't among your target libraries, PyVista built on VTK can help you do this easily (disclaimer: I'm one of the devs). Since you seemed receptive of a PyVista-based solution in comments, here's how you'd do it:
StructuredGrid
for your kind of data, although the equidistant grid in your example could even work with aUniformGrid
,contour
filter,.stl
file using thesave
method of the grid containing the isosurfaces.The interactive plot looks something like this:
The colours correspond to the isovalues, picked from the scalars array and indicated by the scalar bar.
If we load back the mesh from file we'll get the structure, but not the scalars:
The reason why the scalars are missing is that data arrays can't be exported to
.stl
files:While the original isosurfaces each had the isovalues bound to them (providing the colour mapping seen in the first figure), as well as point and cell normals (computed by the call to
.save()
for some reason), there's no data in the latter case.Still, since you're looking for vertices and faces, this should do just fine. In case you need it, you can also access these on the PyVista side, since the isosurface mesh is a
PolyData
object:Now the logistics of the faces is a bit tricky. They are all encoded in a 1d array of integers. In the 1d array you always have an integer
n
telling you the size of the given face, and thenn
zero-based indices corresponding to points in the points array. The above isosurfaces consist entirely of triangles:Which is why you'll see
and you could do
isos.faces.reshape(-1, 4)
to get a 2d array where each row corresponds to a triangular face (and the first column is constant 3).