1

I want to subdivide an edge that is sedected in edit mode and move the newly created vertices after computing position in python.

I can easily create the new vertices with

bpy.ops.mesh.subdivide(number_cuts=self.nbcuts)

How can I retrieve the list of the newly created vertices ?

Penbeuz
  • 111
  • 5

2 Answers2

4

Use bmesh

To keep tabs on mesh elements recommend using bmesh

Most mesh operators have their bmesh equivalent.

In this case bmesh.ops.subdivide_edges

The bonus of bmesh operators is they return new geometry.

Test method, 1 cut subdivide on all edges.

import bpy
import bmesh

context = bpy.context

ob = context.object
me = ob.data

bm = bmesh.new()
bm.from_mesh(me)

print(me.name) 
print("Before subd")

for e in bm.faces[:] + bm.edges[:] + bm.verts[:]:
    print(e)

ret = bmesh.ops.subdivide_edges(bm,
        edges=bm.edges,
        cuts=1,
        use_grid_fill=True)

for k, v in ret.items():
    print(k)
    for e in v:
        print(e)

bm.to_mesh(me)
me.update() 

Result of running on default "Plane" mesh

enter image description here Before (left) 1 face 4 edges 4 verts and after 4 faces, 12 edges and 9 verts.

Plane.001
Before subd
<BMFace(0x7f3c16a24010), index=0, totverts=4>
<BMEdge(0x7f3c127b3010), index=0, verts=(0x7f3c1232f080/2, 0x7f3c1232f010/0)>
<BMEdge(0x7f3c127b3060), index=1, verts=(0x7f3c1232f010/0, 0x7f3c1232f048/1)>
<BMEdge(0x7f3c127b30b0), index=2, verts=(0x7f3c1232f048/1, 0x7f3c1232f0b8/3)>
<BMEdge(0x7f3c127b3100), index=3, verts=(0x7f3c1232f0b8/3, 0x7f3c1232f080/2)>
<BMVert(0x7f3c1232f010), index=0>
<BMVert(0x7f3c1232f048), index=1>
<BMVert(0x7f3c1232f080), index=2>
<BMVert(0x7f3c1232f0b8), index=3>
geom_inner
<BMVert(0x7f3c1232f0f0), index=4>
<BMVert(0x7f3c1232f128), index=5>
<BMVert(0x7f3c1232f160), index=6>
<BMVert(0x7f3c1232f198), index=7>
<BMVert(0x7f3c1232f1d0), index=8>
<BMEdge(0x7f3c127b3290), index=8, verts=(0x7f3c1232f1d0/8, 0x7f3c1232f198/7)>
<BMEdge(0x7f3c127b32e0), index=9, verts=(0x7f3c1232f128/5, 0x7f3c1232f1d0/8)>
<BMEdge(0x7f3c127b3330), index=10, verts=(0x7f3c1232f1d0/8, 0x7f3c1232f0f0/4)>
<BMEdge(0x7f3c127b3380), index=11, verts=(0x7f3c1232f160/6, 0x7f3c1232f1d0/8)>
<BMFace(0x7f3c16a24048), index=1, totverts=4>
<BMFace(0x7f3c16a24080), index=2, totverts=4>
<BMFace(0x7f3c16a240b8), index=3, totverts=4>
geom_split
<BMVert(0x7f3c1232f0f0), index=4>
<BMVert(0x7f3c1232f128), index=5>
<BMVert(0x7f3c1232f160), index=6>
<BMVert(0x7f3c1232f198), index=7>
<BMEdge(0x7f3c127b3010), index=0, verts=(0x7f3c1232f0f0/4, 0x7f3c1232f010/0)>
<BMEdge(0x7f3c127b3060), index=1, verts=(0x7f3c1232f128/5, 0x7f3c1232f048/1)>
<BMEdge(0x7f3c127b30b0), index=2, verts=(0x7f3c1232f160/6, 0x7f3c1232f0b8/3)>
<BMEdge(0x7f3c127b3100), index=3, verts=(0x7f3c1232f198/7, 0x7f3c1232f080/2)>
<BMEdge(0x7f3c127b3150), index=4, verts=(0x7f3c1232f080/2, 0x7f3c1232f0f0/4)>
<BMEdge(0x7f3c127b31a0), index=5, verts=(0x7f3c1232f010/0, 0x7f3c1232f128/5)>
<BMEdge(0x7f3c127b31f0), index=6, verts=(0x7f3c1232f048/1, 0x7f3c1232f160/6)>
<BMEdge(0x7f3c127b3240), index=7, verts=(0x7f3c1232f0b8/3, 0x7f3c1232f198/7)>
geom
<BMVert(0x7f3c1232f0f0), index=4>
<BMVert(0x7f3c1232f128), index=5>
<BMVert(0x7f3c1232f160), index=6>
<BMVert(0x7f3c1232f198), index=7>
<BMVert(0x7f3c1232f1d0), index=8>
<BMEdge(0x7f3c127b3010), index=0, verts=(0x7f3c1232f0f0/4, 0x7f3c1232f010/0)>
<BMEdge(0x7f3c127b3060), index=1, verts=(0x7f3c1232f128/5, 0x7f3c1232f048/1)>
<BMEdge(0x7f3c127b30b0), index=2, verts=(0x7f3c1232f160/6, 0x7f3c1232f0b8/3)>
<BMEdge(0x7f3c127b3100), index=3, verts=(0x7f3c1232f198/7, 0x7f3c1232f080/2)>
<BMEdge(0x7f3c127b3150), index=4, verts=(0x7f3c1232f080/2, 0x7f3c1232f0f0/4)>
<BMEdge(0x7f3c127b31a0), index=5, verts=(0x7f3c1232f010/0, 0x7f3c1232f128/5)>
<BMEdge(0x7f3c127b31f0), index=6, verts=(0x7f3c1232f048/1, 0x7f3c1232f160/6)>
<BMEdge(0x7f3c127b3240), index=7, verts=(0x7f3c1232f0b8/3, 0x7f3c1232f198/7)>
<BMEdge(0x7f3c127b3290), index=8, verts=(0x7f3c1232f1d0/8, 0x7f3c1232f198/7)>
<BMEdge(0x7f3c127b32e0), index=9, verts=(0x7f3c1232f128/5, 0x7f3c1232f1d0/8)>
<BMEdge(0x7f3c127b3330), index=10, verts=(0x7f3c1232f1d0/8, 0x7f3c1232f0f0/4)>
<BMEdge(0x7f3c127b3380), index=11, verts=(0x7f3c1232f160/6, 0x7f3c1232f1d0/8)>
<BMFace(0x7f3c16a24010), index=0, totverts=4>
<BMFace(0x7f3c16a24048), index=1, totverts=4>
<BMFace(0x7f3c16a24080), index=2, totverts=4>
<BMFace(0x7f3c16a240b8), index=3, totverts=4>

