wolph / numpy-stl

Simple library to make working with STL files (and 3D objects in general) fast and easy.
http://numpy-stl.readthedocs.org/
BSD 3-Clause "New" or "Revised" License
605 stars 103 forks source link

Non-watertight STL meshes #186

Closed ivncl closed 10 months ago

ivncl commented 2 years ago

Hi everyone,

Not really an issue of numpy-stl but maybe someone has already encountered the problem. Title speaks for itself, working on some simple convex point clouds I always get non-watertitght meshes, which I may be wrong but seems to be a non-sense.

The problem is easily reproduced with the cube example example provided in pypi https://pypi.org/project/numpy-stl/.

import numpy as np
from stl import mesh

# Define the 8 vertices of the cube
vertices = np.array([\
    [-1, -1, -1],
    [+1, -1, -1],
    [+1, +1, -1],
    [-1, +1, -1],
    [-1, -1, +1],
    [+1, -1, +1],
    [+1, +1, +1],
    [-1, +1, +1]])
# Define the 12 triangles composing the cube
faces = np.array([\
    [0,3,1],
    [1,3,2],
    [0,4,7],
    [0,7,3],
    [4,5,6],
    [4,6,7],
    [5,1,2],
    [5,2,6],
    [2,3,6],
    [3,7,6],
    [0,1,5],
    [0,5,4]])

# Create the mesh
cube = mesh.Mesh(np.zeros(faces.shape[0], dtype=mesh.Mesh.dtype))
for i, f in enumerate(faces):
    for j in range(3):
        cube.vectors[i][j] = vertices[f[j],:]

# Write the mesh to file "cube.stl"
cube.save('cube.stl')

Opening the .stl in any slicer (as Cura) I get non-watertitght warning. Cheking instead its watertightness with trimesh module I got the opposite answer:

import trimesh
mesh = trimesh.base.Trimesh(vertices,faces)
print(mesh.is_watertight)
True

Found this similar issue on trimesh page https://github.com/mikedh/trimesh/issues/535, where the cause is found to be numerical precision errors. Any suggestion on how to solve it? Any help appreciated.

wolph commented 2 years ago

My assumption is that Trimesh says it's watertight because it sees that 2 triangles are close enough to each other to be "watertight".

In reality, in STL files you would expect 2 neighbouring triangles to share the same points so they are not close, but using the exact same points.

This specific case of making a mesh watertight doesn't appear that difficult to do, but it could still take some effort to write a fast and efficient algorithm for it.

It seems that VTK has an algorithm readily available for this purpose: https://github.com/Kitware/VTK/blob/master/Filters/Modeling/vtkFillHolesFilter.cxx https://stackoverflow.com/questions/64804792/how-to-make-an-open-stl-file-watertight

ivncl commented 2 years ago

Thanks for the quick reply!

making a mesh watertight doesn't appear that difficult to do, but it could still take some effort to write a fast and efficient algorithm for it

You mean using exact arithmetic?

About VTK algorithm, that's interesting but that would be more a "repairing" of the mesh, while what I need is a clean mesh who doesn't need filters. My objective is re-use it for tetra meshing, and the more simple the geometry is the more the tetra generation seems to be efficient and its output result regular.

wolph commented 2 years ago

making a mesh watertight doesn't appear that difficult to do, but it could still take some effort to write a fast and efficient algorithm for it

You mean using exact arithmetic?

Basically you would have to walk through all triangles and check if there are adjacent triangles. If there aren't, you would need to look for close triangles and move the two triangles towards each other to close the holes.