# Thread: Help needed: Boolean Union of many objects

1. ## Help needed: Boolean Union of many objects

Hello, I have to Boolean Union ca. 150 objects. I have code (below) that works very well on lists of 10-20 selected objects. But if the object count is higher, then Blender calculates forever. Therefor I would like to split the 150-object-list into ca. 10 15-object-lists. Only a pretty small modification of the code below is needed - how can I do this best please? Many thanks!

Here is the code I have already:

##START “UNION OF SELECTED OBJECTS”:
sce = bpy.context.scene
myobjectlistlength = len(bpy.context.selected_objects)
bpy.context.selected_objects[0].name
myobjectlistlength
for index in range(0, myobjectlistlength):
print (index)
bpy.context.selected_objects[index].name

originalunionobject = sce.objects.get(bpy.context.selected_objects[0].name)
originalunionobject_name = bpy.context.selected_objects[0].name
mymodifier = originalunionobject.modifiers.new('mymodifier', 'BOOLEAN')
mymodifier.operation = 'UNION'
nextobject = sce.objects.get(bpy.context.selected_objects[1].name)
mymodifier.object = nextobject
bpy.context.scene.objects.active = originalunionobject
bpy.ops.object.modifier_apply(apply_as='DATA', modifier="mymodifier")

for index in range(0, myobjectlistlength-2):
print (index)
sce = bpy.context.scene
##we always just retrieve the new next element with index 1, because the list gets
##shorter and shorter with each new union:
bpy.context.selected_objects[1].name
myobjectlistlength
index+1
mymodifier = originalunionobject.modifiers.new('mymodifier', 'BOOLEAN')
mymodifier.operation = 'UNION'
nextobject = sce.objects.get(bpy.context.selected_objects[1].name)
mymodifier.object = nextobject
bpy.context.scene.objects.active = originalunionobject
bpy.ops.object.modifier_apply(apply_as='DATA', modifier="mymodifier")
##END “UNION OF SELECTED OBJECTS”

2. Hi chrissie,

to markup code in the forum wrap it in [code][/code] tags.

The object.join operator may be a simpler way to do this.

Code:
```import bpy

# join them
bpy.ops.object.join()```

afterwards you may wish to remove doubles with

Code:
```bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.remove_doubles()```

3. @batFINGER - he wants boolean union, not just simply joining objects.

@chrissie - without wraping the code in the tags batFINGER mentions, we cant tell where the indents are and thus cant help. Or you could upload to pasteall.org.

I've been wanting something like this for a long time, but been to lazy to try code it

4. Originally Posted by gregzaal
@batFINGER - he wants boolean union, not just simply joining objects.

@chrissie - without wraping the code in the tags batFINGER mentions, we cant tell where the indents are and thus cant help. Or you could upload to pasteall.org.

I've been wanting something like this for a long time, but been to lazy to try code it
I'm aware of the difference @gregzaal.

I'm Not sure how much of an improvement would be achieved by splitting the list into smaller parts. If there is no intersection then join would be alot quicker to achieve the same result. Even changing the originally posted code with a simple bounding box intersection test to either join or add and apply modifier would speed it up IMO. Splitting the list into non intersecting sets, joining then using union would be my suggestion. Surely each and all of the 150 objects don't intersect each other.

5. Great idea. Best would be to try join all the non-intersecting objects into just a few objects first, only then doing the boolean.

6. ## Need for multiple boolean connection script or process help.

I too have this need.
What I have is a bunch (appx 200) of spheres and cylinders that I need to boolean together (like a molecule). Unfortunately I cannot join them and boolean them because they are randomly indexed.
here's a picture (and a closeup) for example:

smallsphere1.PNG smallsphere1 closeup.PNG

Sorry for the dreadful lighting. So each cylinder and each sphere are disconnected objects, and the cylinders "penetrate" into the spheres. I have tried some code snippets suggested by others but none comes close.

What I'm thinking is to somehow, starting with any randomly chosen sphere, to sequentially boolean every connecting cylinder, then proceed to iteratively repeat this process until everything's connected. Unfortunately since i'm new to blender scripting and python i'm crazy stuck.

Any help appreciated.

7. hm... if there was a way to add vertices on edges at intersection points, one could do that and then select only the outside vertices, invert selection and delete verts

8. Hi! Here is what I created / used ("quick and dirty", but it works for me):

