# Bmesh : how do I keep track of vertices in edited topology?

I'm trying to write a script to bisect Ngon rectangles, horizontally or vertically, at a given percentage of the distance along their sides. (The sides may consist of more than one edge).

Some of the script involves finding the right edges to cut, and moving the new vertices to the right place, but I hope this is a minimal expression of my problem:

ob = bpy.context.object
me = ob.data
bm = bmesh.new()
bm.from_mesh(me)

bm.edges.ensure_lookup_table()

e1 = bm.edges[4]
e2 = bm.edges[3]

ret = bmesh.ops.subdivide_edges(bm, edges=[e1], cuts=1)
v1 = ret['geom_inner'][0]

ret = bmesh.ops.subdivide_edges(bm, edges=[e2], cuts=1)
v2 = ret['geom_inner'][0]

bmesh.ops.connect_verts(bm, verts=[v1,v2])

bm.to_mesh(me)
me.update()

bm.free()


(Here, I've hard-coded the edge selections)

The bmesh.ops.connect_verts(bm,verts = [v1,v2]) generates an error: '..BMVert has been removed..', which is perhaps understandable, but how would I keep track of v1,the vertex generated by the first cut? If I run this snippet without the connect, the vertices appear just fine in the updated mesh, so they are there, somewhere.

• I'm in 2.79
• The mesh starts in Object Mode (does that make a difference?)
• Consider doing both at once ret = bmesh.ops.subdivide_edges(bm, edges=[e1, e2], cuts=1) – batFINGER Feb 4 '19 at 11:44
• @batFINGER Thanks very much, that works, and makes the new edge... I'm still confused, in general, about how to keep the database in good nick while you're fiddling with its entries.. but maybe just carry on.. i'm used to learning things in a more abstract, systematic way .. – Robin Betts Feb 4 '19 at 13:58

Tag the verts.

As mentioned in the comments could be done via

bmesh.ops.subdivide_edges(bm, edges=[e1, e2], cuts=1)


in one fell swoop.

When an operator creates new geometry there is a chance any old geom becomes invalid. However the data of the old will match the new, in which case can use the tag or select attribute to advantage.

Make sure to ignore the invalids with How to remove dead BMVerts from a list?

Test script. In edit mode to see what is going on.. Will work same in object mode

import bpy
import bmesh
ob = bpy.context.edit_object
me = ob.data

bm = bmesh.from_edit_mesh(me)

bm.edges.ensure_lookup_table()

e1 = bm.edges[0]
e2 = bm.edges[2]

ret = bmesh.ops.subdivide_edges(bm, edges=[e1], cuts=1)
v1 = ret['geom_inner'][0]
v1.tag = True
ret = bmesh.ops.subdivide_edges(bm, edges=[e2], cuts=1)
v2 = ret['geom_inner'][0]
v2.tag = True

bmesh.ops.connect_verts(bm,
verts=[v for v in bm.verts if v.tag and v.is_valid])

bmesh.update_edit_mesh(me)
me.update()


Note in 2.80 a mesh can be in edit mode in one view, object in another.

On a formatting side, in argument list, space after a comma, none around equals.

• This is a great help.. not just for doing this job, but as an aid to learning the system.. seeing what's going on. Greatly appreciated. – Robin Betts Feb 5 '19 at 7:09
• Always a pleasure @RobinBetts – batFINGER Feb 5 '19 at 8:06