From f5220fba56761a7dad71e9eb3d1c372b9fdf885f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Perdig=C3=A3o?= Date: Mon, 15 Sep 2025 17:01:57 -0300 Subject: [PATCH] Add custom offset to walls `IfcMaterialLayerSetUsage` --- src/bonsai/bonsai/bim/module/material/prop.py | 3 +- src/bonsai/bonsai/bim/module/model/slab.py | 38 +++++------------- src/bonsai/bonsai/tool/model.py | 40 +++++++++++++++++++ 3 files changed, 52 insertions(+), 29 deletions(-) diff --git a/src/bonsai/bonsai/bim/module/material/prop.py b/src/bonsai/bonsai/bim/module/material/prop.py index 558497a28a..2fbd8d2847 100644 --- a/src/bonsai/bonsai/bim/module/material/prop.py +++ b/src/bonsai/bonsai/bim/module/material/prop.py @@ -241,4 +241,5 @@ class BIMObjectMaterialProperties(PropertyGroup): parameterized_profile_classes: str use_custom_offset: bool custom_offset: float - custom_offset_reference: str + custom_slab_reference: str + custom_wall_reference: str diff --git a/src/bonsai/bonsai/bim/module/model/slab.py b/src/bonsai/bonsai/bim/module/model/slab.py index bac9ff90fa..fdb8540e98 100644 --- a/src/bonsai/bonsai/bim/module/model/slab.py +++ b/src/bonsai/bonsai/bim/module/model/slab.py @@ -292,22 +292,8 @@ class DumbSlabPlaner: if thickness == 0: return - layer_offset = layer_params["offset"] - self.props = tool.Material.get_object_material_props(obj) - if self.props.use_custom_offset: - custom_offset_reference = self.props.custom_offset_reference - custom_offset = self.props.custom_offset - direction_sense = layer_params["direction_sense"] - if (direction_sense == "POSITIVE" and custom_offset_reference == "TOP"): - layer_offset = custom_offset - thickness * self.unit_scale - if direction_sense == "POSITIVE" and custom_offset_reference == "MIDDLE": - layer_offset = custom_offset - (thickness / 2) * self.unit_scale - if (direction_sense == "POSITIVE" and custom_offset_reference == "BOTTOM") or (direction_sense == "NEGATIVE" and custom_offset_reference == "TOP"): - layer_offset = custom_offset - if direction_sense == "NEGATIVE" and custom_offset_reference == "MIDDLE": - layer_offset = custom_offset + (thickness / 2) * self.unit_scale - if (direction_sense == "NEGATIVE" and custom_offset_reference == "BOTTOM"): - layer_offset = custom_offset + thickness * self.unit_scale + custom_offset = tool.Model.get_material_layer_custom_offset(element, obj) + layer_offset = (custom_offset * self.unit_scale) if custom_offset is not None else layer_params["offset"] representation = ifcopenshell.util.representation.get_representation(element, "Model", "Body", "MODEL_VIEW") if representation: @@ -348,19 +334,15 @@ class DumbSlabPlaner: extrusion.Depth = perpendicular_depth ifc_position = extrusion.Position - if perpendicular_offset == 0.0: - # Clean up possible previous offset. - tool.Model.reset_extrusion_position(extrusion) + position = offset_direction * perpendicular_offset + material = ifcopenshell.util.element.get_material(element) + if material: + if material.is_a("IfcMaterialLayerSetUsage"): + material.OffsetFromReferenceLine = position.z + if ifc_position: + ifc_position.Location.Coordinates = position else: - position = offset_direction * perpendicular_offset - material = ifcopenshell.util.element.get_material(element) - if material: - if material.is_a("IfcMaterialLayerSetUsage"): - material.OffsetFromReferenceLine = position.z - if ifc_position: - ifc_position.Location.Coordinates = position - else: - tool.Model.add_extrusion_position(extrusion, position) + tool.Model.add_extrusion_position(extrusion, position) else: props = tool.Model.get_model_props() diff --git a/src/bonsai/bonsai/tool/model.py b/src/bonsai/bonsai/tool/model.py index 0f29f2d733..9322e23f0d 100644 --- a/src/bonsai/bonsai/tool/model.py +++ b/src/bonsai/bonsai/tool/model.py @@ -653,6 +653,40 @@ class Model(bonsai.core.tool.Model): direction_sense=direction_sense, ) + @classmethod + def get_material_layer_custom_offset(cls, element: ifcopenshell.entity_instance, obj) -> MaterialLayerParameters: + unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get()) + layer_params = tool.Model.get_material_layer_parameters(element) + layer_offset = layer_params["offset"] + thickness = layer_params["thickness"] / unit_scale + props = tool.Material.get_object_material_props(obj) + if props.use_custom_offset: + if tool.Model.get_usage_type(element) == "LAYER2": + custom_offset_reference = props.custom_wall_reference + elif tool.Model.get_usage_type(element) == "LAYER3": + custom_offset_reference = props.custom_slab_reference + else: + return None + + custom_offset = props.custom_offset + direction_sense = layer_params["direction_sense"] + if direction_sense == "POSITIVE" and custom_offset_reference in {"INTERIOR", "TOP"}: + layer_offset = custom_offset - thickness * unit_scale + if direction_sense == "POSITIVE" and custom_offset_reference in {"CENTER", "MIDDLE"}: + layer_offset = custom_offset - (thickness / 2) * unit_scale + if (direction_sense == "POSITIVE" and custom_offset_reference in {"EXTERIOR", "BOTTOM"}) or ( + direction_sense == "NEGATIVE" and custom_offset_reference in {"EXTERIOR", "TOP"} + ): + layer_offset = custom_offset + if direction_sense == "NEGATIVE" and custom_offset_reference in {"CENTER", "MIDDLE"}: + layer_offset = custom_offset + (thickness / 2) * unit_scale + if direction_sense == "NEGATIVE" and custom_offset_reference in {"INTERIOR", "BOTTOM"}: + layer_offset = custom_offset + thickness * unit_scale + + return layer_offset / unit_scale + + return None + @classmethod def get_booleans( cls, @@ -2466,4 +2500,10 @@ class Model(bonsai.core.tool.Model): queue.add((rel.RelatingElement, obj)) for element, wall in queue: if tool.Model.get_usage_type(element) == "LAYER2" and wall: + # Use layer custom offset + custom_offset = tool.Model.get_material_layer_custom_offset(element, wall) + material = ifcopenshell.util.element.get_material(element) + if material.is_a("IfcMaterialLayerSetUsage") and custom_offset is not None: + material.OffsetFromReferenceLine = custom_offset + cls.recreate_wall(element, wall)