# Convert polygons or ngons to quads using bmesh

I have imported an SVG keyboard layout into Blender (2.83), which arrives as filled curves in the XY plane.

For each key, after converting the curve to mesh, I have managed to dissolve some edges with bmesh.

    # tris to ngons, separating the bottom from the top
edges = [e for e in bm.edges if e.verts[0].co.y != e.verts[1].co.y]
bmesh.ops.dissolve_edges(bm, edges=edges)


This leaves each key with a quad and a polygon, or ngon, with either 5 or 6 vertices/edges.

I want to subdivide the ngons "vertically" using the existing vertices to make quads (2 quads if 5 verts, 3 quads if 6 verts). I have worked out how to find them, or delete the ngon and keep the edges but am no closer to a solution.

    for f in bm.faces:
if len(f.verts) > 4:
bmesh.ops.delete(bm, geom=[f], context='FACES_ONLY')


In one version of the SVG I manually added extra vertices at the bottom to help create the required edges, but wonder if this useful or pointless (bad pun).

How do I convert these polygons (ngons) with more than 4 sides to quads, adding only vertical edges?

Verts of non-boundary edge.

Assuming the white keys are the mesh, where there is an ngon is at the ends of a non boundary edge

Test script below, finds ngons, bisects using YZ (keys aligned along x axis) plane at boundary edge vert coordinates, removes doubles, and repeats until there are no more ngons.

An additional test to make sure the other two connected edges are at an angle of around 90 degrees has been added. (See below)

import bpy
import bmesh

context = bpy.context
ob = context.edit_object
me = ob.data
bm = bmesh.from_edit_mesh(me)

ngons = [f for f in bm.faces if len(f.edges) > 4]

while ngons:
f = ngons.pop()
def test(v, edge):
e0, e1 = [e for e in v.link_edges if e.is_boundary]
ev0 = (e0.verts[0].co - e0.verts[1].co)
ev1 = (e1.verts[1].co - e1.verts[0].co)
return abs(ev0.dot(ev1)) < 0.1
return False
# find verts of non boundary edge
verts = [v for e in f.edges
if not e.is_boundary
for v in e.verts if test(v, e)]
print(len(verts))
for v in verts:
geom = bmesh.ops.bisect_plane(
bm,
geom=[f] + f.edges[:] + f.verts[:],
plane_co=v.co,
plane_no=((1, 0, 0)),
)
bmesh.ops.remove_doubles(
bm,
verts=bm.verts,
dist=1e-5
)
ngons = [f for f in bm.faces if len(f.edges) > 4]

bmesh.update_edit_mesh(me)

• This works for one bisect if I dont use the while loop, but if I use the loop I get infinite loops. Still probing... Oct 25, 2020 at 10:20
• Allow me to apologize for my uncalled for upvote comment. I have removed it. Using is_boundary found me the answer and you deserve a point for it, rather than me adding a similar answer. And dozens of your answers have helped me in the past Having eventually figured out my issues it wasnt worth uploading a blend and I thought I should share my findings for future readers. Oct 30, 2020 at 14:44