select faces using another face's normal as the direction?


(toomanydemons) #1

I’m new to coding and am trying to put together a script which cuts selected faces by a plane, and removes geometry that is “lower” than that plane (from the selected faces).

So far I have a script that will bisect the selected faces by the active face. What I want to do is remove or “clip off” the geometry below the bisect line (using the active face’s opposite normal direction).

I’ve been up all night look for ways to do this and trying a lot of things, to no avail.:no: I’m not experienced enough in coding to select by direction. I could very much use some assistance!

this is my code so far:

import bpy, bmesh

#Get the active mesh
obj = bpy.context.edit_object
me = obj.data

#Get a BMesh representation
bm = bmesh.from_edit_mesh(me)

#Get selected geometry:
edges = [e for e in bm.edges if e.select]
faces = [f for f in bm.faces if f.select]
geom = []
geom.extend(edges)
geom.extend(faces)

selected_faces = [f for f in bm.faces if f.select]

#Get active face as the cutter:
active_face = bm.faces.active
active_normal = active_face.normal
active_location = active_face.calc_center_median()

#Bisect
result = bmesh.ops.bisect_plane(bm, geom = geom, dist = -0.00, plane_co = active_location, plane_no = active_normal, clear_inner= True)

#I can’t figure out this part
for f in selected_faces:
face_location = f.calc_center_median()
if face_location < active_location:
f.select = True
else:
f.select = False

bmesh.update_edit_mesh (me, True)


(tetii) #2

The following code seem to work well.


geom_faces = [f for f in result['geom'] if isinstance(f, bmesh.types.BMFace)]
bm.select_mode = {'FACE'}
for f in bm.faces:
    if not f in geom_faces:
        f.select = False
        continue
    v = f.calc_center_median() - active_location
    if v.dot(active_normal) &lt; 0:
        f.select = True
    else:
        f.select = False


(tetii) #3

I have made the following code and it seems to work fine.


geom_faces = [f for f in result['geom'] if isinstance(f, bmesh.types.BMFace)]
bm.select_mode = {'FACE'}
for f in bm.faces:
    if not f in geom_faces:
        f.select = False
        continue
    v = f.calc_center_median() - active_location
    if v.dot(active_normal) &lt; 0:
        f.select = True
    else:
        f.select = False
bm.select_flush_mode()
bmesh.update_edit_mesh(me)


(tetii) #4

I have made the following code and it seems to work fine.

geom_faces = [f for f in result[‘geom’] if isinstance(f, bmesh.types.BMFace)]
bm.select_mode = {‘FACE’}
for f in bm.faces:
if not f in geom_faces:
f.select = False
continue
v = f.calc_center_median() - active_location
if v.dot(active_normal) < 0:
f.select = True
else:
f.select = False
bm.select_flush_mode()
bmesh.update_edit_mesh(me)


(toomanydemons) #5

Epic! Thank you so much for the response. I’m going to try this right away.


(toomanydemons) #6

@tetii

this works perfectly, thanks very much for the lesson. I’ll definitely study what you’ve done here. I’m extremely new to this (but ambitious…) lol!

Now I have a nice tool that will clip recessed geometry and save on UV/Texture space while modeling. Super great!