1
$\begingroup$

When I use Blender Python to loop through all vertices to select only vertices with a Z coordinate <= 0, the script seems to randomly do one of the following:

  1. Select all vertices
  2. Select the vertices with a Z <= 0

Does the object need to be selected a certain way in the UI or through Python before looping through the vertices to get the correct selection behavior?

The Python I am using is

import bpy
for v in bpy.context.active_object.data.vertices:
   v.select = v.co.z <= 0
   

The steps I do are

  1. Import the model into the file as a mesh
  2. Switch to Scripting view
  3. Select the model in the 3D view or the model list
  4. Run the script

When tabbing the 3D view to Edit Mode, sometimes the wrong set of vertices is selected like seen in the screenshot.

The current object returns the correct object when typed into the console in the screenshot.

selected all

Bmesh version of the script

import bpy, bmesh

me = bpy.context.object.data

bm = bmesh.new() 
bm.from_mesh(me) 

bm.select_flush(True)

for v in bm.verts:
   v.select_set(v.co.z <= 0)

bm.to_mesh(me)
bm.free()
$\endgroup$

1 Answer 1

1
$\begingroup$

Selecting vertices definitely works fine. You don't deselect any already selected geometry in the script though. To deselect everything, you need to deselect verts, edges and faces because they are selected separately even though that's not the case from the user's perspective. You could do that before selecting what you need:

import bpy

d = bpy.context.object.data
for e in d.vertices[:] + d.polygons[:] + d.edges[:]:
    e.select = False 

or maybe

import bpy

d = bpy.context.object.data
for e in [d.vertices, d.polygons, d.edges]:
    e.foreach_set("select", (False,)*len(e))

if you want to be fancy, and more efficient(seems to be quite a lot faster).

However you should consider that using operators in scripts the way you do is not advisable. Operators are generally designed to work with user input and for scripts you should avoid relying on them. Consider using bmesh or other techniques instead if possible.

$\endgroup$
2
  • $\begingroup$ I made the same selection in bmesh in the updated question but it is twice is slow as the bpy operators from before (when measuring the time difference with time.monotonic(). Should I write the bmesh code differently to get a speedup? $\endgroup$
    – ansonl
    Commented Dec 6 at 22:58
  • $\begingroup$ Added the bmesh code that is somehow slower at the end of the original question since comment can't have code block. $\endgroup$
    – ansonl
    Commented Dec 6 at 23:03

You must log in to answer this question.

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