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

2
$\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$ Commented Dec 6, 2024 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$ Commented Dec 6, 2024 at 23:03

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.