Repository: Genesis-Embodied-AI/Genesis
File: genesis/utils/mesh.py (Python)

Code before:

    if cfg.get("quality", True):
        r = cfg.get("minratio", 1.1)
        di = cfg.get("mindihedral", 10)
        flags.append(f"q{r}/{di}")

    a = cfg.get("maxvolume", -1.0)
    if a > 0:
        flags.append(f"a{a}")

    o = cfg.get("order", 1)
    if o != 1:
        flags.append(f"o{o}")

    if cfg.get("nobisect", False):
        flags.append("Y")

    v = cfg.get("verbose", 0)
    if v > 0:
        flags.append("V" * v)

    return "".join(flags)


def tetrahedralize_mesh(mesh, tet_cfg):
    if platform.machine() == "aarch64":
        gs.raise_exception("This method is not support on Linux ARM because 'tetgen' module is crashing.")

    # Importing pyvista and tetgen are very slow to import and not used very often. Let's delay import.
    import pyvista as pv
    import tetgen

    pv_obj = pv.PolyData(
        mesh.vertices, np.concatenate([np.full((mesh.faces.shape[0], 1), mesh.faces.shape[1]), mesh.faces], axis=1)
    )
    tet = tetgen.TetGen(pv_obj)
    # Build and apply the switches string directly, since
    # the Python wrapper sometimes ignores certain kwargs
    # (e.g. maxvolume). See: https://github.com/pyvista/tetgen/issues/24
    switches = make_tetgen_switches(tet_cfg)
    verts, elems = tet.tetrahedralize(switches=switches)
    # visualize_tet(tet, pv_obj, show_surface=False, plot_cell_qual=False)
    return verts, elems


def visualize_tet(tet, pv_data, show_surface=True, plot_cell_qual=False):
    grid = tet.grid
    if show_surface:
        grid.plot(show_edges=True)
    else:
        # get cell centroids

Review comment (performance):
Note: This can be done more efficiently by directly passing faces via:
```pv
points = mesh.vertices
faces = mesh._connectivity_array.reshape(-1, 3).astype(np.int32, copy=False)
tet = tetgen.TetGen(points, faces)
```

Code after:
    if cfg.get("quality", True):
        r = cfg.get("minratio", 1.1)
        di = cfg.get("mindihedral", 10)
        flags.append(f"q{r}/{di}")

    a = cfg.get("maxvolume", -1.0)
    if a > 0:
        flags.append(f"a{a}")

    o = cfg.get("order", 1)
    if o != 1:
        flags.append(f"o{o}")

    if cfg.get("nobisect", False):
        flags.append("Y")

    v = cfg.get("verbose", 0)
    if v > 0:
        flags.append("V" * v)

    return "".join(flags)


def tetrahedralize_mesh(mesh, tet_cfg):
    # Importing pyvista and tetgen are very slow to import and not used very often. Let's delay import.
    import pyvista as pv
    import tetgen

    pv_obj = pv.PolyData(
        mesh.vertices, np.concatenate([np.full((mesh.faces.shape[0], 1), mesh.faces.shape[1]), mesh.faces], axis=1)
    )
    tet = tetgen.TetGen(pv_obj)
    # Build and apply the switches string directly, since
    # the Python wrapper sometimes ignores certain kwargs
    # (e.g. maxvolume). See: https://github.com/pyvista/tetgen/issues/24
    switches = make_tetgen_switches(tet_cfg)
    verts, elems, *_ = tet.tetrahedralize(switches=switches)
    # visualize_tet(tet, pv_obj, show_surface=False, plot_cell_qual=False)
    return verts, elems


def visualize_tet(tet, pv_data, show_surface=True, plot_cell_qual=False):
    grid = tet.grid
    if show_surface:
        grid.plot(show_edges=True)
    else:
        # get cell centroids
        cells = grid.cells.reshape(-1, 5)[:, 1:]
        cell_center = grid.points[cells].mean(axis=1)

        # extract cells below the 0 xy plane