# Cleaning script to cut face edges

I made a script to subdivide the edges of the object faces depending on their length (if edge 0 > edge 1, cut edge 0 n times, and vice versa, being n relative to edge’s length).

I got it working, but there is something I’m not seeing or understanding, in the first part of the script I'm adding in a variable the number of faces the object has and in the second part the edges are subdivided, but in order for the first part to work, I need to add extra steps that are apparently unnecessary. Can someone help me clean this? I’m a noob but I would love to learn and have a tight script, so any advice to make it cleaner / smoother would be great.

PD, having iter = len(bm.faces) won’t work because as soon as you make a cut, a new face is added, so it becomes an infinite loop.

Here's my code:

import bpy
import bmesh
import time

start = time.time()

bpy.ops.mesh.select_mode(type="FACE") # set face selection mode

ob = bpy.context.active_object
me = ob.data
bm = bmesh.from_edit_mesh(me)

length = 2   # length comparison between edges
cutMulti = .008   # higher n = more cuts

cutN = 0
i = 0
iter = 0

# get n of faces, ***just a "for f in bm.faces: iter += 1" won't work***

for f in bm.faces:
f.select_set(False)
e_0 = f.edges[0].calc_length()
e_1 = f.edges[1].calc_length()
if e_0 > e_1:
cutN = int(e_0*cutMulti)
if e_0 / e_1 > length:
f.edges[0].select_set(True)
f.edges[2].select_set(True)
if e_0 < e_1:
cutN = int(e_1*cutMulti)
if e_1 / e_0 > length:
f.edges[1].select_set(True)
f.edges[3].select_set(True)
iter += 1

# Face cuts

for f in bm.faces:
if i < iter:
e_0 = f.edges[0].calc_length()
e_1 = f.edges[1].calc_length()
if e_0 > e_1:
cutN = int(e_0*cutMulti)
if e_0 / e_1 > length:
f.edges[0].select_set(True)
f.edges[2].select_set(True)
if e_0 < e_1:
cutN = int(e_1*cutMulti)
if e_1 / e_0 > length:
f.edges[1].select_set(True)
f.edges[3].select_set(True)
selected_edges = [edge for edge in bm.edges if edge.select]
bmesh.ops.subdivide_edges(bm, edges=selected_edges, cuts=cutN)
selected_edges.clear()
for e in f.edges:
e.select_set(False)
bm.select_flush_mode()
i += 1

bmesh.update_edit_mesh(me, True)

print (str("iterations completed = "), iter)
print (str("lenght comparison = "), length)
print (str("cut multiplier = "), cutMulti)
print (str("processing time = "), time.time()- start)



Do a while pop().

Check out the answer here, shows the return geometry of running bmesh subdivide edges operator. Iterate with python on vertices created by subdividing an edge

Notice the geom_inner returns the 3 newly created faces of the one cut subdivided plane. Could use sets to check the difference before and after.

Also note the original faces are not lost in the process. Some bmesh ops are destructive. It appears sub edges builds on input geometry.

For your example, rather than counting the iter could simply copy the faces before, and do a while pop

faces = bm.faces[:]
while faces:
f = faces.pop()
# op


btw there is no need to use a selection here, simply collect the edges

edges = []
e = face.edges[0]
if e is interesting:
edges.append(e)


and feed edges into the operator. Unless using a bpy.ops.mesh operator there is often very little reason to use selection... unless the select is part of the desired result. Note there is also a more temporary tag property.

No need to cast strings to strings

print(str("string")) # not required
print("string") will do.

• Thanks, worked perfectly! – tach May 17 '20 at 17:26