Dumb slabs now auto update thickness based on layer thickness and type changes.

This commit is contained in:
Dion Moult
2021-05-31 15:27:22 +10:00
parent 0b6af5f848
commit 6ff4c95ac7
5 changed files with 77 additions and 24 deletions
@@ -54,6 +54,7 @@ def register():
def unregister(): def unregister():
bpy.utils.unregister_tool(workspace.WallTool) bpy.utils.unregister_tool(workspace.WallTool)
del bpy.types.Scene.BIMModelProperties 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(grid.add_object_button)
bpy.types.VIEW3D_MT_mesh_add.remove(stair.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) bpy.types.VIEW3D_MT_mesh_add.remove(door.add_object_button)
@@ -2,21 +2,15 @@ import bpy
import ifcopenshell import ifcopenshell
import ifcopenshell.api import ifcopenshell.api
from blenderbim.bim.module.model import product, wall, slab from blenderbim.bim.module.model import product, wall, slab
from blenderbim.bim.ifc import IfcStore
from bpy.app.handlers import persistent from bpy.app.handlers import persistent
@persistent @persistent
def load_post(*args): 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", None, product.generate_box)
ifcopenshell.api.add_post_listener( ifcopenshell.api.add_post_listener("geometry.add_representation", None, wall.generate_axis)
"geometry.add_representation", IfcStore.get_file(), wall.generate_dumb_wall_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_post_listener( ifcopenshell.api.add_pre_listener("type.assign_type", None, wall.DumbWallPlaner().regenerate_from_type)
"geometry.add_representation", IfcStore.get_file(), wall.calculate_dumb_quantities 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)
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
)
@@ -59,6 +59,7 @@ class DumbSlabGenerator:
modifier.offset = 1 modifier.offset = 1
modifier.thickness = self.depth modifier.thickness = self.depth
obj.name = "Slab" obj.name = "Slab"
obj.location = self.location
if self.collection_obj and self.collection_obj.BIMObjectProperties.ifc_definition_id: if self.collection_obj and self.collection_obj.BIMObjectProperties.ifc_definition_id:
obj.location[2] = self.collection_obj.location[2] - self.depth obj.location[2] = self.collection_obj.location[2] - self.depth
else: else:
@@ -69,7 +70,64 @@ class DumbSlabGenerator:
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id) element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
pset = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name="EPset_Parametric") 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("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) MaterialData.load(self.file)
obj.select_set(True) obj.select_set(True)
return obj 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
@@ -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") axis_context = ifcopenshell.util.representation.get_context(ifc_file, "Model", "Axis", "GRAPH_VIEW")
if not axis_context: if not axis_context:
return return
@@ -722,7 +722,7 @@ def generate_dumb_wall_axis(usecase_path, ifc_file, **settings):
bpy.data.meshes.remove(mesh) 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) unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file)
obj = settings["blender_object"] obj = settings["blender_object"]
product = ifc_file.by_id(obj.BIMObjectProperties.ifc_definition_id) 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: 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) self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file)
layer = settings["layer"] layer = settings["layer"]
thickness = settings["attributes"].get("LayerThickness") thickness = settings["attributes"].get("LayerThickness")
@@ -777,13 +777,13 @@ class DumbWallPlaner:
if not rel.is_a("IfcRelAssociatesMaterial"): if not rel.is_a("IfcRelAssociatesMaterial"):
continue continue
for element in rel.RelatedObjects: for element in rel.RelatedObjects:
self.regenerate_wall_thickness(element, delta_thickness) self.change_thickness(element, delta_thickness)
else: else:
for rel in inverse.AssociatedTo: for rel in inverse.AssociatedTo:
for element in rel.RelatedObjects: 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) self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file)
new_material = ifcopenshell.util.element.get_material(settings["relating_type"]) new_material = ifcopenshell.util.element.get_material(settings["relating_type"])
if not new_material.is_a("IfcMaterialLayerSet"): if not new_material.is_a("IfcMaterialLayerSet"):
@@ -795,9 +795,9 @@ class DumbWallPlaner:
new_thickness = sum([l.LayerThickness for l in new_material.MaterialLayers]) new_thickness = sum([l.LayerThickness for l in new_material.MaterialLayers])
if current_thickness == new_thickness: if current_thickness == new_thickness:
return 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") parametric = ifcopenshell.util.element.get_psets(element).get("EPset_Parametric")
if not parametric or parametric["Engine"] != "BlenderBIM.DumbWall": if not parametric or parametric["Engine"] != "BlenderBIM.DumbWall":
return return
@@ -20,4 +20,4 @@ class Usecase:
continue continue
related_objects = set(rel.RelatedObjects) related_objects = set(rel.RelatedObjects)
related_objects.remove(self.settings["product"]) related_objects.remove(self.settings["product"])
rel.RelatedObjects = list(related_object) rel.RelatedObjects = list(related_objects)