vedo
vedo copied to clipboard
Some subdivide functions return meshes with 0 points
I'm investigating an issue with mesh.subdivide. Depending on the method (e.g. linear, loop, butterfly), the resulting mesh has zero vertices. I'm wondering if this is a bug or has something to do with my example data. If the data is the problem, is there a way of fixing it? Do meshes have to fulfill some constraints when being passed to these functions?
Code to reproduce:
import vedo
print("Vedo version", vedo.__version__)
filename = "https://github.com/haesleinhuepf/napari-process-points-and-surfaces/raw/main/napari_process_points_and_surfaces/data/gastruloid.ply"
for method in range(0, 5):
mesh_in = vedo.load(filename)
print("Mesh in points", mesh_in.npoints)
mesh_out = mesh_in.subdivide(n=1, method=method)
print("Mesh out points", mesh_out.npoints, f"(Method {method})")
The output shows that three of the five methods result in meshes with 0 vertices:
Vedo version 2023.4.3
Mesh in points 3324
Mesh out points 0 (Method 0)
Mesh in points 3324
Mesh out points 0 (Method 1)
Mesh in points 3324
Mesh out points 231686 (Method 2)
Mesh in points 3324
Mesh out points 0 (Method 3)
Mesh in points 3324
Mesh out points 9967 (Method 4)
See also:
- https://github.com/haesleinhuepf/napari-process-points-and-surfaces/issues/57
Hi Robert You seem to have a non-manifold edge in your mesh:
import vedo
filename = "https://github.com/haesleinhuepf/napari-process-points-and-surfaces/raw/main/napari_process_points_and_surfaces/data/gastruloid.ply"
mesh_in = vedo.Mesh(filename)
non_manifold_boundaries = mesh_in.boundaries(
non_manifold_edges=True,
boundary_edges=False,
)
print("Mesh in points", mesh_in.npoints)
vedo.show(mesh_in, non_manifold_boundaries)
some subdivision methods are insensitive to it but others may not be...
PS: to spot the cell you can click on a region of the mesh then press . repeatedly to fly to it then press i and check the printout at cellID. Finally adding
mesh_in.delete_cells([3721])
mesh_in.clean()
print("Mesh in points", mesh_in.npoints)
mesh_out = mesh_in.subdivide(n=1, method=0)
print("Mesh out points", mesh_out.npoints)
vedo.show(mesh_out, non_manifold_boundaries).close()
cures the problem.
Would be cool to have some split_non_manifold_edges() function to have this programmatically..
Thanks for the rapid response @marcomusy !
Would be cool to have some
split_non_manifold_edges()function to have this programmatically..
Yes, agreed! We'll look into this. We already use mesh.clean() to remove duplicated edges after running marching cubes. So maybe, this additional cleanup step is necessary, too. Btw. just for completeness: This is how we created the discussed dataset (full details):
- Marching cubes (scikit-image)
- Vedo's
mesh.clean() - Vedo's
mesh.decimate(method='quadric',...) - Vedo's
mesh.smooth()
Would it make sense to remove non-manifold edges after any of those steps in general? We had a similar discussion about mesh.clean() after marching cubes...
Thanks again!
..i've been playing with it this afternoon and this is what i've come up with (you need the dev16 version in master branch):
from vedo import *
filename = "https://github.com/haesleinhuepf/napari-process-points-and-surfaces/raw/main/napari_process_points_and_surfaces/data/gastruloid.ply"
msh = Mesh(filename)
print("msh is_manifold:", msh.is_manifold())
msh.non_manifold_faces(collapse_edges=False, remove_boundary=False, remove_all=True)
print("msh is_manifold:", msh.is_manifold())
msh.fill_holes()
msh.backcolor("p5").linewidth(1)
show(msh, msh.boundaries(), axes=1)
Implemented in https://github.com/marcomusy/vedo/blob/0bc914d0074054bd62305a39f781bf14ee35d36a/vedo/mesh.py#L745
remove_allkills all the problematic cells leaving out a hole which can be cured byfill_holes()remove_boundaryonly removes cells touching any mesh boundariescollapse_edgescollapses all non-manifold edges into a single point and the final degenerate faces are then removed.
..in any case the marching cube algorithm should not generate non manifold isosurfaces...
Thanks again for your time and effort!
..in any case the marching cube algorithm should not generate non manifold isosurfaces...
I was suspecting the scikit-image version to be buggy when was saw it produces duplicate vertices. Are there alternatives? When searching the vedo documentation for "marching" it doesn't find any...
Also let me get @jo-mueller in the loop as he's more knowledgeable in the mesh context than I am: Johannes could you do me a favor and check if the above solution can be used to fix the issue in nppas? Or shall we replace marching cubes? Looking forward to hear what you think.
- https://github.com/haesleinhuepf/napari-process-points-and-surfaces/issues/57
Big thanks to you both!
Hi, the method doing the marching cube is called isosurface() and it's documented here:
https://vedo.embl.es/autodocs/content/vedo/vedo/base.html#BaseGrid.isosurface
it has a fast implementation activated by default, which you can disable by setting flying_edges=False.