Compute the outer hull of the input mesh. Args: engine (:py:class:`str`): (optional) Outer hull engine name. Valid engines are: * ``auto``: Using the default engine (``igl``). * ``igl``: `libigl's outer hull support <https://github.com/libigl/lib
(mesh, engine="auto", all_layers=False)
| 5 | from .meshutils import remove_degenerated_triangles_raw |
| 6 | |
| 7 | def compute_outer_hull(mesh, engine="auto", all_layers=False): |
| 8 | """ Compute the outer hull of the input mesh. |
| 9 | |
| 10 | Args: |
| 11 | engine (:py:class:`str`): (optional) Outer hull engine name. Valid engines are: |
| 12 | |
| 13 | * ``auto``: Using the default engine (``igl``). |
| 14 | * ``igl``: `libigl's outer hull support |
| 15 | <https://github.com/libigl/libigl>`_ |
| 16 | |
| 17 | all_layers (:py:class:`bool`): (optional) If true, recursively peel |
| 18 | outer hull layers. |
| 19 | |
| 20 | Returns: |
| 21 | If ``all_layers`` is false, just return the outer hull mesh. |
| 22 | |
| 23 | If ``all_layers`` is ture, return a recursively peeled outer hull |
| 24 | layers, from the outer most layer to the inner most layer. |
| 25 | |
| 26 | The following mesh attirbutes are defined in each outer hull mesh: |
| 27 | |
| 28 | * ``flipped``: A per-face attribute that is true if a face in outer |
| 29 | hull is orientated differently comparing to its corresponding face |
| 30 | in the input mesh. |
| 31 | * ``face_sources``: A per-face attribute that specifies the index of the |
| 32 | source face in the input mesh. |
| 33 | """ |
| 34 | assert(mesh.dim == 3) |
| 35 | assert(mesh.vertex_per_face == 3) |
| 36 | |
| 37 | if engine == "auto": |
| 38 | engine = "igl" |
| 39 | |
| 40 | engine = PyMesh.OuterHullEngine.create(engine) |
| 41 | engine.set_mesh(mesh.vertices, mesh.faces) |
| 42 | engine.run() |
| 43 | |
| 44 | vertices = engine.get_vertices() |
| 45 | faces = engine.get_faces() |
| 46 | flipped = engine.get_face_is_flipped().squeeze() |
| 47 | ori_faces = engine.get_ori_face_indices().squeeze() |
| 48 | layers = engine.get_outer_hull_layers().squeeze() |
| 49 | to_flip = flipped != 0 |
| 50 | faces[to_flip] = np.fliplr(faces[to_flip]) |
| 51 | |
| 52 | def extract_layer(i): |
| 53 | selected_faces = layers == i |
| 54 | o_faces = faces[selected_faces] |
| 55 | o_flipped = flipped[selected_faces] |
| 56 | o_ori_faces = ori_faces[selected_faces] |
| 57 | o_vertices, o_faces, __ = remove_isolated_vertices_raw(vertices, o_faces) |
| 58 | o_vertices, o_faces, info = remove_degenerated_triangles_raw( |
| 59 | o_vertices, o_faces) |
| 60 | o_flipped = o_flipped[info["ori_face_indices"]] |
| 61 | o_ori_faces = o_ori_faces[info["ori_face_indices"]] |
| 62 | outer_hull = form_mesh(o_vertices, o_faces) |
| 63 | outer_hull.add_attribute("flipped") |
| 64 | outer_hull.set_attribute("flipped", o_flipped) |