1
$\begingroup$

I want to select (or to put into active selection) some vertices using their coordinates so I've seen an answer there : Automatic select vertices by given coordinates

But it only works when I'm in edit mode, how could I use it this way :
Object mode : select an object, put it in edit mode and then select the vertices, go out of edit mode (back to object)
And when I use this at the beggining of the code : bpy.ops.object.editmode_toggle() it sends me an error.

Because I'd like to use this code with other objects in my scene not just one. I guess the problem is in bmesh but I don't quite understand it... Thank you for your help.

The answer given by zeffii :

import bpy
import bmesh
from mathutils import Vector, kdtree

coords_to_find = [
    (0.3203125, -0.734375, 0.7578125),
    (0.0, -0.2890625, 0.8984375),
    (0.453125, -0.234375, 0.8515625),
    (-0.6328125, -0.28125, 0.453125),
    (-0.796875, -0.125, 0.5625)
]

# Get the active mesh
obj = bpy.context.edit_object
me = obj.data
bm = bmesh.from_edit_mesh(me)

size = len(bm.verts)
kd = kdtree.KDTree(size)

for i, vtx in enumerate(bm.verts):
    kd.insert(vtx.co, i)
kd.balance()

for idx, vtx in enumerate(coords_to_find):
    co, index, dist = kd.find(vtx)  # dist is the distance
    print(idx, vtx, index, co)
    bm.verts[index].select = True

# Show the updates in the viewport
# and recalculate n-gon tessellation.
bmesh.update_edit_mesh(me, True)
$\endgroup$
1
$\begingroup$

Object mode non-bmesh version

Run script in object mode. Selects vertices in each object based on being closest to points in list.

import bpy
import bmesh
from mathutils import Vector, kdtree

context = bpy.context

coords_to_find = [
    (0.3203125, -0.734375, 0.7578125),
    (0.0, -0.2890625, 0.8984375),
    (0.453125, -0.234375, 0.8515625),
    (-0.6328125, -0.28125, 0.453125),
    (-0.796875, -0.125, 0.5625)
]

# Get the active meshes
meshes = set(o.data for o in context.selected_objects
        if o.type == 'MESH')

for me in meshes:
    size = len(me.vertices)
    kd = kdtree.KDTree(size)
    select = [False] * size

    # deselect all edges and faces
    me.edges.foreach_set("select", [False] * len(me.edges))
    me.polygons.foreach_set("select", [False] * len(me.polygons))

    for v in me.vertices:
        kd.insert(v.co, v.index)
    kd.balance()

    for co in coords_to_find:
        loc, index, dist = kd.find(co)  
        select[index] = True

    me.vertices.foreach_set("select", select)
    print(me.name, [v.index for v in me.vertices if v.select])
    #me.update_tag()
    #context.view_layer.update()

which if run on default scene, returns

Cube [5, 6]

Note this assumes the given coordinates are in local space.

For global coordinates would have to decide how to handle objects sharing the same mesh, since a different vert may be chosen based on object transform for each object that shares the mesh.

$\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.