From 3fe085ea664405ae8a7cf0b050a9fcf7cee11384 Mon Sep 17 00:00:00 2001 From: ranjian0 Date: Wed, 29 Jul 2020 00:04:57 +0300 Subject: [PATCH] Feature: support creation of elements on n-gons (i.e convert ngons to quads) - Works by creating tiny initial inset if face is an ngon and removing unnecessary verts. --- btools/core/balcony/balcony_types.py | 8 +++----- btools/core/door/door_types.py | 7 +++---- btools/core/multigroup/multigroup_types.py | 7 +++---- btools/core/window/window_types.py | 8 ++++---- btools/utils/util_mesh.py | 19 +++++++++++++++++++ 5 files changed, 32 insertions(+), 17 deletions(-) diff --git a/btools/core/balcony/balcony_types.py b/btools/core/balcony/balcony_types.py index 0b812da9..dc1f4ef2 100644 --- a/btools/core/balcony/balcony_types.py +++ b/btools/core/balcony/balcony_types.py @@ -11,8 +11,8 @@ valid_ngon, filter_geom, create_face, + ngon_to_quad, get_top_faces, - popup_message, add_faces_to_map, calc_face_dimensions, ) @@ -22,11 +22,9 @@ def create_balcony(bm, faces, prop): """Generate balcony geometry """ for f in faces: - if not valid_ngon(f): - popup_message("Balcony creation not supported for non-rectangular n-gon!", "Ngon Error") - return False - f.select = False + if not valid_ngon(f): + ngon_to_quad(bm, f) normal = f.normal.copy() f = create_balcony_split(bm, f, prop) diff --git a/btools/core/door/door_types.py b/btools/core/door/door_types.py index 3386669a..52f6774e 100644 --- a/btools/core/door/door_types.py +++ b/btools/core/door/door_types.py @@ -14,7 +14,7 @@ validate, local_xyz, valid_ngon, - popup_message, + ngon_to_quad, map_new_faces, get_top_edges, get_top_faces, @@ -32,11 +32,10 @@ def create_door(bm, faces, prop): """Create door from face selection """ for face in faces: + face.select = False if not valid_ngon(face): - popup_message("Door creation not supported non-rectangular n-gon!", "Ngon Error") - return False + ngon_to_quad(bm, face) - face.select = False clamp_count(calc_face_dimensions(face)[0], prop.frame_thickness * 2, prop) array_faces = subdivide_face_horizontally( bm, face, widths=[prop.size_offset.size.x] * prop.count diff --git a/btools/core/multigroup/multigroup_types.py b/btools/core/multigroup/multigroup_types.py index 27164048..6614fc02 100644 --- a/btools/core/multigroup/multigroup_types.py +++ b/btools/core/multigroup/multigroup_types.py @@ -12,6 +12,7 @@ validate, local_xyz, valid_ngon, + ngon_to_quad, get_top_faces, get_top_edges, popup_message, @@ -40,11 +41,9 @@ def create_multigroup(bm, faces, prop): prop.components = re.sub("[^d|w|]", "", prop.components) for face in faces: - if not valid_ngon(face): - popup_message("Multigroup creation not supported for non-rectangular n-gon!", "Ngon Error") - return False - face.select = False + if not valid_ngon(face): + ngon_to_quad(bm, face) array_faces = subdivide_face_horizontally(bm, face, widths=[prop.size_offset.size.x]*prop.count) for aface in array_faces: diff --git a/btools/core/window/window_types.py b/btools/core/window/window_types.py index e0ce7761..9a3458a9 100644 --- a/btools/core/window/window_types.py +++ b/btools/core/window/window_types.py @@ -14,7 +14,7 @@ valid_ngon, sort_faces, sort_edges, - popup_message, + ngon_to_quad, get_top_edges, get_top_faces, map_new_faces, @@ -35,15 +35,15 @@ def create_window(bm, faces, prop): """Generate a window """ for face in faces: + face.select = False if not valid_ngon(face): - popup_message("Window creation not supported for non-rectangular n-gon", "Ngon Error") - return False + ngon_to_quad(bm, face) - face.select = False clamp_count(calc_face_dimensions(face)[0], prop.frame_thickness * 2, prop) array_faces = subdivide_face_horizontally(bm, face, widths=[prop.size_offset.size.x]*prop.count) for aface in array_faces: face = create_window_split(bm, aface, prop.size_offset.size, prop.size_offset.offset) + window, arch = create_window_frame(bm, face, prop) if prop.type == "RECTANGULAR": fill_window_face(bm, window, prop) diff --git a/btools/utils/util_mesh.py b/btools/utils/util_mesh.py index 37c01772..0aa0c8da 100644 --- a/btools/utils/util_mesh.py +++ b/btools/utils/util_mesh.py @@ -367,3 +367,22 @@ def sort_edges(edges, direction): def sort_verts(verts, direction): return sorted(verts, key=lambda v: direction.dot(v.co)) + + +def ngon_to_quad(bm, face): + """ Try to convert rectangular ngon to quad + Method: + - Perform inset. + - Dissolve all edges that are created from lone(non-corner) verts. + - Dissolve all the lone(non-corner) verts. + """ + + INSET_EPS = 0.0011 + bmesh.ops.inset_individual( + bm, faces=[face], thickness=INSET_EPS, use_even_offset=True + ) + + diss_verts = list({loop.vert for loop in face.loops if equal(loop.calc_angle(), math.pi)}) + diss_edges = list({e for v in diss_verts for e in v.link_edges if e not in face.edges}) + bmesh.ops.dissolve_edges(bm, edges=diss_edges) + bmesh.ops.dissolve_verts(bm, verts=diss_verts)