0
$\begingroup$

I have 2400 small cubes stacked to form a brick base. The total dimension is 40x12x5 with each cube size of 1x1x1. There is a large cone, some parts of that directly go through the brick base as shown in the figure. Is there any very fast way of getting the name of all the objects (cubes) that touches / falls inside the cone? enter image description here

$\endgroup$
2

1 Answer 1

0
$\begingroup$

I have found a solution with two different approaches. The first is to find the cubes that intersect with the cone and usually on the side of the edge. Second, finds the cubes that sit inside the cone. In the second part, there will be some cubes that actually intersect with the cone. Thus, there will be some cubes present both results. You can just join both lists and get rid of the duplicate cubes for the correct answer.

# import libraries
import bpy, bmesh, time
from mathutils.bvhtree import BVHTree
from mathutils import Vector

obj_list = [e for e in bpy.data.objects if e.type == 'MESH' and e != bpy.data.objects['Cone']] # get all the cubes
cone = bpy.data.objects['Cone']

# part 1: find the cubes intersect with the cone create cone mesh and it's BVH Tree
cone_mesh = bmesh.new()
cone_mesh.from_mesh(cone.data)
cone_mesh.transform(cone.matrix_world)
cone_BVHtree = BVHTree.FromBMesh(cone_mesh)

intersect_obj_list = [] # the cubes intersect the cone create cube mesh for each cube and their BVH Trees
for cube in obj_list:
    cube_mesh = bmesh.new()
    cube_mesh.from_mesh(cube.data)            
    cube_mesh.transform(cube.matrix_world) 
    cube_BVHtree = BVHTree.FromBMesh(cube_mesh)

    # get the intersected faces using BVHtree, if result is non-none, the cube is intersecting         
    inter = cone_BVHtree.overlap(cube_BVHtree)
    if inter != []:
        intersect_obj_list.append(cube)
print (len(intersect_obj_list))


# part 2: find the cubes sits completely inside the cone
falls_inside = [] 
for cube in obj_list:
    cube_location = cube.location
    x,y,z = cube_location
    dest_point = Vector((x, y, z+100)) # destination will be point far from the origin
    origin =  cone.matrix_local.inverted()@cube_location
    destination = cone.matrix_local.inverted()@dest_point
    direction = (destination - origin).normalized() #normalizing 
    # shooting ray from origin to the destinantion, if it hits then the object is sitting inside the cone
    hit, loc, norm, face = cone.ray_cast(origin, direction)  
    if hit:
        falls_inside.append(cube)

interset_inside_cubes = list(set(intersect_obj_list+falls_inside))
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.