As a style thing, I’d suggest breaking the big main function up a bit. For example you’re doing this inline
BBObj = cmds.polyEvaluate(allObjectsList[obj], boundingBox = True)
BBObj2 = cmds.polyEvaluate(allObjectsList[obj2], boundingBox = True)
BBObjMin = (BBObj[0][0], BBObj[1][0], BBObj[2][0])
BBObjMax = (BBObj[0][1], BBObj[1][1], BBObj[2][1])
distanceMin = myMath.distance(BBObj[0][0], BBObj2[0][0], BBObj[1][0], BBObj2[1][0], BBObj[2][0], BBObj2[2][0])
BBObj2Min = (BBObj2[0][0], BBObj2[1][0], BBObj2[2][0])
BBObj2Max = (BBObj2[0][1], BBObj2[1][1], BBObj2[2][1])
distanceMax = myMath.distance(BBObj[0][1], BBObj2[0][1], BBObj[1][1], BBObj2[1][1], BBObj[2][1], BBObj2[2][1])
You could convert that to a separate function like compare_bounds()
and move it outside of the loop, then just call it. That helps reusability and also readability.
On a related note it’s usually a good idea to break up index-access blocks (like the BBObj2[0][1], BBObj2[1][1], BBObj2[2][1]
) into something more legible. For example
def bounds_from_object(obj):
xcoords, ycoords, zcoords = cmds.polyEvaluate(obj, boundingBox = True)
min_bbox = xcoords[0], ycoords[0], zcoords[0]
max_bbox = xcoords[1], ycoords[1], zcoords[1]
return min_bbox, max_bbox
extracts the min and max corners of the box just as you are doing, but it’s easier to spot an issue and see a problem (whereas with all indices it’s harder to notice a bug like
BBObj2Min = (BBObj2[0][0], BBObj2[0][0], BBObj2[2][0])
which accidentally uses the minimum X twice instead
It’s a good idea to think about how you’re structuring your loops. You don’t need to do indexes like you would in, say, c# ; instead you can just loop over lists directly:
delenda = []
for first_object in all_object_list:
for second_object in all_object_list:
if first_object == second_object:
continue
dist_min, dist_max = compare_bounds(first_object, second_object)
if distanceMin <= maxDistance and distanceMax <= maxDistance:
delenda.append(second_object)
Which raises a point about the algorithm: I think that as written you’re checking each pair of objects twice, since every item is checked against every other in the second loop, meaning you’ll try both A->B and B->A.
There are a couple of ways around that; the itertools
module has a function that produces all the combinations in a list itertools.combinations(all_object_list, 2)
would give you all the unique pairs of objects in all_object_list
. Or, you could track which pairs have already been tried by using sets:
delenda = []
seen = []
for first_object in all_object_list:
for second_object in all_object_list:
if first_object == second_object:
continue
if set([first_object, second_object]) in seen:
continue
else:
seen.append(set([first_object, second_object]))
dist_min, dist_max = compare_bounds(first_object, second_object)
if distanceMin <= maxDistance and distanceMax <= maxDistance:
delenda.append(second_object)