1

In Python, Is there an operator that selects the vertex (or vertices if applies) that has the lowest value on a global axis (let's say Z).
I have an object that I need to select it's bottom vertex/vertices (the ones with the lowest Z global value) using Python, in order to move it's origin to the Median point among these vertices later.

Georges D
  • 4,962
  • 6
  • 40
  • 70

4 Answers4

1

I'm a noob when it comes to python but won't this do the job?

import bpy
import bmesh 

object = bpy.data.scenes[0].objects["Cube"].data
vcount = len(object.vertices)
cube = bmesh.from_edit_mesh(object)

if (vcount > 0):
    lowest = cube.verts[0]
    for i in range(vcount):
        if (lowest.co.z > cube.verts[i].co.z):
            lowest = cube.verts[i]

    for v in cube.verts:
        if (v.co.z == lowest.co.z):
            v.select = True
        else:
            v.select = False
bmesh.update_edit_mesh(object, True)
  • Thank you for your answer, I tried this script on a Cube object, it's selecting only one vertex, even though 4 vertices have the same Z value, is there a way to select all vertices with the same value? Reading the code, I expected it to select all vertices with the same Z, but that's not the case. – Georges D Jun 12 '16 at 11:31
1

enter image description here

Here's a slightly shorter and faster way to do this (Version <2.8):

import bpy

o = bpy.context.object # active object mw = o.matrix_world # Active object's world matrix

glob_vertex_coordinates = [ mw * v.co for v in o.data.vertices ] # Global coordinates of vertices

Find the lowest Z value amongst the object's verts

minZ = min( [ co.z for co in glob_vertex_coordinates ] )

Select all the vertices that are on the lowest Z

for v in o.data.vertices: if (mw * v.co).z == minZ: v.select = True

Version > 2.8

import bpy

o = bpy.context.object # active object mw = o.matrix_world # Active object's world matrix

glob_vertex_coordinates = [ mw @ v.co for v in o.data.vertices ] # Global coordinates of vertices

Find the lowest Z value amongst the object's verts

minZ = min( [ co.z for co in glob_vertex_coordinates ] )

Select all the vertices that are on the lowest Z

for v in o.data.vertices: if (mw @ v.co).z == minZ: v.select = True

n1cK
  • 230
  • 3
  • 9
TLousky
  • 16,043
  • 1
  • 40
  • 72
  • Thank you for taking the time to answer my question, however, I'm getting an Error here: minZ = min( [ co.z for co in glob_vertex_coordinates ] ), an unexpected indent, and a unknown location (-1) – Georges D Jun 12 '16 at 11:26
  • 1
    Well now it worked!! I tried this several times with no luck, looks like I was doing something wrong, thank you, great answer! – Georges D Jun 12 '16 at 11:32
0

This code will find and select the lowest vertix: (Must be in Edit mode)

import bpy
import bmesh

obj = context.active_object wm = obj.matrix_world #data = obj.data bm = bmesh.from_edit_mesh(obj.data) vertices = [e for e in bm.verts] minZ = 999999.8 for v in vertices: world = wm * v.co if (world[2] < minZ): minZ = world[2] lowest = v

lowest.select= True bmesh.update_edit_mesh(obj.data, True)

0

I had a similar need as this question, to find the lowest vertex in the Z dimension. However, I needed to find the lowest/highest % of vertices in any/all dimensions. Here's a script that will let you do just that.

Blender version: 2.92.0

How to use:

  1. In Object mode, select your object(s) that you want to find the min/max vertices per dimension.
  2. Run the script. It will select vertices and then switch to edit mode so you can see them.

Disclaimer: I barely know how to use Blender (including scripting in it). This script is not efficient and could probably be improved greatly.

I wrote this script to select the the vertices in this picture. My goal is to create a mesh representing the rectangular "bounding box" which encapsulates all of these vertices.

enter image description here

import bpy
#### User params
threshold = 0.004 #Percent out of 1
select = ['-x', '+x', '-y', '+y']#, '+z']
invert = False #Select the lower or higher {threshold}% per dimension?
#### end User params

class TransformedVertex: def init(self, obj, vert): self.obj = obj self.vert = vert self.world_vert = self.obj.matrix_world @ self.vert.co

def isWithinThreshold(dimensionNear, dimensionFar, myDimensionPos, threshold): totalDiff = abs(dimensionNear - dimensionFar) diffFromNearDimension = abs(dimensionNear - myDimensionPos)

return (diffFromNearDimension / totalDiff) &lt;= threshold

Can only do this work in object mode

bpy.ops.object.mode_set(mode = 'OBJECT')

All selected objects

objects = bpy.context.selected_objects

All vertices from selected objects, transformed to world coordinates

worldVertices = [] for o in objects: for v in o.data.vertices: worldVertices.append(TransformedVertex(o, v))

Find the lowest and highest value amongst the verts

allX = [ wv.world_vert.x for wv in worldVertices ] minX = min( allX ) maxX = max( allX )

allY = [ wv.world_vert.y for wv in worldVertices ] minY = min( allY ) maxY = max( allY )

allZ = [ wv.world_vert.z for wv in worldVertices ] minZ = min( allZ ) maxZ = max( allZ )

Select all the vertices that are on the lowest {threshold}% of their dimension

for wv in worldVertices: vertX = wv.world_vert.x vertY = wv.world_vert.y vertZ = wv.world_vert.z wv.vert.select = invert

# X
if ('-x' in select) and isWithinThreshold(minX, maxX, vertX, threshold): wv.vert.select = not invert
if ('+x' in select) and isWithinThreshold(maxX, minX, vertX, threshold): wv.vert.select = not invert

# Y
if ('-y' in select) and isWithinThreshold(minY, maxY, vertY, threshold): wv.vert.select = not invert
if ('+y' in select) and isWithinThreshold(maxY, minY, vertY, threshold): wv.vert.select = not invert

# Z
if ('-z' in select) and isWithinThreshold(minZ, maxZ, vertZ, threshold): wv.vert.select = not invert
if ('+z' in select) and isWithinThreshold(maxZ, minZ, vertZ, threshold): wv.vert.select = not invert

cnt = sum([1 for wv in worldVertices if wv.vert.select])
print ("selected " + str(cnt) + " vertices")

See results in edit mode

bpy.ops.object.mode_set(mode = 'EDIT')