mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +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):
|
if isinstance(mesh, bpy.types.Curve):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if mesh.get("has_layer_styles", None) == True:
|
||||||
|
return
|
||||||
|
|
||||||
self.mesh = mesh
|
self.mesh = mesh
|
||||||
self.obj = obj
|
self.obj = obj
|
||||||
if element.is_a("IfcTypeProduct"):
|
if element.is_a("IfcTypeProduct"):
|
||||||
@@ -1059,12 +1062,13 @@ class IfcImporter:
|
|||||||
else:
|
else:
|
||||||
mesh["has_cartesian_point_offset"] = False
|
mesh["has_cartesian_point_offset"] = False
|
||||||
|
|
||||||
return tool.Loader.convert_geometry_to_mesh(
|
mesh = tool.Loader.convert_geometry_to_mesh(
|
||||||
geometry,
|
geometry,
|
||||||
mesh,
|
mesh,
|
||||||
verts=verts,
|
verts=verts,
|
||||||
load_indexed_maps=self.ifc_import_settings.load_indexed_maps,
|
load_indexed_maps=self.ifc_import_settings.load_indexed_maps,
|
||||||
)
|
)
|
||||||
|
return tool.Loader.slice_layerset_mesh(element, mesh)
|
||||||
except:
|
except:
|
||||||
self.ifc_import_settings.logger.error("Could not create mesh for %s", element)
|
self.ifc_import_settings.logger.error("Could not create mesh for %s", element)
|
||||||
import traceback
|
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()
|
mesh["ios_material_ids"] = ifcopenshell.util.shape.get_faces_material_style_ids(geometry).tolist()
|
||||||
return mesh
|
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
|
@classmethod
|
||||||
def create_mesh_from_shape(
|
def create_mesh_from_shape(
|
||||||
cls,
|
cls,
|
||||||
|
|||||||
Reference in New Issue
Block a user