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$
2

1 Answer 1

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$

You must log in to answer this question.

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