Refreshing BMesh Object After Merge/Split

I am trying to make a mesh cleanup tool for STL’s with poor connectivity, but cannot figure out how to refresh the bmesh object after splitting edges and merging nodes. I split the edges, then try and refresh but get a “BMesh object BMVerts has been removed” error or get the error telling me to use “ensure_lookup_table()”. Nothing seems to update the verts and I get stuck before the vert merger (the last vert created is supposed to merge to the current vert after edge splitting).

Can someone tell me how to refresh a bmesh object after mesh modification? I have tried everything on the internet short of exiting to object mode (but I am afraid that this will reorder the mesh objects, and cause me to lose track of the vert I need to merge; From what I can tell the last created vert simply gets appended to the list…).

Any help or insight would be appreciated.

Some code showing what you have done would help but


bm.verts.remove(bm.verts[10])
bm.verts.ensure_loopup_table()

Also for edges, faces and loops as needed.

ensure_lookup_table is needed for accessing the vertices by index, which is the fasted method.

Hint, if removing many vertices, collect them remove them and then run ensure_lookup_table()

Ah, alright. I never was able to find it used in such a way. I am literally splitting and edge, and then merging verts based on a criterion after getting the non-manifold edges, i.e.:


#HERE IS THE GIST OF MY CODE...

#LOOP THROUGH BMESH ENDLESSLY TILL I RESOLVE ALL NONMANIFOLD EDGES
while True:
   #GATHER NONMANIFOLD EDGES IN A LIST
   nonmanifold = []
   nonmanifold = get_non_manifold()
   #STOP WHEN I HAVE NO MORE NONMANIFOLD EDGES
   if nonmanifold == []:
      break
   #GO THROUGH THE NONMANIFOLD EDGES AND FIND THE EDGE THAT 
   #BEST FITS THE CRITERIA FOR BEING AN EDGE PAIR, USE THE FIRST 
   #EDGE IN THE LIST AS A BASE FOR THE PAIRING
   current_pair = None
   for i in range(0, len(nonmanifold)-1):
       if i == 0:
         continue
       if edgePair(nonmanifold[0], nonmanifold<i>)
          current_pair = mark_geometry()
   #IF WE FIND AN EDGE THAT FITS THE CRITERIA 
   #SPLIT IT AND MERGE THE NEIGHBORING VERT TO FORM AN N-GON
   #AND REPAIR THE NON-MANIFOLD EDGE...
   if current_pair != None:
      selected = select_edge(edge)
      bpy.ops.mesh.subdivide()
      #HERE IS WHERE THINGS GO BADLY
      selected = select_verts(verts[0], verts[1])
      bpy.ops.mesh.merge(type='LAST')


So does ensure_lookup_table() require an arg: ensure_lookup_table(verts[i])? or is it a class based operator like: mesh.verts[i].ensure_lookup_table()?

Would I supply the verts created from the subdivide and those removed from the merger, and if so how do I keep the knowledge of which verts was removed/created[I]…I’m assuming that the id’s cannot be duplicated…but this is an assumption especially during merger.

ensure_lookup_table() is a method for the various sequences of elements inside a bmesh, vertices, edges, faces and loops.


bm = bmesh.from_edit_mesh(mesh)
bm.verts.ensure_lookup_table()

However in the code above there is no example of using the bmesh module and instead you use by.ops.mesh.merge which doesn’t work on the bmesh but instead works on the active edit mesh.
however the errors you provide comes from the bmesh module. it is hard to help more without seeing the whole picture.

However in the code above there is no example of using the bmesh module and instead you use by.ops.mesh.merge which doesn’t work on the bmesh but instead works on the active edit mesh.

Ah, this is probably where I’m getting stuck. I’m not sure what the difference is between the two constructs (from what I gather there are two constructs BMesh and Mesh??). I’m assuming that the BMesh and active edit mesh are the same until changes are made? How do the two differ? Is there a way to operate on the other to avoid the issue?

I’ll try and get the real code up here ASAP.

Thanks.