4
$\begingroup$

I know that the closest_point_on_mesh function in BPY can be used to find the closest point on any mesh to an arbitrary point in space. However, I am working on a project for which I need to take a vertex on a mesh object, and find the closest point on any other mesh object. Is there a method that can be used to do that? Thanks.

$\endgroup$

3 Answers 3

7
$\begingroup$

Using closest point on mesh.

Similarly to the answer here https://blender.stackexchange.com/a/40979/15543 code hacked together to find the closest point on mesh of all other mesh objects in the scene to vertex[0] of the active mesh object. Adds an Empty on the hit point.

import bpy
import bmesh
context = bpy.context
scene = context.scene

edit_obj = context.active_object
me = edit_obj.data
mesh_objects = [o for o in scene.objects if o.type == 'MESH']
bm = bmesh.new()
for sphere in mesh_objects:
    if sphere == edit_obj:
        continue
    smwi = sphere.matrix_world.inverted()

    bm.from_mesh(me)
    bm.verts.ensure_lookup_table()
    vert = bm.verts[0]
    v1 = edit_obj.matrix_world * vert.co # global face median
    local_pos = smwi * v1  # face cent in sphere local space

    (hit, loc, norm, face_index) = sphere.closest_point_on_mesh(local_pos)
    if hit:
        v2 = sphere.matrix_world * loc
        bpy.ops.object.empty_add(location=v2)
        print(sphere.name, (v2 - v1).length)
    bm.clear()
$\endgroup$
2
$\begingroup$

A base to do that by simply going through all objects vertices (so not really optimized if many vertices/objects) :

The result is a list of tuples [object, nearest vertice, distance].

import bpy
from mathutils import Vector

max = 100000 #max distance

point = Vector([0, 0, 0]) #reference point from which we seek the distances (set your reference vertex in global coordinates here)

result = [] #stores the results

for obj in bpy.data.objects:
    pos = obj.matrix_world.inverted() * point #converts the reference to local space

    shortest = None
    shortestDist = max

    for v in obj.data.vertices: #go throught all vertices
        dist = (Vector( v.co ) - pos).length  #calculate the distance
        if dist < shortestDist : #test if better so far
            shortest = v
            shortestDist = dist

    result.append( [obj, shortest, shortestDist] ) #append the result

print( result )
$\endgroup$
1
$\begingroup$

mathutils supports KDTrees, which can also be helpful in this scenario: https://docs.blender.org/api/current/mathutils.kdtree.html

from mathutils.kdtree import KDTree

def createKdTreeForObject(blenderObject):
    mesh = blenderObject.data
    size = len(mesh.vertices)
    kd = KDTree(size)

    for i, v in enumerate(mesh.vertices):
        kd.insert(v.co, i)

    kd.balance()
    return kd

vertex = (1,0,1)
blenderObject = D.objects['Cube']
kdTree = createKdTreeForObject(blenderObject)
matrixWorld = blenderObject.matrix_world
invertedMatrixWorld = matrixWorld.inverted()

vertexInverted = invertedMatrixWorld @ Vector(vertex)

print("Closest 10 points")
for (co, index, dist) in kdTree.find_n(vertexInverted, 10):
    print("    ", co, index, dist)

```
$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .