Fix bug where extrusion detection on voided profiles was not reliable

This commit is contained in:
Dion Moult
2021-06-17 19:24:16 +10:00
parent 1b49a10a15
commit 2a2f4d692a
2 changed files with 16 additions and 7 deletions
@@ -1,5 +1,6 @@
import bpy import bpy
import bmesh import bmesh
import mathutils
import ifcopenshell import ifcopenshell
import ifcopenshell.util.unit import ifcopenshell.util.unit
from math import pi from math import pi
@@ -197,19 +198,26 @@ class Helper:
return {"profile": outer_loop, "inner_curves": inner_loops, "extrusion": extrusion} return {"profile": outer_loop, "inner_curves": inner_loops, "extrusion": extrusion}
# An extrusion edge is an edge that shares a single vertex with a profile # An extrusion edge is an edge that shares a single vertex with a profile
# face and is not parallel to the face. # face and is not on the plane of the face.
def detect_extrusion_edge(self, bm, profile_face): def detect_extrusion_edge(self, bm, profile_face):
bm.edges.ensure_lookup_table() bm.edges.ensure_lookup_table()
extrusion = None extrusion = None
face_verts_set = set(profile_face.verts) face_verts_set = set(profile_face.verts)
for edge in bm.edges: for edge in bm.edges:
edge_vector = edge.verts[1].co - edge.verts[0].co
unshared_verts = set(edge.verts) - face_verts_set unshared_verts = set(edge.verts) - face_verts_set
angle_to_normal = edge_vector.angle(profile_face.normal) if len(unshared_verts) == 1:
if len(unshared_verts) == 1 and (angle_to_normal < 0.001 or angle_to_normal - pi < 0.001): unshared_vert = unshared_verts.pop()
if unshared_verts.pop() == edge.verts[1]: if (
return [edge.verts[0].index, edge.verts[1].index] abs(
return [edge.verts[1].index, edge.verts[0].index] mathutils.geometry.distance_point_to_plane(
unshared_vert.co, profile_face.verts[0].co, profile_face.normal
)
)
> 0.001
):
if unshared_vert == edge.verts[1]:
return [edge.verts[0].index, edge.verts[1].index]
return [edge.verts[1].index, edge.verts[0].index]
def create_extruded_area_solid(self, mesh, extrusion_indices, profile_def): def create_extruded_area_solid(self, mesh, extrusion_indices, profile_def):
position = self.create_ifc_axis_2_placement_3d( position = self.create_ifc_axis_2_placement_3d(
@@ -82,6 +82,7 @@ class Usecase:
faces = [f for f in bm.faces if self.should_triangulate_face(f)] faces = [f for f in bm.faces if self.should_triangulate_face(f)]
bmesh.ops.triangulate(bm, faces=faces) bmesh.ops.triangulate(bm, faces=faces)
bm.to_mesh(mesh) bm.to_mesh(mesh)
mesh.update()
bm.free() bm.free()
del bm del bm