pymeshfix icon indicating copy to clipboard operation
pymeshfix copied to clipboard

Segmentation fault when trying to load it through load_array

Open marios-stam opened this issue 1 year ago • 5 comments

Hello, I am trying to load the attached mesh using the following code and get Segmentation fault (core dumped). Please note that the vertices and faces are given using trimesh since I am doing some operation with it. The mesh is not watertight.

from pymeshfix._meshfix import PyTMesh
from pymeshfix import _meshfix
filepath = "/home/marios/Desktop/MARIOS/phd/CollaborativeStructure/customChunker/debugAssets/nonWatertightPosMesh.stl"
probPart = trimesh.load_mesh(filepath)
print("Is watertight: ", probPart.is_watertight)
tin = _meshfix.PyTMesh()
v = np.array(probPart.vertices)
f = np.array(probPart.faces)
tin.load_array(v, f)

However if I load it as follows I do not get any error and the mesh is watertight.

from pymeshfix._meshfix import PyTMesh
from pymeshfix import _meshfix
filepath = "/home/marios/Desktop/MARIOS/phd/CollaborativeStructure/customChunker/debugAssets/nonWatertightPosMesh.stl"
tin = _meshfix.PyTMesh()
tin.load_file(filepath)

Do you maybe have any suggestions or possible solutions that I could use?

nonWatertightPosMesh.zip

marios-stam avatar Mar 19 '24 16:03 marios-stam

Here's an alternative script:

import numpy as np
import trimesh
import pyvista as pv
from pymeshfix._meshfix import PyTMesh
from pymeshfix import _meshfix, meshfix

filepath = 'nonWatertightPosMesh.stl'
probPart = trimesh.load_mesh(filepath)
print("Is watertight: ", probPart.is_watertight)

mesh = pv.read(filepath)
mfix = meshfix.MeshFix(mesh)
mfix.repair(verbose=True)
mfix.plot()

With output:

Is watertight:  False
INFO- Loaded 28 vertices and 52 faces.
Fixing degeneracies and intersections
INFO- ********* ITERATION 0 *********
INFO- Removing degeneracies...
INFO- Removing self-intersections...

0 % done   
INFO- 16 intersecting triangles have been selected.

0 % done   
INFO- 15 intersecting triangles have been selected.

0 % done   
INFO- No intersections detected.

Arrays can be accessed from:

mfix.v
mfix.f

Note that many triangles have been removed from the original surface, but if you subdivide, you can preserve the volume of the original surface using subdivide:

import numpy as np
import trimesh
import pyvista as pv
from pymeshfix._meshfix import PyTMesh
from pymeshfix import _meshfix, meshfix

filepath = 'nonWatertightPosMesh.stl'
probPart = trimesh.load_mesh(filepath)
print("Is watertight: ", probPart.is_watertight)

mesh = pv.read(filepath)
mesh = mesh.subdivide(1).clean()
print('Original volume:', mesh.volume)
mfix = meshfix.MeshFix(mesh)
mfix.repair(verbose=True)
mfix.plot()
print('Final volume:', mesh.volume)

mfix.save('WatertightPosMesh.stl')

akaszynski avatar Mar 19 '24 17:03 akaszynski

Hello and thank you for the quick response.

The problem is indeed solved by loading the mesh directly from the .stl file but as I already mentioned above my problem is that I want to load the vertices and the faces of the mesh dynamically since I already have them in the trimesh format after various modifications.

Do you maybe know why everything is working as expected when I load it from the file but I get the segmentation fault when I read the mesh from the arrays?

marios-stam avatar Mar 19 '24 22:03 marios-stam

Do you maybe know why everything is working as expected when I load it from the file but I get the segmentation fault when I read the mesh from the arrays?

That's perplexing for me as well, especially as when loading from a PyVista mesh.

I'm afraid don't have the time at the moment to dedicate to debugging the C++ layer (which is where this bug is occurring), but PyVista and trimesh work well together and you can convert between the two with:

Trimesh to PyVista
part = trimesh.load_mesh(filepath)
pv_mesh = pv.wrap(part)
Trimesh to PyVista
faces_as_array = pv_mesh.faces.reshape((self.n_faces, 4))[:, 1:] 
tmesh = trimesh.Trimesh(pv_mesh.points, faces_as_array) 

akaszynski avatar Mar 20 '24 16:03 akaszynski

I also have a segfault for which I have no workaround: it is raised by both meshfix.MeshFix(mesh) and clean_from_arrays(). I even tried passing copies of the pyvista arrays, thinking it might be a "numpy array view" issue, but that didn't work. I can share the .vtp file if it's of any help.

nicolascedilnik avatar Apr 24 '24 09:04 nicolascedilnik

I was running into a similar issue when using pymeshfix on the output from pyacvd and found that rolling back scipy to v1.12.0 resolved the issue (see https://github.com/pyvista/pyacvd/issues/47 from pyacvd).

Prior to finding this solution I was able to track the issue down to Basic_TMesh::fixConnectivity as I could not get a return value from Basic_TMesh_wrap::loadArray but it would display the line TMesh::info("Loaded %d vertices and %d faces.\n", nv, nt); prior to crashing.

Hopefully that works to give someone else who understands more of the cpp code a lead to track down the source of the issue. In the meantime, maybe rolling back the scipy version would solve the segfault issue?

adbeagley avatar May 07 '24 18:05 adbeagley