The BVHTree functions should not be limited to trees of tris.
They may extend to any element that can be contained within a volume (such as edges, vertices, polygons, objects ...).
So the first thing to do is to separate the methods of creating the tree of its own class that will have the settings of tris.
With this patch the mathutils.bvhtree module works like this:
>>> from mathutils import bvhtree >>> bvhtree.from_ bmesh_faces( object_polygons( polygons( >>> treeTri = bvhtree.from_object_polygons(C.object, C.scene) >>> treeTri. find_nearest( overlap( ray_cast(
It is also important to allow the user to create their own kinds of BVHTrees, so the settings of a BVHTree can now be stored in the UserData class, and finally the tree can be created.
Here is a example of using customized BVHTrees:
import bpy from mathutils import bvhtree, geometry print("------------------------------") ## defining userdata ## my_userdata = bvhtree.UserData() ## setting up userdata ## obj = bpy.context.object vertices = [v.co for v in obj.data.vertices] indices = [e.vertices for e in obj.data.edges] #edges my_userdata.set_coords(vertices, indices) ## defining a custom "find_nearest" callback ## my_ret_co = None # the result will be stored here dist_sq = 1000 # max dist squared def find_nearest_to_edge_cb(self, co, index): global dist_sq global my_ret_co edge = self.coords[index] isect, fac = geometry.intersect_point_line(co, *edge) if fac <= 0: isect = edge elif fac >= 1: isect = edge tmp_dist_sq = (isect-co).length_squared if tmp_dist_sq < dist_sq: dist_sq = tmp_dist_sq my_ret_co = isect return dist_sq my_userdata.find_nearest_callback = find_nearest_to_edge_cb ## creating tree ## tree = bvhtree.BVHTree(my_userdata) ## Executing the custom find_nearest (no return) ## print("Previous", my_ret_co) my_coord = obj.matrix_world.inverted() * bpy.context.scene.cursor_location tree.find_nearest(my_coord) # the custom callback is being used here print("New", my_ret_co) bpy.context.scene.cursor_location = obj.matrix_world * my_ret_co del tree del my_userdata
I also changed the Non returns of raycast and find_nearest from (None, None, None, None) to only None (This summarizes the code).