3
$\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

3
$\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$ Commented Apr 30, 2024 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$ Commented Apr 29, 2024 at 14:30

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.