Hi to everyone,
I am using a Boolean modifier through a python script.
During the BOOLEAN Union of two meshes I get the following exception:
CSG failed, exception extern/carve/lib/triangulator.cpp:899 "didn't manage to link up hole!"
Unknown internal error in boolean
As learned by other posts most of the time one can avoid the exception by applying a little spatial rotation to one of the two meshes before applying the modifier, however it would be very useful being able to catch this exception at runtime so that the rotation can be applied automatically.
The problem is that I am not able to catch and handle the exception at runtime in the python script as it is raised by a c++ sublibrary (triangulator.cpp), any idea on how to do this?
Thanks in advance for any attempt to think this through!
CSG failed, exception extern/carve/lib/triangulator.cpp:899
Moderators: jesterKing, stiv
A partial solution
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)
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
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 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