# Boolean difference not cutting all holes correctly within for loop (python script)

I have a strange problem with a python script. I am generating an object with holes cut out of it in specific locations. The script works well for all of it except for one specific and weird problem. I run a loop for a boolean difference operation and it works for every hole except for my first hole.

I've gone back and stopped the code before the first boolean cut occurs by adding an extra edit mode toggle (to break it) and tried to manually add the difference boolean to generate the hole and it doesn't want to work manually either. I have no idea what is going on - especially since it works on all the other holes and also since it won't even seem to let me do it manually.

My code is attached below. I have no idea why it won't build my first hole - all assistance will be greatly appreciated.

#imports
import bpy
import numpy as np
import math
from array import *

#Definitions
# Calculates Rotation Matrix given euler angles.  Need angle in radians.
def eulerAnglesToRotationMatrix(theta) :

R_x = np.array([[1,         0,                  0                   ],
[0,         math.cos(theta[0]), -math.sin(theta[0]) ],
[0,         math.sin(theta[0]), math.cos(theta[0])  ]
])

R_y = np.array([[math.cos(theta[1]),    0,      math.sin(theta[1])  ],
[0,                     1,      0                   ],
[-math.sin(theta[1]),   0,      math.cos(theta[1])  ]
])

R_z = np.array([[math.cos(theta[2]),    -math.sin(theta[2]),    0],
[math.sin(theta[2]),    math.cos(theta[2]),     0],
[0,                     0,                      1]
])
R = np.dot(R_z, np.dot( R_y, R_x ))
return R

#Variables
hemiSegments = 25
hemiRingCount = 25
hemiLocation = (0, 0, 0)
dropVertices = 16

#Variables for hole placement.
maxYaw = (75) #degrees
maxPitch = (65) #degrees

#Sphere

#Cut sphere in half vertically in the correct plane
#Change plane_co("X", 0.3, 0) to '0' to make it a perfect half of a sphere, increase 'X' to allow more of the other half of the sphere to be present
bpy.ops.mesh.bisect(plane_co=(0.03, 0.3, 0), plane_no=(0.999995, 0.003263, -0), clear_inner=False, clear_outer=True, xstart=681, xend=683, ystart=715, yend=102)

bpy.ops.mesh.select_all(action='TOGGLE')
bpy.ops.mesh.select_all(action='TOGGLE')
bpy.ops.mesh.subdivide(smoothness=0)

#increase thickness
bpy.ops.object.modifier_remove(modifier="Solidify")
bpy.context.object.modifiers["Solidify"].offset = 0
bpy.context.object.modifiers["Solidify"].thickness = 0.02
bpy.ops.object.editmode_toggle()
bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Solidify")
bpy.ops.object.editmode_toggle()

###At this point, Hemisphere is built

maxYaw = (maxYaw/180.0)*np.pi #now in radians
maxPitch = (maxPitch/180.0)*np.pi #now in radians

#locations of holes
rollPointsDeg = [[0, 0, 0],                #0 center
[0, maxPitch, 0],          #1 top mid
[0, maxPitch, maxYaw],     #2 top left
[0, 0, maxYaw],            #3 mid left
[0, -maxPitch, maxYaw],    #4 bot left
[0, -maxPitch, 0],         #5 bot mid
[0, -maxPitch, -maxYaw],   #6 bot rig
[0, 0, -maxYaw],           #7 mid rig
[0, maxPitch, -maxYaw]]    #8 top rig

#location of holes
rollPoints =    [[-radius, 0, 0],   #0
[0, 0, 0],         #1
[0, 0, 0],         #2
[0, 0, 0],         #3
[0, 0, 0],         #4
[0, 0, 0],         #5
[0, 0, 0],         #6
[0, 0, 0],         #7
[0, 0, 0]]         #8

#the rotational matrix variable
rotMat = np.array([[0,0,0],[0,0,0],[0,0,0]])

#Rotation Matrix Loop
i=1
while i < 9:
rotMat = eulerAnglesToRotationMatrix(rollPointsDeg[i]) #converts the rotMat into the rotational matrix
rollPoints[i] = np.dot (rotMat, rollPoints[0])  #dot product of rotMatrix and rollPoints[0]
i += 1

#comment out this line if getting errors from blender about <<operation cannot performe in edit mode
bpy.ops.object.editmode_toggle()

#Loop adding circles in precise location and orientation
k = 0
while k < 9:
bpy.context.scene.cursor_location = (0.0, 0.0, 0.0)
bpy.ops.object.origin_set(type='ORIGIN_CURSOR')

scj = bpy.context.scene

# The added circle will be the active object after it is created
ob = bpy.context.object
me = ob.data

# If you want to move your object, simply set its location thus:
ob.location = ( rollPoints[k][0], rollPoints[k][1],rollPoints[k][2] )

# And you can rotate the object the same way
# Note that you need to use radians rather than angles here
ob.rotation_euler = (0*(np.pi/2), (np.pi/2) + rollPointsDeg[k][1], rollPointsDeg[k][2])

#Now apply shrinkwrap after orientations are correct
bpy.context.object.modifiers["Shrinkwrap"].target = bpy.data.objects["Sphere"]
bpy.context.object.modifiers["Shrinkwrap"].wrap_method = 'PROJECT'
bpy.context.object.modifiers["Shrinkwrap"].use_project_z = True
bpy.context.object.modifiers["Shrinkwrap"].use_negative_direction = True
bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Shrinkwrap")

#weird prep-stuff needed to make boolean operation work correctly:
#moving circles within the sphere to allow proper difference boolean operation

bpy.ops.object.editmode_toggle()

bpy.ops.mesh.extrude_region_move(MESH_OT_extrude_region={"mirror":False}, TRANSFORM_OT_translate={"value":(0, 0, 0.09883128), "constraint_axis":(False, False, True), "constraint_orientation":'LOCAL', "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), "gpencil_strokes":False, "texture_space":False, "remove_on_cancel":False, "release_confirm":False, "use_accurate":False})

bpy.ops.object.editmode_toggle()

bpy.ops.transform.translate(value=(9.31323e-010, -2.09548e-009, -0.0348931), constraint_axis=(False, False, True), constraint_orientation='LOCAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1)

#boolean difference operation

hemmy = bpy.data.objects['Sphere']
bpy.context.scene.objects.active = hemmy

bpy.ops.object.select_all(action='TOGGLE')
bpy.ops.object.select_all(action='TOGGLE')

bpy.ops.object.modifier_apply(modifier="Auto Boolean")
bpy.ops.btool.auto_difference(solver='BMESH')

k +=1

• blender.stackexchange.com/questions/3212/… – Duarte Farrajota Ramos Apr 29 at 15:09
• blender.stackexchange.com/questions/34781/… – Duarte Farrajota Ramos Apr 29 at 15:10
• @DuarteFarrajotaRamos: thank you for the links. I'll review them and post an update on my progress thereafter. – user70711 Apr 30 at 6:43
• I rewrote my code such that cylinders were generated instead of circles. This simplified the code and I was able to then perform the difference boolean operation on the cylinders and it worked. Looking through the example links you posted helped me do this. So, I was able to make my model correctly, HOWEVER, I still haven't figured out why the boolean operation would not work correctly...on only one of my circles. I would like to know as it will help me learn and develop my skills further. If anyone has ideas, please don't hesitate to comment. Thanks! – user70711 Apr 30 at 8:22