From 6ff4c95ac7444c5b4a177ef3c14336c796308f25 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Mon, 31 May 2021 15:27:22 +1000 Subject: [PATCH] Dumb slabs now auto update thickness based on layer thickness and type changes. --- .../blenderbim/bim/module/model/__init__.py | 1 + .../blenderbim/bim/module/model/handler.py | 22 +++---- .../blenderbim/bim/module/model/slab.py | 60 ++++++++++++++++++- .../blenderbim/bim/module/model/wall.py | 16 ++--- .../api/material/unassign_material.py | 2 +- 5 files changed, 77 insertions(+), 24 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/model/__init__.py b/src/blenderbim/blenderbim/bim/module/model/__init__.py index 2a491cf399..7c99e0903a 100644 --- a/src/blenderbim/blenderbim/bim/module/model/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/model/__init__.py @@ -54,6 +54,7 @@ def register(): def unregister(): bpy.utils.unregister_tool(workspace.WallTool) del bpy.types.Scene.BIMModelProperties + bpy.app.handlers.load_post.remove(handler.load_post) bpy.types.VIEW3D_MT_mesh_add.remove(grid.add_object_button) bpy.types.VIEW3D_MT_mesh_add.remove(stair.add_object_button) bpy.types.VIEW3D_MT_mesh_add.remove(door.add_object_button) diff --git a/src/blenderbim/blenderbim/bim/module/model/handler.py b/src/blenderbim/blenderbim/bim/module/model/handler.py index 9c50006edb..b50aa35bf4 100644 --- a/src/blenderbim/blenderbim/bim/module/model/handler.py +++ b/src/blenderbim/blenderbim/bim/module/model/handler.py @@ -2,21 +2,15 @@ import bpy import ifcopenshell import ifcopenshell.api from blenderbim.bim.module.model import product, wall, slab -from blenderbim.bim.ifc import IfcStore from bpy.app.handlers import persistent + @persistent def load_post(*args): - ifcopenshell.api.add_post_listener("geometry.add_representation", IfcStore.get_file(), product.generate_box) - ifcopenshell.api.add_post_listener( - "geometry.add_representation", IfcStore.get_file(), wall.generate_dumb_wall_axis - ) - ifcopenshell.api.add_post_listener( - "geometry.add_representation", IfcStore.get_file(), wall.calculate_dumb_quantities - ) - ifcopenshell.api.add_pre_listener( - "material.edit_layer", IfcStore.get_file(), wall.DumbWallPlaner().regenerate_wall_thicknesses_from_layer - ) - ifcopenshell.api.add_pre_listener( - "type.assign_type", IfcStore.get_file(), wall.DumbWallPlaner().regenerate_wall_thicknesses_from_type - ) + ifcopenshell.api.add_post_listener("geometry.add_representation", None, product.generate_box) + ifcopenshell.api.add_post_listener("geometry.add_representation", None, wall.generate_axis) + ifcopenshell.api.add_post_listener("geometry.add_representation", None, wall.calculate_quantities) + ifcopenshell.api.add_pre_listener("material.edit_layer", None, wall.DumbWallPlaner().regenerate_from_layer) + ifcopenshell.api.add_pre_listener("type.assign_type", None, wall.DumbWallPlaner().regenerate_from_type) + ifcopenshell.api.add_pre_listener("material.edit_layer", None, slab.DumbSlabPlaner().regenerate_from_layer) + ifcopenshell.api.add_pre_listener("type.assign_type", None, slab.DumbSlabPlaner().regenerate_from_type) diff --git a/src/blenderbim/blenderbim/bim/module/model/slab.py b/src/blenderbim/blenderbim/bim/module/model/slab.py index c04b268119..2f70250af4 100644 --- a/src/blenderbim/blenderbim/bim/module/model/slab.py +++ b/src/blenderbim/blenderbim/bim/module/model/slab.py @@ -59,6 +59,7 @@ class DumbSlabGenerator: modifier.offset = 1 modifier.thickness = self.depth obj.name = "Slab" + obj.location = self.location if self.collection_obj and self.collection_obj.BIMObjectProperties.ifc_definition_id: obj.location[2] = self.collection_obj.location[2] - self.depth else: @@ -69,7 +70,64 @@ class DumbSlabGenerator: element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id) pset = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name="EPset_Parametric") ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"Engine": "BlenderBIM.DumbSlab"}) - ifcopenshell.api.run("material.assign_material", self.file, product=element, type="IfcMaterialLayerSetUsage") MaterialData.load(self.file) obj.select_set(True) return obj + + +class DumbSlabPlaner: + def regenerate_from_layer(self, usecase_path, ifc_file, **settings): + self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file) + layer = settings["layer"] + thickness = settings["attributes"].get("LayerThickness") + if thickness is None or layer.LayerThickness == thickness: + return + delta_thickness = thickness - layer.LayerThickness + for layer_set in layer.ToMaterialLayerSet: + total_thickness = sum([l.LayerThickness for l in layer_set.MaterialLayers]) + if not total_thickness: + continue + for inverse in ifc_file.get_inverse(layer_set): + if not inverse.is_a("IfcMaterialLayerSetUsage"): + continue + if ifc_file.schema == "IFC2X3": + for rel in ifc_file.get_inverse(inverse): + if not rel.is_a("IfcRelAssociatesMaterial"): + continue + for element in rel.RelatedObjects: + self.change_thickness(element, delta_thickness) + else: + for rel in inverse.AssociatedTo: + for element in rel.RelatedObjects: + self.change_thickness(element, delta_thickness) + + def regenerate_from_type(self, usecase_path, ifc_file, **settings): + self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file) + new_material = ifcopenshell.util.element.get_material(settings["relating_type"]) + if not new_material.is_a("IfcMaterialLayerSet"): + return + obj = IfcStore.get_element(settings["related_object"].id()) + if not obj: + return + current_thickness = obj.dimensions.z / self.unit_scale + new_thickness = sum([l.LayerThickness for l in new_material.MaterialLayers]) + if current_thickness == new_thickness: + return + self.change_thickness(settings["related_object"], new_thickness - current_thickness) + + def change_thickness(self, element, delta_thickness): + parametric = ifcopenshell.util.element.get_psets(element).get("EPset_Parametric") + if not parametric or parametric["Engine"] != "BlenderBIM.DumbSlab": + return + + obj = IfcStore.get_element(element.id()) + if not obj: + return + + modifier = [m for m in obj.modifiers if m.type == "SOLIDIFY"] + if modifier: + modifier = modifier[0] + else: + pass + modifier.thickness += delta_thickness * self.unit_scale + obj.location[2] -= delta_thickness * self.unit_scale diff --git a/src/blenderbim/blenderbim/bim/module/model/wall.py b/src/blenderbim/blenderbim/bim/module/model/wall.py index cd04c211c2..a14b333970 100644 --- a/src/blenderbim/blenderbim/bim/module/model/wall.py +++ b/src/blenderbim/blenderbim/bim/module/model/wall.py @@ -687,7 +687,7 @@ class DumbWallGenerator: -def generate_dumb_wall_axis(usecase_path, ifc_file, **settings): +def generate_axis(usecase_path, ifc_file, **settings): axis_context = ifcopenshell.util.representation.get_context(ifc_file, "Model", "Axis", "GRAPH_VIEW") if not axis_context: return @@ -722,7 +722,7 @@ def generate_dumb_wall_axis(usecase_path, ifc_file, **settings): bpy.data.meshes.remove(mesh) -def calculate_dumb_quantities(usecase_path, ifc_file, **settings): +def calculate_quantities(usecase_path, ifc_file, **settings): unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file) obj = settings["blender_object"] product = ifc_file.by_id(obj.BIMObjectProperties.ifc_definition_id) @@ -758,7 +758,7 @@ def calculate_dumb_quantities(usecase_path, ifc_file, **settings): class DumbWallPlaner: - def regenerate_wall_thicknesses_from_layer(self, usecase_path, ifc_file, **settings): + def regenerate_from_layer(self, usecase_path, ifc_file, **settings): self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file) layer = settings["layer"] thickness = settings["attributes"].get("LayerThickness") @@ -777,13 +777,13 @@ class DumbWallPlaner: if not rel.is_a("IfcRelAssociatesMaterial"): continue for element in rel.RelatedObjects: - self.regenerate_wall_thickness(element, delta_thickness) + self.change_thickness(element, delta_thickness) else: for rel in inverse.AssociatedTo: for element in rel.RelatedObjects: - self.regenerate_wall_thickness(element, delta_thickness) + self.change_thickness(element, delta_thickness) - def regenerate_wall_thicknesses_from_type(self, usecase_path, ifc_file, **settings): + def regenerate_from_type(self, usecase_path, ifc_file, **settings): self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file) new_material = ifcopenshell.util.element.get_material(settings["relating_type"]) if not new_material.is_a("IfcMaterialLayerSet"): @@ -795,9 +795,9 @@ class DumbWallPlaner: new_thickness = sum([l.LayerThickness for l in new_material.MaterialLayers]) if current_thickness == new_thickness: return - self.regenerate_wall_thickness(settings["related_object"], new_thickness - current_thickness) + self.change_thickness(settings["related_object"], new_thickness - current_thickness) - def regenerate_wall_thickness(self, element, delta_thickness): + def change_thickness(self, element, delta_thickness): parametric = ifcopenshell.util.element.get_psets(element).get("EPset_Parametric") if not parametric or parametric["Engine"] != "BlenderBIM.DumbWall": return diff --git a/src/ifcopenshell-python/ifcopenshell/api/material/unassign_material.py b/src/ifcopenshell-python/ifcopenshell/api/material/unassign_material.py index 5c16e48a90..09c625a900 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/material/unassign_material.py +++ b/src/ifcopenshell-python/ifcopenshell/api/material/unassign_material.py @@ -20,4 +20,4 @@ class Usecase: continue related_objects = set(rel.RelatedObjects) related_objects.remove(self.settings["product"]) - rel.RelatedObjects = list(related_object) + rel.RelatedObjects = list(related_objects)