I am seeking help with a script. Essentially I have any object in the scene and I need to select the vertex furthest away from the blender floor in the z direction. So, if you had to move the sphere under the floor, the script would then select the lowest point, away from the floor.
-
Maybe check: https://blender.stackexchange.com/a/139291/35559 – Robin Betts Jun 05 '22 at 08:29
2 Answers
Edit Mode
import bpy, bmesh
from bpy import context as C
ob = C.object
me = ob.data
bpy.ops.mesh.select_all(action='DESELECT')
bm = bmesh.from_edit_mesh(me)
key_global = lambda v: abs((ob.matrix_world @ v.co).z)
key_local = lambda v: abs(v.co.z)
v = max(bm.verts, key=key_global)
v.select = True
bmesh.update_edit_mesh(me)
Object Mode
import bpy
from bpy import context as C
ob = C.object
me = ob.data
me.edges.foreach_set('select', (False,)len(me.edges))
me.polygons.foreach_set('select', (False,)len(me.polygons))
key_global = lambda v: abs((ob.matrix_world @ v.co).z)
key_local = lambda v: abs(v.co.z)
v = max(me.vertices, key=key_global)
me.vertices.foreach_set('select', [i==v for i in me.vertices])
Numpy
I don't know how to multiply the numpy coords by matrix efficiently, so I just transform the object to world space and back:
import bpy, numpy as np
from bpy import context as C
ob = C.object
me = ob.data
me.transform(ob.matrix_world)
me.edges.foreach_set('select', np.zeros(len(me.edges), dtype=bool))
me.polygons.foreach_set('select', np.zeros(len(me.polygons), dtype=bool))
coords = np.zeros(len(me.vertices)*3, dtype=np.float32)
me.vertices.foreach_get('co', coords)
abs_z = np.absolute(coords[2::3])
sel = np.zeros(len(me.vertices), dtype=bool)
sel[np.argmax(abs_z)] = True
me.vertices.foreach_set('select', sel)
me.transform(ob.matrix_world.inverted())
- 36,563
- 3
- 30
- 99
Select the lowest vertex from a object.
You need check the object type first
import bpy, bmesh
access active object
obj = bpy.context.object
or access by name
obj = bpy.data.objects["Cube"]
me = obj.data
bpy.ops.object.mode_set(mode='EDIT')
bm = bmesh.from_edit_mesh(me)
bm.verts.ensure_lookup_table()
get verts in global space
A faster way is to use numpy, see: https://blender.stackexchange.com/questions/6155/how-to-convert-coordinates-from-vertex-to-world-space
m = obj.matrix_world
verts = (m @ v.co for v in bm.verts)
print(verts)
z = 1.7976931348623157e+308
ind = 0
for i, v in enumerate(verts):
if v[2] < z:
ind = i
z = v[2]
deselect all verts
bm.select_mode |= {'VERT'}
bm.select_flush_mode()
for v in bm.verts:
v.select_set(False)
deselect all verts END
v = bm.verts[ind]
v.select_set(True)
print("local location: ", v.co)
print("global location: ", m @ v.co)
bmesh.update_edit_mesh(me)
- 5,234
- 1
- 6
- 20
-
2This needs a fix, you need to set the initial
zto-1, and instead ofif v[2] < z, doif abs(v[2]) > z. BTW, whenever you're sorting like that, you can assignfloat('inf')orfloat('-inf'), however, more pythonic isv = max((v for v in bm.verts), key=lambda x:abs((m @ x.co).z)), no need to ensure lookup table when you're iterating over the verts and don't care about indices, cheers! – Markus von Broady Jun 05 '22 at 08:14
