2
$\begingroup$
import bpy
from mathutils import Vector

context = bpy.context
obj = context.object
me = obj.data
up = Vector ((0, 0, 1))

for f in me.polygons:
    for face in f.normal:
        if f.normal == up:
            f.select = True

I'm trying to select the top most face on a selected object/objects in Blender 2.93. So I was trying to get the vector information of each face and compare it with my own given vector and from there be able to select. I found couple of problems on my script, first this will select all the faces that are pointing up, so not the top most face will be selected. And the second problem is that this is not selecting anything.

$\endgroup$
2

1 Answer 1

5
$\begingroup$

A normal is a direction a polygon is facing. You want to check e.g. for a median of the face:

import bpy, bmesh
from functools import reduce

me = bpy.context.active_object.data
bm = bmesh.from_edit_mesh(me)

tuples = map(lambda x: (x, x.calc_center_median().z), bm.faces)
reduce(lambda a,b: a if a[1] > b[1] else b, tuples)[0].select_set(True)
bmesh.update_edit_mesh(me)

If you check for the highest vertex (max((v.co.z for v in f.verts))) - then the top vertex may be a part of multiple faces...

import bpy, bmesh

me = bpy.context.active_object.data
bm = bmesh.from_edit_mesh(me)

top_verts = [bm.verts[0]]

for v in bm.verts:
    if v.co.z > top_verts[0].co.z:
        top_verts = [v]
    elif v.co.z == top_verts[0].co.z:
        top_verts.append(v)
        
for v in top_verts:
    for f in v.link_faces:
        f.select_set(True)

bmesh.update_edit_mesh(me)

Comparison of 1st (left) and 2nd (right) scripts:

Keep in mind the first script doesn't allow for ex æquo winners, but it could just as well if you replaced reduce with loop, comparison, append/new list logic.

$\endgroup$

You must log in to answer this question.

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