1
$\begingroup$

enter image description hereI'm trying to select the top and bottom face of meshes and delete them.

So far, the code I have just deletes to first face but not the second. It would probably be more efficient to select both top and bottom together and delete them in one go rather than one, then the other, but I'll be happy with whatever just works. Any help anyone can offer would be most appreciated. Thanks

import bpy
from mathutils import Vector

def NormalInDirection( normal, direction, limit = 0.5 ):
    return direction.dot( normal ) > limit

def GoingUp( normal, limit = 0.5):
    return NormalInDirection( normal, Vector( (0, 0, 1 ) ), limit )

def GoingDown( normal, limit = 0.5):
   return NormalInDirection( normal, Vector( (0, 0, -1 ) ), limit )

def GoingSide( normal, limit = 0.5):
    return GoingUp( normal, limit ) == False and GoingDown( normal, limit ) == False

obj = bpy.context.object

#bpy.ops.object.editmode_toggle()

prevMode = obj.mode

bpy.ops.object.mode_set(mode='OBJECT', toggle=False)

#Selects faces going up
for face in obj.data.polygons:
    face.select = GoingUp( face.normal ) 

bpy.ops.object.mode_set(mode=prevMode, toggle=False)

bpy.ops.mesh.delete(type='FACE')

#Selects faces going down
for face in obj.data.polygons:
    face.select = GoingDown( face.normal ) 

bpy.ops.object.mode_set(mode=prevMode, toggle=False)

bpy.ops.mesh.delete(type='FACE') 
$\endgroup$

1 Answer 1

4
$\begingroup$

You can use bmesh and bmesh.ops to do it.

The code is commented below:

import bpy
import bmesh
from mathutils import Vector

def NormalInDirection( normal, direction, limit = 0.5 ):
    return direction.dot( normal ) > limit

def GoingUp( normal, limit = 0.5):
    return NormalInDirection( normal, Vector( (0, 0, 1 ) ), limit )

def GoingDown( normal, limit = 0.5):
   return NormalInDirection( normal, Vector( (0, 0, -1 ) ), limit )

def GoingSide( normal, limit = 0.5):
    return GoingUp( normal, limit ) == False and GoingDown( normal, limit ) == False

obj = bpy.context.object

prevMode = obj.mode

# Will need to be in object mode
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)

# Create a bmesh access
bm = bmesh.new()
bm.from_mesh( obj.data )

# Get faces access
bm.faces.ensure_lookup_table()

# Identify the wanted faces
faces = [f for f in bm.faces if GoingUp( f.normal ) or GoingDown( f.normal )]

# Delete them
bmesh.ops.delete( bm, geom = faces, context = 'FACES_ONLY' )

# Push the geometry back to the mesh
bm.to_mesh( obj.data )

# Back to the initial mode
bpy.ops.object.mode_set(mode=prevMode, toggle=False)
$\endgroup$
2
  • $\begingroup$ Thank you, that worked great for me on 2.8. $\endgroup$
    – James
    Aug 31, 2019 at 11:53
  • $\begingroup$ Thank you so much. You've helped me solve a completely different problem. $\endgroup$ Jul 21, 2021 at 12:11

You must log in to answer this question.

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