The only 4 elements to survive unscathed from the operator are the original four corner verts. They appear not in the return geometry. All other geom has been altered in some way and is spread across the three options geom_inner, geom_split, geom. I leave it to you to decipher what each is.

look nice but how do I extract the initial edge I want to work on? everything seems selected when i iterate on bm.edges.

Yes, bm.edges is all edges in the bmesh. Can feed any subset list of edges into operator.

Another example, run in edit mode, make sure you are in edge select mode, have an active edge selected.

If so, Makes 5 cuts in edge, loops thru and prints return geometry as above.

import bpy
import bmesh

context = bpy.context

ob = context.edit_object
me = ob.data

bm = bmesh.from_edit_mesh(me)
# selected edges
selected_edges = [e for e in bm.edges if e.select]
# active edge (from active selection)
active_edge = bm.select_history.active
# make sure active element is edge
assert(isinstance(active_edge, bmesh.types.BMEdge))

ret = bmesh.ops.subdivide_edges(bm,
        edges=[active_edge],
        cuts=5,
        )

for k, v in ret.items():
    print(k)
    for e in v:
        #e.select = True
        print(e)

bmesh.update_edit_mesh(me) 
batFINGER
  • 84,216
  • 10
  • 108
  • 233
  • look nice but how do I extract the initial edge I want to work on? everything seems selected when i iterate on bm.edges. – Penbeuz May 13 '20 at 16:29
0

I was able to find the solution with these two answers this and this

obj=bpy.context.object
# Get the currently select object

if obj.mode == 'EDIT':

    bpy.ops.mesh.subdivide(number_cuts=5)
    #cree de nouveaux vertex avec subdivide

    bpy.ops.object.mode_set(mode='OBJECT')
    # Go into object mode to update the selected vertices
    bpy.ops.object.mode_set(mode='EDIT')

    for ind in [i.index for i in obj.data.vertices if i.select]:
        # Loop over each currently selected vertex
        v = obj.data.vertices[ind]
        print('Vertex {} at local position {}, world position {} is selected'.format(v.index, v.co, obj.matrix_world @ v.co))
else:
    print("Object is not in edit mode.")
return({"FINISHED"})
Penbeuz
  • 111
  • 5