5
$\begingroup$

I have empty squares (those with exactly 4 edges only) in my 2D mesh and I need to fill them with faces via python but I don't know how to automatically select these edges. Is it possible to select all of these regions marked in orange via python?

enter image description here

This is what I tried. I selected all edges that have linked exactly only 1 face. Unfortunately it selects the boundary edges as well so I tried doing an and not edge.is_boundary but then nothing gets selected since the small squares inside are apparently also boundary edges.

import bpy
import bmesh

obj = bpy.context.active_object
mesh = obj.data

bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='DESELECT')

bm = bmesh.from_edit_mesh(mesh)

for edge in bm.edges:
    edge.select = False

edges_to_select = []

for edge in bm.edges:
    if len(edge.link_faces) == 1: #and not edge.is_boundary:
        edges_to_select.append(edge)

for edge in edges_to_select:
    edge.select = True

bmesh.update_edit_mesh(mesh)

Here's another try where I almost got the result:

enter image description here

import bpy
import bmesh

obj = bpy.context.active_object
mesh = obj.data

bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='DESELECT')

bm = bmesh.from_edit_mesh(mesh)

for edge in bm.edges:
    edge.select = False

edges_to_select = []

for edge in bm.edges:
    if len(edge.link_faces) == 1:
        vertices_with_four_edges = all(len(v.link_edges) == 4 for v in edge.verts)
        if vertices_with_four_edges:
            edges_to_select.append(edge)

for edge in edges_to_select:
    edge.select = True

bmesh.update_edit_mesh(mesh)
$\endgroup$

3 Answers 3

5
$\begingroup$

I found a solution. First I select all the edges that have only 1 face linked to them and then check that all of the vertices have exactly 4 edges linked to them:

import bpy
import bmesh

obj = bpy.context.active_object
mesh = obj.data

bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='DESELECT')

bm = bmesh.from_edit_mesh(mesh)

edge_selection = []

for edge in bm.edges:
    if len(edge.link_faces) != 1:
        continue
    vertices_with_four_edges = all(len(v.link_edges) == 4 for v in edge.verts)
    if vertices_with_four_edges:
        edge_selection.append(edge)
        edge.select = True

This will result in something like this:

enter image description here

And then I continue on to deselect the excess edges by checking if each edge has both of its vertices shared with a selected edge or else deselect it.

for edge in edge_selection:
    if not any(linked_edge in edge_selection and linked_edge.select for linked_edge in edge.verts[0].link_edges if linked_edge != edge) or \
       not any(linked_edge in edge_selection and linked_edge.select for linked_edge in edge.verts[1].link_edges if linked_edge != edge):
        edge.select = False

bmesh.update_edit_mesh(mesh)

In the process I found a bug where I had to check that linked_edge != edge. This is unexpected behavior that a linked edge as its own self edge is included in the list.

$\endgroup$
2
$\begingroup$

How to find a hold with only 4 edges

import bpy
import bmesh

def get_all_closed_path(bm, length=4):
    for vert0 in bm.verts:
        for edge0 in vert0.link_edges:
            v0, v1 = edge0.verts
            vert1 = v0  if vert0 is v1 else v1

            for edge1 in vert1.link_edges:
                if edge1 is edge0: continue
                v0, v1 = edge1.verts
                vert2 = v0  if v1 in {vert0, vert1} else v1
                if vert2 in {vert0, vert1}: continue

                for edge2 in vert2.link_edges:
                    if edge2 in {edge0, edge1}: continue
                    v0, v1 = edge2.verts
                    vert3 = v0  if v1 in {vert1, vert2} else v1
                    if vert3 in {vert0, vert1, vert2}: continue

                    for edge3 in vert3.link_edges:
                        if edge3 in {edge0, edge1, edge2}: continue
                        v0, v1 = edge3.verts
                        if v0 is vert0: yield vert0, vert1, vert2, vert3
                        if v1 is vert0: yield vert0, vert1, vert2, vert3


obj = bpy.context.active_object
mesh = obj.data

bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='VERT')

bm = bmesh.from_edit_mesh(mesh)

def fill_one(bm):
    verts_group_of_faces = [set(face.verts)  for face in bm.faces]

    for verts in get_all_closed_path(bm):
        if set(verts) in verts_group_of_faces: continue

        bm.faces.new(verts)
        return True
    return False

while fill_one(bm):
    bmesh.update_edit_mesh(mesh)

bmesh.update_edit_mesh(mesh)
bm.free()
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.mode_set(mode='EDIT')
$\endgroup$
1
  • $\begingroup$ hey thank you very much for your answer i gave you +1 but it's very slow due to too many loops. check out my answer it's very fast :) $\endgroup$
    – Megan Love
    Commented Apr 30 at 7:32
0
$\begingroup$

Select a hole (4 vertices)

enter image description here

import bpy
import bmesh

bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_similar(type='VERT_EDGES', threshold=0.01)
bpy.ops.mesh.fill()
bpy.ops.mesh.tris_convert_to_quads()

# remove overlapping faces
obj = bpy.context.active_object
mesh = obj.data

def remove_overlap_face(faces):
    for face in faces:
        verts = set(face.verts)
        if any(verts == set(f.verts) for f in faces if f is not face):
            faces.remove(face)
            return True
    return False

bm = bmesh.from_edit_mesh(mesh)

while remove_overlap_face(bm.faces): pass

bmesh.update_edit_mesh(mesh)

Result:

enter image description here

$\endgroup$
1
  • 1
    $\begingroup$ hi thank you for your answer. unfortunately i need to be able to automate this, meaning i can't just select anything manually. also its very heavy processing the script. oh and it also didnt work snipboard.io/HBwEIR.jpg this is the mesh blend-exchange.com/b/rgaLzEJ0 tested script on 4.1 since it doesnt work on other versions. $\endgroup$
    – Megan Love
    Commented Apr 29 at 14:30

You must log in to answer this question.

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