Normal selections

Just to throw it out there, here’s a little script I wrote for a weekend challenge last week.

Basically I had a mesh and I wanted to select faces pointing up within a range, you know the ones likely to be able to support tree growth.

It’s very crude (but works better than ‘Shift + G’ for this purpose).

http://www.avidfish.com/stuff/flight_norms.png

Anyway, at the moment you need to be in face select mode for it too work. I know the issues / limitations of the method used, but, adjust ‘norm’ and ‘ntol’ to desired values for different results.


import bpy

'''

*** Currently requires to be in face select mode!!!


If you get unexpected results, e.g. it seems upside down, then apply the rotation and recalculate the normals.

'''

norm = [0.0, 0.0, 1.0]
#ntol = [0.5, 0.5, 0.5]
ntol = [0.75, 0.75, 0.75]
#ntol = [1.0, 1.0, 1.0]


def obj_print_sel_norms(o):
    for v in o.data.faces:
        if v.select == True:
            print(v.normal[0], v.normal[1], v.normal[2])
    return

def deselect_all(o):
    if bpy.context.mode != 'EDIT_MESH':
        bpy.ops.object.editmode_toggle()
    bpy.ops.mesh.select_all(action='DESELECT')
    return

def check_norm(x, y, z):
    global norm, ntol
    
    if ( (x >= norm[0]-ntol[0])and(x <= norm[0]+ntol[0]) ) and \
        ( (y >= norm[1]-ntol[1])and(y <= norm[1]+ntol[1]) ) and \
        ( (z >= norm[2]-ntol[2])and(z <= norm[2]+ntol[2]) ):
        return True
    return False

def obj_norms(o):
    deselect_all(o)

    bpy.ops.object.mode_set(mode='EDIT')
    bpy.ops.object.mode_set(mode='OBJECT')
    
    for v in o.data.faces:
        if check_norm(v.normal[0], v.normal[1], v.normal[2]):
            v.select = True
    bpy.ops.object.mode_set(mode='EDIT')
    return

print("-----------------------------------")

obj = bpy.context.object
#obj_print_sel_norms(obj)
obj_norms(obj)

Oh, if you want to find the normal of a face then unselect ‘obj_print_sel_norms(obj)’ and have a face selected, then look in the console for it’s normal.

Have fun!

r