Cut BMesh with python Goal:  Efficiently cut out (holes) or trim off regions of dense meshes defined by editable polyline or bezier curves which are snapped to a mesh surface.

Uses:  


My narrow use is to cut teeth out of scanned model data.
Cut meshes data into articulating parts to print models larger than 3d print volumes
Cleaning boundaries of 3d scanned data
Cut holes in meshes (see the 10 or so related questions here)


Related Topics:


Standard Knife tool:
Cons:  No way to edit cut path once clicked, slow on dense meshes, sometimes skips faces.
Knife Project:
Cons: Doesn't always work if not a good view path or on dense triangle meshes.  Here you can see the result with a bezier I manually paced on surface (visualized with a thickness) and the cut from knife project.

Grease Cutter:  Cons:  Uses boolean
Sculpt Trim:  Cons:  Not implemented, cut not editable


Progress


I have written a simple user interface for defining the desired cut path.

The segment intersections are calculated and previewed.  Segments which failed to successfully cut are displayed in red, so the cut can be altered.



I now have a list of edges in the oringal Bmesh, and corresponding intersection points.  And to finish "cutting" I need to split those edges at the intersection points (create new verts), connect the new verts with new edges.  Optionally, split the new edges to actually separate a piece of the mesh.



Problem

This method has been extremely slow.  >2 minutes.  Calculating the cut locations for this example was instantaneous.

    for v, ed in zip(new_cos, ed_map):
        ed_pcts = {}
        ed_pcts[ed] = .5   
        geom = bmesh.ops.bisect_edges(bm, edges = [ed],cuts = 1,edge_percents = ed_pcts)
        geom['geom_split'][0].co = v
        new_verts += [geom['geom_split'][0].index]

    for i in range(0,len(new_verts)):
        bm.verts.ensure_lookup_table()
        v_pair = [bm.verts[new_verts[i]], bm.verts[new_verts[i-1]]]
        ed_geom = bmesh.ops.connect_vert_pair(bm, verts = v_pair, verts_exclude = [], faces_exclude = [])`



using mesh.ops.bisect_edges and passing in all of my edges, and then simply passing all of the new vertices to bmesh.ops.connect_verts vastly improves the performace, however I have not been able to get the edge_percents argument for bmesh.ops.bisect_edges to work. It seems to be completely ignored.  Cut's really fast, but doesn't cut in the right place, it just bisects the intersected edges at the midpoint.
This code snippet assumes some existing variables which were pre-calculated

'''
bme     : blender BMesh
ed_map  : all the edges to be bisected into 2 edges
new_cos : desired positions of bisection, in same order as ed_map
'''

geom =  bmesh.ops.bisect_edges(self.bme, 
                               edges = ed_map,
                               cuts = 1,
                               edge_percents = {})

new_bmverts = [ele for ele in geom['geom_split'] if isinstance(ele, bmesh.types.BMVert)]

#assign the locations to the new vertices, which were automatically
#placed at edge midpoints
for v, co in zip(new_bmverts, new_cos):
        v.co = co

#connect the new vertices, to cut across the individual faces
ed_geom = bmesh.ops.connect_verts(bme, 
                                  verts = new_bmverts, 
                                  faces_exclude = [], 
                                  check_degenerate = False)
new_edges = ed_geom['edges']

#optionally, split the new edges, to make 2 separate mesh pieces
bme.verts.ensure_lookup_table()
bme.edges.ensure_lookup_table()
bmesh.ops.split_edges(bme, edges = new_edges, verts = [], use_verts = False)