0
$\begingroup$

I'm a looking for a simple and fast way to find the lower left vertex index of a quad with python. What I've tried so far is to change the coordonate system to fit with the normal and sort the coordonnate of the vertices to the x and y axes and get the first element. Unfortunately this doesn't seem to work, any idea of a simple solution ?

lower left vertex of a plane

$\endgroup$
2
$\begingroup$

I think, this is doing the job:

enter image description here

The principle is the following:

  • Get objects faces that are quads
  • For each face, get its normal in world coordinates
  • Define a left axis from a (0, 0, -1) vector and this normal (cross product)
  • Get the face's vertices and calculate their center
  • Compare each "v minus center" in world coordinates to the left axis
  • From this, take the lower (along z) vertex

Here is the commented code

import bpy
from mathutils import Vector

def SelectLowerLeft( obj, polygon ):
    worldMat = obj.matrix_world    
    normalInWorld = worldMat * polygon.normal
    polygonVertices = [obj.data.vertices[vI] for vI in polygon.vertices]

    if abs(normalInWorld[2]) == 1.0: #If normal is along Z, all are lower left... a choice
        for v in polygonVertices: v.select = True
    else:
        #Left axis is defined from down (Z=-1) cross the normal
        leftAxis = Vector( (0, 0, -1) ).cross( normalInWorld )
        #Create pairs of vertex and in world coordinates, sorted by z in world
        verticesAndWorldCo = sorted( [(v, worldMat * v.co) for v in polygonVertices], key=lambda vAndco: vAndco[1][2] )
        #Center of the polygon
        centerInWorld = sum( [co for v, co in verticesAndWorldCo], Vector() ) / len(verticesAndWorldCo)
        #Take the first going left        
        for toSelect in [v for v, co in verticesAndWorldCo if (co - centerInWorld).dot( leftAxis ) > 0]:
            toSelect.select = True
            return          
print( '-------------' )


obj = bpy.context.object

data = obj.data

prevMode = obj.mode

#Deselect all
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='DESELECT')

#To be able to select via 'select' property
bpy.ops.object.mode_set(mode='OBJECT')

#All object's polygons that are quads   
for polygon in [p for p in data.polygons if len(p.vertices) == 4]:
    SelectLowerLeft( obj, polygon )

bpy.ops.object.mode_set(mode=prevMode)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.