mikedh / trimesh

Python library for loading and using triangular meshes.
https://trimesh.org
MIT License
2.96k stars 576 forks source link

Extruding 2D polygons/faces with trimesh #2022

Open 0xCoto opened 1 year ago

0xCoto commented 1 year ago

I'm able to read and export an STL file pretty easily, e.g.:

# Read STL file
stl_obj = trimesh.load(file_obj=stl_data, file_type="stl")

# Do some fancy operations

# Write STL file
stl_obj.export("output.stl")

This works well for 3D meshes. However, for STLs representing 2D polygons, I would like to apply an extrusion of +0.2 mm towards the normal vector of the polygon, forming a 3D shape. If the STL is a 3D mesh, I would not like to apply any modifications.

For example, if I have a 2D square:

Screenshot 2023-09-02 at 09 52 56

and after the extrusion, I expect to get something that looks like a box (notice the thickness):

Screenshot 2023-09-02 at 09 53 52

Does trimesh (or another library you're aware of) allow me to easily extrude faces/polygons? I'm essentially trying to convert infinitely thin 2D surfaces to very thin 3D meshes. 🙂

For testing, the above example is attached here: example_stls.zip - it includes the input STL, as well as the expected STL I'm trying to produce with trimesh.

Thanks!

0xCoto commented 1 year ago

@mikedh Bumping in case you've got any ideas. :)

mikedh commented 1 year ago

Hey, I think you probably want to extrude the outline if it's planar:

import trimesh

if __name__ == "__main__":
    # generate a not-watertight single plane mesh                                                   
    # move it to a random location in 3D space                                                      
    m = trimesh.Trimesh(
        vertices=[[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0]], faces=[[0, 1, 2, 3]]
    ).permutate.transform()

    # there will be no outline if the mesh is watertight                                            
    assert not m.is_watertight

    # get the outline of the mesh, move it to 2D, save the transform                                
    on_plane, to_3D = m.outline().to_planar()

    # extrude the outline into a solid                                                              
    extrude = on_plane.extrude(0.1).to_mesh().apply_transform(to_3D)

    # set the solid extrusion to a transparent color                                                
    extrude.visual.face_colors = [100, 100, 100, 100]
    # set the original thing to red                                                                 
    m.visual.face_colors = [200, 0, 0, 255]
    assert extrude.is_watertight

    trimesh.Scene([extrude, m]).show()

Screenshot from 2023-09-07 16-31-37