mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-08 17:01:40 +00:00
See #1227. Experimental support for 3D layerset slicing.
This commit is contained in:
@@ -69,6 +69,9 @@ class MaterialCreator:
|
||||
if isinstance(mesh, bpy.types.Curve):
|
||||
return
|
||||
|
||||
if mesh.get("has_layer_styles", None) == True:
|
||||
return
|
||||
|
||||
self.mesh = mesh
|
||||
self.obj = obj
|
||||
if element.is_a("IfcTypeProduct"):
|
||||
@@ -1059,12 +1062,13 @@ class IfcImporter:
|
||||
else:
|
||||
mesh["has_cartesian_point_offset"] = False
|
||||
|
||||
return tool.Loader.convert_geometry_to_mesh(
|
||||
mesh = tool.Loader.convert_geometry_to_mesh(
|
||||
geometry,
|
||||
mesh,
|
||||
verts=verts,
|
||||
load_indexed_maps=self.ifc_import_settings.load_indexed_maps,
|
||||
)
|
||||
return tool.Loader.slice_layerset_mesh(element, mesh)
|
||||
except:
|
||||
self.ifc_import_settings.logger.error("Could not create mesh for %s", element)
|
||||
import traceback
|
||||
|
||||
@@ -1018,6 +1018,74 @@ class Loader(bonsai.core.tool.Loader):
|
||||
mesh["ios_material_ids"] = ifcopenshell.util.shape.get_faces_material_style_ids(geometry).tolist()
|
||||
return mesh
|
||||
|
||||
@classmethod
|
||||
def slice_layerset_mesh(cls, element: ifcopenshell.entity_instance, mesh: bpy.types.Mesh) -> bpy.types.Mesh:
|
||||
if True: # This feature is still experimental
|
||||
return mesh
|
||||
if not (material := ifcopenshell.util.element.get_material(element)):
|
||||
return mesh
|
||||
elif material.is_a("IfcMaterialLayerSetUsage"):
|
||||
usage = material
|
||||
layer_set = material.ForLayerSet
|
||||
offset = usage.OffsetFromReferenceLine * cls.unit_scale
|
||||
sense_factor = 1 if usage.DirectionSense == "POSITIVE" else -1
|
||||
elif material.is_a("IfcMaterialLayerSet"):
|
||||
usage = None
|
||||
layer_set = material
|
||||
offset = 0
|
||||
sense_factor = 1
|
||||
else:
|
||||
return mesh
|
||||
if len(layer_set.MaterialLayers) == 1:
|
||||
return mesh
|
||||
bm = bmesh.new()
|
||||
bm.from_mesh(mesh)
|
||||
prev_co = None
|
||||
co = Vector((0.0, offset, 0.0))
|
||||
no = Vector((0.0, 1.0, 0.0))
|
||||
# Cache this
|
||||
body = ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Model", "Body", "MODEL_VIEW")
|
||||
styles = {}
|
||||
has_layer_styles = False
|
||||
for i, material in mesh.materials:
|
||||
if style := tool.Ifc.get_entity(material):
|
||||
styles[style] = i
|
||||
for layer in layer_set.MaterialLayers[:-1]:
|
||||
prev_co = co.copy()
|
||||
co.y = layer.LayerThickness * cls.unit_scale * sense_factor
|
||||
bisect_geom = bmesh.ops.bisect_plane(
|
||||
bm, geom=bm.verts[:] + bm.edges[:] + bm.faces[:], dist=0.0001, plane_co=co, plane_no=no
|
||||
)
|
||||
bmesh.ops.duplicate(bm, geom=bisect_geom["geom_cut"])
|
||||
if style := ifcopenshell.util.representation.get_material_style(layer.Material, body):
|
||||
if (material_index := styles.get(style, None)) is None:
|
||||
material_index = len(mesh.materials)
|
||||
mesh.materials.append(tool.Ifc.get_object(style))
|
||||
for face in bisect_geom["geom"]:
|
||||
if isinstance(face, bmesh.types.BMFace):
|
||||
center = face.calc_center_bounds() * sense_factor
|
||||
if center.y < co.y and center.y > prev_co.y:
|
||||
face.material_index = material_index
|
||||
has_layer_styles = True
|
||||
|
||||
# Last layer
|
||||
layer = layer_set.MaterialLayers[-1]
|
||||
if style := ifcopenshell.util.representation.get_material_style(layer.Material, body):
|
||||
if (material_index := styles.get(style, None)) is None:
|
||||
material_index = len(mesh.materials)
|
||||
mesh.materials.append(tool.Ifc.get_object(style))
|
||||
for face in bisect_geom["geom"]:
|
||||
if isinstance(face, bmesh.types.BMFace):
|
||||
center = face.calc_center_bounds() * sense_factor
|
||||
if center.y > co.y:
|
||||
face.material_index = material_index
|
||||
has_layer_styles = True
|
||||
|
||||
bm.to_mesh(mesh)
|
||||
bm.free()
|
||||
mesh["has_layer_styles"] = has_layer_styles
|
||||
return mesh
|
||||
|
||||
@classmethod
|
||||
def create_mesh_from_shape(
|
||||
cls,
|
||||
|
||||
Reference in New Issue
Block a user