Code:
```##START “UNION OF SELECTED OBJECTS”:
sce = bpy.context.scene
myobjectlistlength = len(bpy.context.selected_objects)
bpy.context.selected_objects[0].name
myobjectlistlength
for index in range(0, myobjectlistlength):
print (index)
bpy.context.selected_objects[index].name

originalunionobject = sce.objects.get(bpy.context.selected_objects[0].name)
originalunionobject_name = bpy.context.selected_objects[0].name
mymodifier = originalunionobject.modifiers.new('mymodifier', 'BOOLEAN')
mymodifier.operation = 'UNION'
nextobject = sce.objects.get(bpy.context.selected_objects[1].name)
mymodifier.object = nextobject
bpy.context.scene.objects.active = originalunionobject
bpy.ops.object.modifier_apply(apply_as='DATA', modifier="mymodifier")

# for index in range(0, 10):
for index in range(0, myobjectlistlength-2):
print (index)
sce = bpy.context.scene
##we always just retrieve the new next element with index 1, because the list gets
##shorter and shorter with each new union:
bpy.context.selected_objects[1].name
myobjectlistlength
index+1
mymodifier = originalunionobject.modifiers.new('mymodifier', 'BOOLEAN')
mymodifier.operation = 'UNION'
nextobject = sce.objects.get(bpy.context.selected_objects[1].name)
mymodifier.object = nextobject
bpy.context.scene.objects.active = originalunionobject
bpy.ops.object.modifier_apply(apply_as='DATA', modifier="mymodifier")
##END  “UNION OF SELECTED OBJECTS```
You first select all objects to boolean union.
Then execute the code in the python console.

I once had a memory problem when I wanted to boolean union too many objects in one go.
I created a variant of the code which 1st unioned in chunks of 15, then unioned those.
Let me know if you need this.

Let me know if you have questions.

9. Ahoi,

got it triggered out how to Union boolean many objects:

#!BPY
"""
Name: 'Muli Boolean Union'
Blender: 242
Group: 'Misc'
Tooltip: 'trying'
"""
from Blender import *
from Blender import Draw, Scene, Object
from Blender.Mathutils import Rand
# runs through all objects and boolean:union them together
def supb(scn, sel):
i = 0
for objss in sel:
if i == 0:
objFirst = objss
i = 1
else: # i == 1
if i == 1:
objSecond = objss
i = 2

mods = objFirst.modifiers # adding a modifier
mod = mods.append(Modifier.Types.BOOLEAN) # with boolean
mod[Modifier.Settings.OPERATION] = 1 # and union

# doing the modifier
mod[Modifier.Settings.OBJECT] = objSecond # adding the element to the modifier
objFirst.makeDisplayList() # doing the modifier

# deleting the old two
# scn.unlink( objFirst )
else:
i = 3
Window.RedrawAll() #??

def main():
scn = Scene.GetCurrent()
if not scn.objects.context:
return

sel = scn.objects.context
objects = [ob for ob in scn.objects.context]
Count = len(objects)
# i = 0
# while i < 10:
# i = i + 1
f = Count
for i in range(0, f):
supb( scn, sel )
sel = scn.objects.context

Window.RedrawAll()

if __name__ == '__main__':
main()

-------------------

also here is a script, which Looks good...was not working with me:

http://www.mediafire.com/view/7d8kv9...ion+script.txt

have fun

10. This question is old but maybe some people still want this and end up here.

A quite easy, non scripting solution is:

1. join all meshes you want to union
2. draw a large cube around it, that contains all your joined meshes.
3. apply a boolean operator "intersect" on this cube and your joined mesh

Seems to work!

11. Originally Posted by raymondnijssen
This question is old but maybe some people still want this and end up here.

A quite easy, non scripting solution is:

1. join all meshes you want to union
2. draw a large cube around it, that contains all your joined meshes.
3. apply a boolean operator "intersect" on this cube and your joined mesh

Seems to work!

raymondnijssen...you're the best!!!!!!

I haven't tried it in complex figures but it seems to work perfectly!!!!!! AWESOME

12. The idea is really perfect. And I just tried on some complex meshes... it seems that part of the object is missing.
input.jpgoutput.jpg
I'll try the script way soon, maybe it won't work either.

13. The script way is not working either. Here's my code, it maybe helpful to someone sometime.
Code:
```loopCategoryNum = [50, 776]
loopCategory = ["ball", "cylinder"]
basePath = "E:/Coding/skeleton_code/skeleton_code/bin/Mesh/"

for categoryIndex in range(len(loopCategory)):
loopIndex = int((loopCategoryNum[categoryIndex]-1)/50)
for i in range(loopIndex+1):
bpy.ops.import_scene.obj(filepath = basePath + loopCategory[categoryIndex] + str(i*50) + ".obj")
para1 = bpy.data.objects[loopCategory[categoryIndex] + str(i*50)]
bpy.context.scene.objects.active = para1
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.object.mode_set(mode='OBJECT')
for j in range(i*50+1,i*50+50):
if j>=loopCategoryNum[categoryIndex]:
break
bpy.ops.import_scene.obj(filepath = basePath + loopCategory[categoryIndex] + str(j) + ".obj")
para2 = bpy.data.objects[loopCategory[categoryIndex] + str(j)]
bpy.context.scene.objects.active = para2
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.object.mode_set(mode='OBJECT')
bpy.context.scene.objects.active = para1
boolean_modifier = para1.modifiers.new('Name', 'BOOLEAN')
boolean_modifier.operation = 'UNION'
boolean_modifier.object = para2
bpy.ops.object.modifier_apply(apply_as='DATA', modifier = 'Name')
bpy.context.scene.objects.active = para2
bpy.ops.object.delete()
#if i!=0:
#para2 = bpy.data.objects[loopCategory[categoryIndex] + str(i*50-50)]
#bpy.context.scene.objects.active = para1
#boolean_modifier = para1.modifiers.new('Name', 'BOOLEAN')
#boolean_modifier.operation = 'UNION'
#boolean_modifier.object = para2
#bpy.ops.object.modifier_apply(apply_as='DATA', modifier = 'Name')
The commented code is not working, but I think the problems come from blender's boolean operation itself.
(I try to manually combine those segments, blender(2.76) tells me it can not excute bool operation)

update: I come up with a new idea!!! We can first do the "difference boolean operation" between each pair (as the pre processing). To ensure every two segments are not collided.

14. Originally Posted by tcdoe

What I'm thinking is to somehow, starting with any randomly chosen sphere, to sequentially boolean every connecting cylinder, then proceed to iteratively repeat this process until everything's connected. Unfortunately since i'm new to blender scripting and python i'm crazy stuck.

Any help appreciated.
I realize this is old, but I came across the thread when I need to do the same thing (for a ball and stick molecular model). Taking pieces from other scripts I came up with something that does exactly this. It uses the selected objects so if you start with something that has many objects (I've used it on structures with ~1200 objects imported as VRML2) it can be faster to select it in chunks instead of trying to do it all in one pass. Also, make sure there are no internal objects. PyMol stick representations always put out extra spheres at the end.

Code:
```import bpy
import bmesh
from mathutils.bvhtree import BVHTree

