It is nearly direct, we just need to convert objects vertices in world coordinates:
from mathutils.bvhtree import BVHTree
# Get the objects
obj1 = bpy.data.objects["Cube"]
obj2 = bpy.data.objects["Suzanne"]
# Get their world matrix
mat1 = obj1.matrix_world
mat2 = obj2.matrix_world
# Get the geometry in world coordinates
vert1 = [mat1 @ v.co for v in obj1.data.vertices]
poly1 = [p.vertices for p in obj1.data.polygons]
vert2 = [mat2 @ v.co for v in obj2.data.vertices]
poly2 = [p.vertices for p in obj2.data.polygons]
# Create the BVH trees
bvh1 = BVHTree.FromPolygons( vert1, poly1 )
bvh2 = BVHTree.FromPolygons( vert2, poly2 )
# Test if overlap
if bvh1.overlap( bvh2 ):
print( "Overlap" )
print( "No overlap" )
With all the objects being same-sized cubes on the same Z, you only need to worry about XY.
Three possible levels to consider going about this, in increasing order of complexity:
Just rough it with circle separation. If you treat each object as if it were a circle, no Z-rotation will matter. A cube with half-width ('radius') 1 will fit inside a circle of radius sqrt(2) - with its corners touching that circle. In that case, the cheap and nasty quick way to detect all these sorts of overlaps is just using the distance formula between the object centers to see if that distance is less than two of these radii.
from math import sqrt
def dist(a, b):
dx = a.location - b.location
dy = a.location - b.location
return sqrt(dx*dx + dy*dy)
minDist = 2 * circRadius
cubes = [ob for ob in bpy.data.objects if ob.name.startswith("Cube")]
for cube in cubes:
for other in cubes:
if other != cube:
if dist(cube, other) < minDist:
print("%s and %s overlap." % (cube.name, other.name))
Note that this will report false positive overlaps on cubes that are closely aligned and close by each other, not touching, but still within the approximate circles.
If you want to get more 'proper' or accurate, that starts to get more into 'collision detection' topics. You may want to read up on how games check for overlaps, eg SAT (the separating axis theorem).
Blender definitely has utilities for doing this sort of thing internally. I don't know its internals well enough to know what's all in there, having not done this exact thing before, but it sounds like a common need. The boolean tool is bound to detect things exactly. Even just testing this basic stuff, I noticed in the Scripting workspace that there's internal modules like mathutils, mathutils.geometry, and that objects have functions such as closest_point_on_mesh, ray_cast, and so on.
Familiarizing yourself with these and searching through/reading the API docs will pay dividends, if you need a more exact solution. For example, at a glance I also see spatial partitioning helpers such as mathutils.bvhtree, mathutils.kdtree, and others.