Is it possible to select a group of edges that fit two selection conditions? For example, first select face edges based on the number of sides a face has (using the Select All by Trait command Faces By Sides) then of those selected edges only select the edges that are also boundary edges. I have a complex mesh that has some faces with 3 sides and I want to collapse only the boundary edge of those 3 sides faces.
2 Answers
You can set the first condition and select the edges, then invert the selection (Ctrl I) and hide all the others edges (H), then set the second condition, perform the edit, then unhide all (Alt H).
Another method, that can be useful in your case, set the selection by second condition and press Ctrl G to assign theese vertices to a new vertex group (that you can call "Boundary"). Then select a triangle in face select mode, press Shift G to select by polygon sides, Shift H to hide the inverted selection, go to vertex select mode, deselect all and press "Select" in the vertex groups properties tab.
Then a "Merge by distance" (M) should solve most of the problems.
I would work on a copy of the mesh and do some manual snapping for cleaning the resulting mesh where necessary. Also Automerge vertices function can be useful for some manual cleaning.
-
$\begingroup$ +1.. A couple of extra details? ..the first 2 moves are Shift-H, and you have to uncheck 'Select' in the Alt H 'Reveal Hidden'. Or, at least, I do.. the default is annoyingly the wrong choice, IMO. $\endgroup$– Robin Betts ♦Sep 2, 2022 at 20:46
-
$\begingroup$ Hi @josh-sanfelici and Robin thanks for the help but I tried this and I wasn't able to make it work. After I select edges with the first condition (3 sided faces) and then hide the inverted selection I am left with new and different boundary loops that are not the same as the boundary loops of the original mesh. The second condition (boundary loop edges of the original unhidden mesh) therefore can't be met. I'm not sure if I'm doing the correct sequence of what you guys are suggesting. The goal of this is to remove faces with 3 sides. I have already run the Tris to Quads command. $\endgroup$ Sep 4, 2022 at 19:04
-
I was able to accomplish what I wanted with the following python script:
import bpy
import datetime
t = datetime.datetime.now()
## GET TRI EDGES (First Condition)###########################################
bpy.ops.object.mode_set(mode = 'EDIT')
bpy.ops.mesh.select_all(action='DESELECT')
## create list to store triangle edges IDs (edges for first condition)
tri_edge_ids = []
## Select all edges of triangles and store their IDs in list created above
bpy.ops.mesh.select_face_by_sides(number=4, type='LESS', extend=False)
## switch to Object Mode first for the selected edges to get "registered"
bpy.ops.object.mode_set(mode = 'OBJECT')
## store edges in list created above and sort list
for edge in bpy.context.active_object.data.edges:
if edge.select:
tri_edge_ids.append(edge.index)
tri_edge_ids.sort()
## Print the list with edge indecies to the console for debugging purposes
print(t, "Tris edge IDs (3 sided faces): ", tri_edge_ids)
############################################################################
## GET NON MANIFOLD EDGES (Second Condition)##################################
bpy.ops.object.mode_set(mode = 'EDIT')
bpy.ops.mesh.select_all(action='DESELECT')
## create list to store non-manifold edges IDs (edges for second condition)
non_manifold_edges = []
## Select non-manifold edges and store their IDs in list created above
bpy.ops.mesh.select_non_manifold()
## switch to Object Mode first for the selected edges to get "registered"
bpy.ops.object.mode_set(mode = 'OBJECT')
## store edges in list created above and sort list
for edge in bpy.context.active_object.data.edges:
if edge.select:
non_manifold_edges.append(edge.index)
non_manifold_edges.sort()
## Print the non-manifold edge IDs to the Console for debugging purposes
print(t, "Non-manifold edge IDs: ", non_manifold_edges)
############################################################################
## GET MATCHING EDGES ########################################################
bpy.ops.object.mode_set(mode = 'EDIT')
bpy.ops.mesh.select_all(action='DESELECT')
## Create list for storing matched edges
## Assign to the list only the edges whose ID is present in both lists
matching_edges = list(set(tri_edge_ids) & set(non_manifold_edges))
matching_edges.sort()
## switch to Object Mode first for the selected edges to get "registered"
bpy.ops.object.mode_set(mode = 'OBJECT')
for edge in matching_edges:
bpy.context.active_object.data.edges[edge].select = True
## Print the matching edge IDs to the Console for debugging purposes
print(t, "Matching Edge IDs: ", matching_edges)
bpy.ops.object.mode_set(mode = 'EDIT')
############################################################################