def bmesh_copy_from_object(obj, transform=True, triangulate=True, apply_modifiers=False):
"""
Returns a transformed, triangulated copy of the mesh
"""

assert(obj.type == 'MESH')

if apply_modifiers and obj.modifiers:
me = obj.to_mesh(bpy.context.scene, True, 'PREVIEW', calc_tessface=False)
bm = bmesh.new()
bm.from_mesh(me)
bpy.data.meshes.remove(me)
else:
me = obj.data
if obj.mode == 'EDIT':
bm_orig = bmesh.from_edit_mesh(me)
bm = bm_orig.copy()
else:
bm = bmesh.new()
bm.from_mesh(me)

# Remove custom data layers to save memory
for elem in (bm.faces, bm.edges, bm.verts, bm.loops):
for layers_name in dir(elem.layers):
if not layers_name.startswith("_"):
layers = getattr(elem.layers, layers_name)
for layer_name, layer in layers.items():
layers.remove(layer)

if transform:
bm.transform(obj.matrix_world)

if triangulate:
bmesh.ops.triangulate(bm, faces=bm.faces)

return bm

def bmesh_check_intersect_objects(obj, obj2):
"""
Check if any faces intersect with the other object

returns a boolean
"""
assert(obj != obj2)

# Triangulate
bm = bmesh_copy_from_object(obj, transform=True, triangulate=True)
bm2 = bmesh_copy_from_object(obj2, transform=True, triangulate=True)
intersect = False
BMT1 = BVHTree.FromBMesh(bm)
BMT2 = BVHTree.FromBMesh(bm2)
overlap_pairs = BMT1.overlap(BMT2)
#print (len(overlap_pairs))

if len(overlap_pairs) > 0:
intersect = True

return intersect

sce = bpy.context.scene

myobjectlistlength = len(bpy.context.selected_objects)
startlist = len(bpy.context.selected_objects)
i = 0

while i < myobjectlistlength or myobjectlistlength > 1:
sce.update()
obj1 = bpy.context.selected_objects[0]

for obj2 in bpy.context.selected_objects:
if obj1.name == obj2.name:
continue
#print(obj1.name)
#print(obj2.name)
intersect = bmesh_check_intersect_objects(obj1, obj2)

if intersect:
mymodifier = obj1.modifiers.new('mymodifier', 'BOOLEAN')
mymodifier.operation = 'UNION'
mymodifier.object = obj2
bpy.context.scene.objects.active = obj1
bpy.ops.object.convert(target='MESH')
myobjectlistlength = len(bpy.context.selected_objects)
print("Objects left to merge: %s" % myobjectlistlength)

i = i+1```

15. Originally Posted by raymondnijssen
This question is old but maybe some people still want this and end up here.

A quite easy, non scripting solution is:

1. join all meshes you want to union
2. draw a large cube around it, that contains all your joined meshes.
3. apply a boolean operator "intersect" on this cube and your joined mesh

Seems to work!
This seemed like a great idea, but it didn't work for me. The places where the once individual objects meet don't result in joined vertices after the intersection. This had implications down the road for 3D printing.

16. There is now an add-on included in Blender by default (2.78): https://wiki.blender.org/index.php/D..._Boolean_Tools

17. Originally Posted by shocksofmighty
This seemed like a great idea, but it didn't work for me. The places where the once individual objects meet don't result in joined vertices after the intersection. This had implications down the road for 3D printing.
I actually tried this again, realizing that I hadn't attempted it after removing the fully internal spheres that were in my object. After removing the internal spheres it worked great! Now I'm feeling silly or spending so much time writing that script.

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•