mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-28 11:18:18 +00:00
Skip parts without polygons converting mesh to tessellation #5870
As IFC doesn't allow mixed geometry types anyway.
This commit is contained in:
@@ -217,6 +217,12 @@ class AssignClass(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
should_add_representation = False
|
should_add_representation = False
|
||||||
export_mesh_to_tesselation = True
|
export_mesh_to_tesselation = True
|
||||||
|
|
||||||
|
if tool.Geometry.mesh_has_loose_geometry(obj.data):
|
||||||
|
self.report(
|
||||||
|
{"WARNING"},
|
||||||
|
f"Mesh '{obj.data.name}' has loose geometry, loose geometry was be ignored to save mesh to IFC as a tessellation.",
|
||||||
|
)
|
||||||
|
|
||||||
element = core.assign_class(
|
element = core.assign_class(
|
||||||
tool.Ifc,
|
tool.Ifc,
|
||||||
tool.Collector,
|
tool.Collector,
|
||||||
|
|||||||
@@ -1727,6 +1727,10 @@ class Geometry(bonsai.core.tool.Geometry):
|
|||||||
items = []
|
items = []
|
||||||
meshes = cls.split_by_loose_parts(obj)
|
meshes = cls.split_by_loose_parts(obj)
|
||||||
for mesh in meshes:
|
for mesh in meshes:
|
||||||
|
# Skip parts that won't work for tessellation.
|
||||||
|
if not mesh.polygons:
|
||||||
|
bpy.data.meshes.remove(mesh)
|
||||||
|
continue
|
||||||
verts = [v.co / unit_scale for v in mesh.vertices]
|
verts = [v.co / unit_scale for v in mesh.vertices]
|
||||||
faces = [p.vertices[:] for p in mesh.polygons]
|
faces = [p.vertices[:] for p in mesh.polygons]
|
||||||
item = builder.mesh(verts, faces)
|
item = builder.mesh(verts, faces)
|
||||||
@@ -1750,3 +1754,28 @@ class Geometry(bonsai.core.tool.Geometry):
|
|||||||
ifcopenshell.api.style.assign_item_style(tool.Ifc.get(), item=item, style=style)
|
ifcopenshell.api.style.assign_item_style(tool.Ifc.get(), item=item, style=style)
|
||||||
bpy.data.meshes.remove(mesh)
|
bpy.data.meshes.remove(mesh)
|
||||||
return builder.get_representation(ifc_context, items)
|
return builder.get_representation(ifc_context, items)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def mesh_has_loose_geometry(cls, mesh: bpy.types.Mesh) -> bool:
|
||||||
|
"""Check if mesh has loose geometry (edges without faces, verts without edges)."""
|
||||||
|
bm = tool.Blender.get_bmesh_for_mesh(mesh)
|
||||||
|
|
||||||
|
# Most of the time it will return `False`,
|
||||||
|
# so checking verts for being manifold
|
||||||
|
# should be the fastest way to proceed in those cases.
|
||||||
|
non_manifold_edges = set()
|
||||||
|
for vert in bm.verts:
|
||||||
|
if not vert.is_manifold:
|
||||||
|
# Not all non-manifold verts mean loose geometry
|
||||||
|
# e.g. a vert shared by 2 planes.
|
||||||
|
if not vert.link_faces:
|
||||||
|
return True
|
||||||
|
non_manifold_edges.update(vert.link_edges)
|
||||||
|
|
||||||
|
if not non_manifold_edges:
|
||||||
|
return False
|
||||||
|
|
||||||
|
for edge in non_manifold_edges:
|
||||||
|
if not edge.link_faces:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|||||||
Reference in New Issue
Block a user