Skip to content

Commit

Permalink
Feature: support creation of elements on n-gons (i.e convert ngons to…
Browse files Browse the repository at this point in the history
… quads)

- Works by creating tiny initial inset if face is an ngon and removing unnecessary verts.
  • Loading branch information
ranjian0 committed Jul 28, 2020
1 parent 5623663 commit 3fe085e
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 17 deletions.
8 changes: 3 additions & 5 deletions btools/core/balcony/balcony_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
)
Expand All @@ -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)
Expand Down
7 changes: 3 additions & 4 deletions btools/core/door/door_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
validate,
local_xyz,
valid_ngon,
popup_message,
ngon_to_quad,
map_new_faces,
get_top_edges,
get_top_faces,
Expand All @@ -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
Expand Down
7 changes: 3 additions & 4 deletions btools/core/multigroup/multigroup_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
validate,
local_xyz,
valid_ngon,
ngon_to_quad,
get_top_faces,
get_top_edges,
popup_message,
Expand Down Expand Up @@ -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:
Expand Down
8 changes: 4 additions & 4 deletions btools/core/window/window_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
valid_ngon,
sort_faces,
sort_edges,
popup_message,
ngon_to_quad,
get_top_edges,
get_top_faces,
map_new_faces,
Expand All @@ -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)
Expand Down
19 changes: 19 additions & 0 deletions btools/utils/util_mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

0 comments on commit 3fe085e

Please sign in to comment.