# Using overlap() to check if two meshes are intersecting?

This is a follow up to How to check if two meshes intersect in python with BVH Tree?

It appears that just calling overlap() on the BVH tree of two objects is not enough. Some sort of bmesh transform is required (this part confuses the hell out of me). I tried this in the code below, however I am still getting intersection on every object even if they are all not touching..

#delete objects that are intersecting
def delInter():
#check every object for intersection with every other object
for obj_now in obj_list:
for obj_next in obj_list:
print()
if obj_now == obj_next:
continue

#create bmesh objects
bm1 = bmesh.new()
bm2 = bmesh.new()

#fill bmesh data from objects
bm1.from_mesh(scene.objects[obj_now].data)
bm2.from_mesh(scene.objects[obj_next].data)

#fixed it here:
bm1.transform(scene.objects[obj_now].matrix_world)
bm2.transform(scene.objects[obj_next].matrix_world)

#make BVH tree from BMesh of objects
obj_now_BVHtree = BVHTree.FromBMesh(bm1)
obj_next_BVHtree = BVHTree.FromBMesh(bm2)

#get intersecting pairs
inter = obj_now_BVHtree.overlap(obj_next_BVHtree)

#if list is empty, no objects are touching
if inter != []:
print(obj_now + " and " + obj_next + " are touching!")
else:
print(obj_now + " and " + obj_next + " NOT touching!")

• Whoops. Corrected! :) – VSB Jan 15 '17 at 0:29

Turns out I had to apply location to the BMesh I generated, I have edited code above to work:

        bm1.transform(scene.objects[obj_now].matrix_world)
bm2.transform(scene.objects[obj_next].matrix_world)


This is the reason I was getting intersection for every face and object, since they were all in the same location as far as BVHTree was concerned.

I added the missing context so the code can be used by anyone. Tested and working with 2.8.

import bpy, bmesh
from mathutils.bvhtree import BVHTree

#show objects that are intersecting
def intersection_check():
#check every object for intersection with every other object
for obj_now in obj_list:
for obj_next in obj_list:
print()
if obj_now == obj_next:
continue

#create bmesh objects
bm1 = bmesh.new()
bm2 = bmesh.new()

#fill bmesh data from objects
bm1.from_mesh(scene.objects[obj_now].data)
bm2.from_mesh(scene.objects[obj_next].data)

#fixed it here:
bm1.transform(scene.objects[obj_now].matrix_world)
bm2.transform(scene.objects[obj_next].matrix_world)

#make BVH tree from BMesh of objects
obj_now_BVHtree = BVHTree.FromBMesh(bm1)
obj_next_BVHtree = BVHTree.FromBMesh(bm2)

#get intersecting pairs
inter = obj_now_BVHtree.overlap(obj_next_BVHtree)

print("i got this far 1")

#if list is empty, no objects are touching
if inter != []:
print(obj_now + " and " + obj_next + " are touching!")
else:
print(obj_now + " and " + obj_next + " NOT touching!")

# use active scene
scene =  bpy.context.scene

# define object list
obj_list = ['object_a', 'object_b']

# Run it
intersection_check()

• This doesn't seem to work if objects are overlapping by just an edge or vertex... meaning an edge from one object is equal to the edge of another. If one object is moved over the other just a tick, then it flags overlap. My project has objects that start right at the point where one ends, using the same edge vertices. Overlap doesn't appear to be the proper solution in those cases. – Sam Vimes Sep 18 '19 at 22:25

I tried to copy this code/test myself, without any Blender Python knowledge. But was getting many errors. I had to add in some extra code/rename some stuff to get it to work. But here's what I got:

import bpy  #addbpy   <<ADD

# get the current meshes   <<ADD
obj_list = bpy.data.meshes

# get the current scene  <ADD
scn = bpy.context.scene

# Define the BVH Tree  <ADD
BVHTree = mathutils.bvhtree.BVHTree

#Print objects that are intersecting
def delInter():
#check every object for intersection with every other object
for obj_now in obj_list:
for obj_next in obj_list:
print()
if obj_now == obj_next:
continue

#create bmesh objects
bm1 = bmesh.new()
bm2 = bmesh.new()

#fill bmesh data from objects
bm1.from_mesh(scn.objects[obj_now.name].data)   #<<  Add .name on both
lines.
bm2.from_mesh(scn.objects[obj_next.name].data)  #<<  Add .name on both
lines.

#fixed it here:
on both lines.
on both lines.

#make BVH tree from BMesh of objects
obj_now_BVHtree = BVHTree.FromBMesh(bm1)
obj_next_BVHtree = BVHTree.FromBMesh(bm2)

#get intersecting pairs
inter = obj_now_BVHtree.overlap(obj_next_BVHtree)

#if list is empty, no objects are touching
if inter != []:
print(obj_now.name + " and " + obj_next.name + " are touching!")   #
<<  Add .name on both lines.
else:
print(obj_now.name + " and " + obj_next.name + " NOT touching!")
#<<  Add .name on both lines.

delInter()  #Call FN

• Please use 4 space indenting. – batFINGER Aug 28 '18 at 18:25

a similar code would return an empty list of indices:

import bpy, bmesh
from mathutils.bvhtree import BVHTree

list_of_obj = [ o for o in bpy.context.scene.objects]
the_object = list_of_obj[0]
the_other_object = list_of_obj[1]

BMESH_1 = bmesh.new()
BMESH_1.from_mesh(bpy.context.scene.objects[the_object.name].data)
BMESH_1.transform(the_object.matrix_world)
BVHtree_1 = BVHTree.FromBMesh(BMESH_1)

BMESH_2 = bmesh.new()
BMESH_2.from_mesh(bpy.context.scene.objects[the_other_object.name].data)
BMESH_2.transform(the_other_object.matrix_world)
BVHtree_2 = BVHTree.FromBMesh(BMESH_2)

inter = BVHtree_1.overlap(BVHtree_2)

print(inter)


is there a missing bmesh operation ?

EDIT : the above code actually works if any object matrix transformation has not been changed after the last scene update. To apply this code to objects which have been transformed within the same script for example, one can add the following line above the code:

bpy.context.scene.update() # as commented below by @batFINGER