Mesh Cutting Functionality in SpecklePy

We’re currently exploring the capabilities of SpecklePy within our Building.py (GitHub - 3BMLabs/building.py: Python Library for creating buildings, building systems, objects, and exporting to various programs like Blender, Revit, Speckle.) environment and have come across a specific requirement. We’re wondering if it’s possible to cut a mesh using another mesh directly within SpecklePy.

We’re keen to understand if there’s a built-in functionality or method in SpecklePy that allows for mesh cutting operations. If anyone has experience or insights on how to achieve this, we’d greatly appreciate your guidance.

Any code examples or documentation references on this topic would be immensely helpful for us to integrate mesh cutting functionality into our workflow effectively.

There is little to no geometry processing within specklepy. (or speckle-sharp)

For the clash detection demo for Automate, I used a combination of Trimesh and PyMesh (with its C++ counterpart) to perform various Mesh manipulations. SpecklePy plays nicely enough with each, but there is a need to translate the Speckle Mesh definition to a more typical one:

import numpy as np
import trimesh

def speckle_mesh_to_trimesh(input_mesh: SpeckleMesh) -> \
        trimesh.Trimesh:
    vertices = np.array(input_mesh.vertices)\
        .reshape((-1, 3))
    faces = []

    i = 0
    while i < len(input_mesh.faces):
        face_vertex_count = input_mesh.faces[i]
        i += 1  # Skip the vertex count

        # Direct use of indices for face_vertex_indices
        face_vertex_indices = \
            input_mesh.faces[i: i + face_vertex_count]

        if face_vertex_count == 3:
            # For triangular faces, append directly
            faces.append(face_vertex_indices)
        else:
            # Convert indices to Vector only when necessary
            face_vertices = \
                [Vector.from_list(vertices[idx].tolist()) \
                 for idx in face_vertex_indices]
            
            # Assume triangulate_face returns indices
            triangulated = triangulate_face(face_vertices)
            faces.extend(triangulated)

        i += face_vertex_count

    t_mesh = trimesh.Trimesh(vertices=vertices, 
                             faces=np.array(faces))
    return t_mesh

This was written to accept Speckle data sources that utilised NGons, and thus, the triangulation step was necessary as TriMesh doesn’t support this (as suggested by its name, I suppose)

Other helpers in that demo are simple casst from one format to another so toTrimesh() toSpeckleMesh() and toPyMesh() should be compact.