I have a script which takes an SVG path, converts it to a mesh, joins all the edges together, extrudes it, and adds the missing faces. It then reads in a CNC drill file and drills holes in the mesh using a cylinder and the boolean DIFFERENCE operator.
As it stands, it works. However it starts out nice and quick, but rapidly each boolean operation starts to take longer and longer, ending up as a couple of seconds per operation.
The boolean section of the script I found somewhere online (I can't find where now), so I assume it's the right way to do it. But it may not be. So I'd like some pointers or ideas on how it can be sped up.
Here's the core of the script where the boolean work is done:
bpy.ops.mesh.primitive_cylinder_add()
bit = bpy.context.object
bit.name="Drill Bit"
bit.dimensions=[4,4,10]
def subtract(target, opObj):
'''subtract opObj from the target'''
# Deselect All
bpy.ops.object.select_all(action='DESELECT')
# Select the new object.
target.select = True
bpy.context.scene.objects.active = target
# Add a modifier
bpy.ops.object.modifier_add(type='BOOLEAN')
mod = target.modifiers
mod[0].name = "SubEmUp"
mod[0].object = opObj
mod[0].operation = 'DIFFERENCE'
# Apply modifier - I assume this is the bit that is taking a long
# time but I cannot be sure yet.
bpy.ops.object.modifier_apply(apply_as='DATA', modifier=mod[0].name)
for line in content:
if line == '%':
inHeader = False
continue
if inHeader:
# T61C0.300
if line.startswith('T'):
parts = line.split('C')
drills[parts[0]] = float(parts[1])
else:
# T61
if line.startswith('T'):
drillWidth = drills[line]
print("Selecting drill width " + str(drillWidth) + "mm")
bit.dimensions=[drillWidth, drillWidth, 50]
continue
# X009050Y046150
if line.startswith('X'):
coords = line[1:].split('Y')
x = float(coords[0])
y = float(coords[1])
x = x / 1000
y = y / 1000
print("Drilling at " + str(x) + "," + str(y))
bit.location=[x, y, 0]
subtract(pcb, bit)
# I added this to see why the script was taking so long.
bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)
bpy.ops.object.select_all(action='DESELECT')
bit.select = True
bpy.ops.object.delete()
pcb
is the mesh generated earlier.
Is there some way I can "batch up" all the boolean modifiers and perform them all in one operation? Would it be better to make one "drill bit" per hole and locate them all, then join them into one big drill object and subtract that from the main mesh? (would that even work?)
print("blah", x, y)
will be quicker thanprint("Drilling at " + str(x) + "," + str(y))
Best Practices $\endgroup$target.data = target.to_mesh(bpy.context.scene, True, 'PREVIEW')
that is the slowness. Without that it is really fast but, of course, doesn't do anything. I will have a go at stacking the modifiers up. $\endgroup$