After few more tries I am still not able to catch the "Unknown internal error in boolean" exception, however I have found a partial solution which may help to avoid the exception.
The following is useful when you already know that applying a boolean operator on two meshes raises the exception OR when you want to make sure that the boolean operator does not generate a corrupted mesh containing non-manifold elements, this often happens when two or more edges/vertices of the input meshes are overlapping.
In this script I have iteratively applied a small random shift along x-y-z for one of the two input meshes, instead a rotation can also be used. The
scaler parameter is decisive for obtaining a successful boolean operation as the spatial shift applied to the mesh has to be a small percentage of its overall dimension. In this example I have used boolean UNION but the same process applies to boolean DIFFERENCE and INTERSECTION. If the program still does not return a valid mesh you can always increas the number of iterations (
n_attempts)
Code: Select all
#########################################################################################
#
# This code takes two input objects which, as they are located, generate a mesh containing
# non-manifold elements when Boolean Union is applied. One of the two objects is randomly
# shifted in space within a user-defined threshold for a number of iterations until the
# Boolean Operator returns a valid mesh (without non-manifold elements).
#
#########################################################################################
import bpy
import bmesh
import random
from random import *
# Boolean_check = 0 Non-Manifold Found / boolean_check = 1 Non-Manifold NOT Found
boolean_check = 1
#How many times it tries to adjust the objects' location
n_attempts = 50
#This parameter depends on the dimension of the 3D objects
scaler = 0.0000008
#The two objects used for Boolean UNION
object_1 = "Name of first object"
object_2 = "Name of second object"
#Move the objects along the 3 directions
boolean_adjustment_x=[]
boolean_adjustment_y=[]
boolean_adjustment_z=[]
#Prepare random shifts along three axis
for index in range (n_attempts):
boolean_adjustment_x.append(scaler*random())
boolean_adjustment_y.append(scaler*random())
boolean_adjustment_z.append(scaler*random())
#Space shift adjustment Loop
for bool_index in range (n_attempts):
print('Iteration number ' +str(bool_index))
print ('Shift in x is ' +str(boolean_adjustment_x[bool_index]))
print ('Shift in y is ' +str(boolean_adjustment_y[bool_index]))
print ('Shift in z is ' +str(boolean_adjustment_z[bool_index]))
bpy.context.scene.objects.active = bpy.data.objects[bpy.data.objects.find(object_1)]
bpy.data.objects[bpy.data.objects.find(object_1)].select = True
#Temporary copy of first object
bpy.ops.object.duplicate_move(OBJECT_OT_duplicate={"linked":False, "mode":'TRANSLATION'}, TRANSFORM_OT_translate={"value":(boolean_adjustment_x[bool_index], boolean_adjustment_y[bool_index], boolean_adjustment_z[bool_index]), "constraint_axis":(True, True, True), "constraint_orientation":'GLOBAL', "mirror":False, "proportional":'DISABLED', "proportional_edit_falloff":'SMOOTH', "proportional_size":1, "snap":False, "snap_target":'CLOSEST', "snap_point":(0, 0, 0), "snap_align":False, "snap_normal":(0, 0, 0), "texture_space":False, "release_confirm":False})
#Attempt Boolean UNION between two objects
bpy.ops.object.modifier_add(type='BOOLEAN')
bpy.data.objects[bpy.data.objects.find(object_1 +'.001')].modifiers[0].operation='UNION'
bpy.data.objects[bpy.data.objects.find(object_1 +'.001')].modifiers[0].object=bpy.data.objects[bpy.data.objects.find(object_2)]
bpy.ops.object.modifier_apply(modifier='Boolean')
#-----------------------Non-manifold Check-------------------------------------------
bpy.ops.object.mode_set(mode = 'EDIT')
bpy.ops.mesh.select_all( action='DESELECT' )
bpy.ops.mesh.select_non_manifold(extend=True)
obj=bpy.context.object
bm=bmesh.from_edit_mesh(obj.data)
non_manifolds_counter = 0
#Loop through all vertices and check if they have been selected as non-manifold, if so break the loop (unsuccessful Boolean)
for v in bm.verts:
if v.select:
print('Found a manifold!')
boolean_check = 0
non_manifolds_counter = non_manifolds_counter + 1
break
bpy.ops.object.mode_set(mode = 'OBJECT')
#-------------------------Non-manifolds Check END------------------------------------------
#----------------------------------Check the BOOLEAN flag----------------------------------
#End program if there are NOT non-manifold elements, otherwise keep going with a new shift in x y z...
if (boolean_check == 1 ):
bool_index = n_attempts
print("Boolean Union successful!")
break
else:
#Delete the Unioned mesh with non-manifold elements and re-start with new shift in x y z...
bpy.ops.object.delete(use_global=True)
bpy.ops.object.select_all(action = 'DESELECT')
boolean_check = 1
I would like to underline that what this script does NOT do is catching the "Unknown internal error in boolean" exception
I hope this can avoid the headaches I had with this issue to some of you, happy blending!
The script was tested with Blender 2.68 running on Windows 8 Pro