Python script to eliminate objects that intersect each other along z-axis

Sorry if the title was not descriptive enough. Here’s my problem. I have built a “city” in blender. The roads came from one source and the buildings came from another. They are fairly well aligned but not perfectly. There are lots of buildings in this “city”. Every building is it’s own object (though they could easily be joined into one if necessary). And the road is a separate object. What I’ve been trying to do is come up with a script that will cycle through all the bottom vertices of the buildings (I can raise them way above the roads if necessary) and ray cast straight down and if I hit a face that belongs to the the roads object for any of the vertices, then delete the object. It’s very easy to explain, visually simple to see the problem (from top view buildings are on top of the road), but I haven’t been able to create a script that works. I have something that goes through every building and cycles through every vertex and finds the distance to the nearest roads vertex in x,y,z. But what I really want is just to know if a ray casted straight down from a given vertex will hit a face on the roads object. Then all my problems would be fixed… well… except for buildings whose vertices don’t intersect straight down with the roads but a face still does (think of a building laid out perpendicular to a road).

The other thing I tried was seeing if I could make the roads really tall so that buildings that were over them would be enclosed or intersection with the roads mesh… if I could then have the roads mesh be joined by anything it touches. Then I could delete the roads along with the “bad” buildings and call it a day. But that didn’t work.

The other option was to try to place a plane under the roads and somehow let the buildings fall (physics? modifier?) and hopefully there’s a way of getting the good buildings fall through (sort of like a catcher) and the bad buildings would get stuck on the road object.

I’m just thinking out loud… it’s been a couple of days of trying crazy things with no success. Please help!

This here works for me with Blender 2.76.

Expects an object called “road”. All house objects must be selected. Casts a ray downwards in Z direction from each vertex of each house.


import bpy
import bmesh
import mathutils.bvhtree


road = bpy.data.objects["road"]
houses = bpy.context.selected_objects


bm = bmesh.new()
bm.from_mesh(road.data)
bvh = mathutils.bvhtree.BVHTree.FromBMesh(bm)


for house in houses:
    m1 = house.matrix_world
    m2 = road.matrix_world
    one_hit = False
    for v in house.data.vertices:
        # convert coordinates to local space of 'road'
        co = m2.inverted() * m1 * v.co
        hit, normal, index, distance = bvh.ray_cast(co, (0, 0, -1))
        if hit:
            one_hit = True


    # select house if on road, deleselect if not on road
    house.select = one_hit