Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mesh non watertight after slicing with plane #2180

Open
marios-stam opened this issue Mar 10, 2024 · 3 comments
Open

Mesh non watertight after slicing with plane #2180

marios-stam opened this issue Mar 10, 2024 · 3 comments

Comments

@marios-stam
Copy link

Hello all,

I have been trying to slice the following mesh that I have attached with the plane defined in the code and I get a non-watertight mesh as a result. However, if I save the sliced mesh and load it from another similar framework and save it using it, it is watertight when I load it again in trimesh.

origin = [-0.03,  0.05,  0.10]
normal = [-0.25,  0.43,  0.87]
part = trimesh.load_mesh("debugAssets/problematic.stl")
slicedMesh = trimesh.intersections.slice_mesh_plane(part, plane_normal=normal, plane_origin=origin, cap=True)
trimesh.repair.fill_holes(slicedMesh)
trimesh.repair.fix_winding(slicedMesh)
trimesh.repair.fix_inversion(slicedMesh)
trimesh.repair.fix_normals(slicedMesh)
slicedMesh =  slicedMesh.process()

print("slicedMesh watertight: ", slicedMesh.is_watertight)

Here is also a photo of how the plane and the mesh look
image
image

problematic.zip

@mikedh
Copy link
Owner

mikedh commented Mar 11, 2024

Hey, not totally sure why it's not watertight... I was able to get it to be watertight with triangle (free for non-commercial use, pip install triangle) but not the permissibly licensed mapbox-earcut (i.e. the default).

Might be an on-vertex hit or some case that's not handled well? PR's welcome if you figure it out! With triangle and process(validate=True) fixed it which means it removed a degenerate or otherwise bad face.

import trimesh

if __name__ == "__main__":
    s = trimesh.load("~/Downloads/problematic.zip")
    assert len(s.geometry) == 1

    origin = [-0.03, 0.05, 0.10]
    normal = [-0.25, 0.43, 0.87]

    part = next(iter(s.geometry.values()))

    viz = trimesh.Scene([part,
                         trimesh.path.creation.grid(
                             side=part.bounds.max(),
                             plane_normal=normal,
                             plane_origin=origin)])

    st = part.slice_plane(
        plane_origin=origin,
        plane_normal=normal,
        cap=True,
        engine="triangle",
        triangle_args="pY",
    ).process(validate=True)

    se = part.slice_plane(
        plane_origin=origin,
        plane_normal=normal,
        cap=True,
    ).process(validate=True)

@marios-stam
Copy link
Author

Hello

yes, that seemed to do the work! Thank you for the quick response and in case I find the original source of the issue I will let you know with a PR!

@marios-stam
Copy link
Author

Following the previous, after lots of testing, the "triangle" engine seems much more robust but there are still issues. For example, the following code does not provide watertight meshes.

meshFile = "partBefore.stl"
m = trimesh.load_mesh(meshFile)
p = [0.0, 0.0, 0.0]
n = [-0.71 , 0.00 ,0.71]

nNeg = [0.71 , 0.00 ,-0.71]

posMesh =  intersections.slice_mesh_plane(m, n, p, cap=True,engine="triangle").process(validate=True)
negMesh =  intersections.slice_mesh_plane(m, nNeg, p, cap=True,engine="triangle").process(validate=True)

print("posMesh.is_watertight", posMesh.is_watertight)
print("negMesh.is_watertight", negMesh.is_watertight)
sc = trimesh.Scene()
sc.add_geometry(posMesh)
sc.add_geometry(negMesh)
sc.show()
 

image

partBefore.zip

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants