mikedh / trimesh

Python library for loading and using triangular meshes.

Home Page:https://trimesh.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Mesh non watertight after slicing with plane

marios-stam opened this issue · comments

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

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)

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!

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