Changing types of a dumb wall now auto updates their wall thicknesses

This commit is contained in:
Dion Moult
2021-05-30 21:02:03 +10:00
parent 730efcae49
commit 0b6f3113a7
6 changed files with 46 additions and 14 deletions
+13
View File
@@ -47,6 +47,19 @@ class IfcStore:
IfcStore.schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(IfcStore.file.schema) IfcStore.schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(IfcStore.file.schema)
return IfcStore.schema return IfcStore.schema
@staticmethod
def get_element(id_or_guid):
if isinstance(id_or_guid, int):
map_object = IfcStore.id_map
else:
map_object = IfcStore.guid_map
try:
obj = map_object[id_or_guid]
obj.type # In case the object has been deleted, this triggers an exception
except:
return
return obj
@staticmethod @staticmethod
def link_element(element, obj): def link_element(element, obj):
IfcStore.id_map[element.id()] = obj IfcStore.id_map[element.id()] = obj
@@ -200,11 +200,12 @@ class SwitchRepresentation(bpy.types.Operator):
if self.oprops.ifc_definition_id not in VoidData.products: if self.oprops.ifc_definition_id not in VoidData.products:
VoidData.load(IfcStore.get_file(), self.oprops.ifc_definition_id) VoidData.load(IfcStore.get_file(), self.oprops.ifc_definition_id)
for opening_id in VoidData.products[self.oprops.ifc_definition_id]: for opening_id in VoidData.products[self.oprops.ifc_definition_id]:
if opening_id in IfcStore.id_map: opening = IfcStore.get_element(opening_id)
opening = IfcStore.id_map[opening_id] if not opening:
modifier = self.element_obj.modifiers.new("IfcOpeningElement", "BOOLEAN") continue
modifier.operation = "DIFFERENCE" modifier = self.element_obj.modifiers.new("IfcOpeningElement", "BOOLEAN")
modifier.object = opening modifier.operation = "DIFFERENCE"
modifier.object = opening
else: else:
for modifier in self.element_obj.modifiers: for modifier in self.element_obj.modifiers:
if modifier.type == "BOOLEAN" and "IfcOpeningElement" in modifier.name: if modifier.type == "BOOLEAN" and "IfcOpeningElement" in modifier.name:
@@ -735,7 +735,6 @@ class DumbWallGenerator:
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.DumbWall"}) ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"Engine": "BlenderBIM.DumbWall"})
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
@@ -106,7 +106,7 @@ def calculate_dumb_quantities(usecase_path, ifc_file, **settings):
class DumbWallPlaner: class DumbWallPlaner:
def regenerate_dumb_wall_thicknesses(self, usecase_path, ifc_file, **settings): def regenerate_wall_thicknesses_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")
@@ -114,7 +114,7 @@ class DumbWallPlaner:
return return
delta_thickness = thickness - layer.LayerThickness delta_thickness = thickness - layer.LayerThickness
for layer_set in layer.ToMaterialLayerSet: for layer_set in layer.ToMaterialLayerSet:
total_thickness = sum([l.LayerThickness for l in layer_set.MaterialLayers]) * self.unit_scale total_thickness = sum([l.LayerThickness for l in layer_set.MaterialLayers])
if not total_thickness: if not total_thickness:
continue continue
for inverse in ifc_file.get_inverse(layer_set): for inverse in ifc_file.get_inverse(layer_set):
@@ -131,14 +131,27 @@ class DumbWallPlaner:
for element in rel.RelatedObjects: for element in rel.RelatedObjects:
self.regenerate_wall_thickness(element, delta_thickness) self.regenerate_wall_thickness(element, delta_thickness)
def regenerate_wall_thicknesses_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.y / self.unit_scale
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)
def regenerate_wall_thickness(self, element, delta_thickness): def regenerate_wall_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
try:
obj = IfcStore.id_map[element.id()] obj = IfcStore.get_element(element.id())
obj.name # In case the object has been deleted if not obj:
except:
return return
bm = bmesh.new() bm = bmesh.new()
@@ -206,6 +219,9 @@ class ActivateParametricEngine(bpy.types.Operator):
"geometry.add_representation", IfcStore.get_file(), calculate_dumb_quantities "geometry.add_representation", IfcStore.get_file(), calculate_dumb_quantities
) )
ifcopenshell.api.add_pre_listener( ifcopenshell.api.add_pre_listener(
"material.edit_layer", IfcStore.get_file(), DumbWallPlaner().regenerate_dumb_wall_thicknesses "material.edit_layer", IfcStore.get_file(), DumbWallPlaner().regenerate_wall_thicknesses_from_layer
)
ifcopenshell.api.add_pre_listener(
"type.assign_type", IfcStore.get_file(), DumbWallPlaner().regenerate_wall_thicknesses_from_type
) )
return {"FINISHED"} return {"FINISHED"}
@@ -38,7 +38,7 @@ class AssignContainer(bpy.types.Operator):
aggregate_collection = bpy.data.collections.get(related_element.name) aggregate_collection = bpy.data.collections.get(related_element.name)
relating_structure_obj = IfcStore.id_map.get(relating_structure) relating_structure_obj = IfcStore.get_element(relating_structure)
relating_collection = None relating_collection = None
if relating_structure_obj: if relating_structure_obj:
relating_collection = bpy.data.collections.get(relating_structure_obj.name) relating_collection = bpy.data.collections.get(relating_structure_obj.name)
@@ -5,6 +5,7 @@ import ifcopenshell.api
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.type.data import Data from ifcopenshell.api.type.data import Data
from ifcopenshell.api.geometry.data import Data as GeometryData from ifcopenshell.api.geometry.data import Data as GeometryData
from ifcopenshell.api.material.data import Data as MaterialData
class AssignType(bpy.types.Operator): class AssignType(bpy.types.Operator):
@@ -31,6 +32,7 @@ class AssignType(bpy.types.Operator):
) )
Data.load(IfcStore.get_file(), oprops.ifc_definition_id) Data.load(IfcStore.get_file(), oprops.ifc_definition_id)
GeometryData.load(IfcStore.get_file(), oprops.ifc_definition_id) GeometryData.load(IfcStore.get_file(), oprops.ifc_definition_id)
MaterialData.load(IfcStore.get_file(), oprops.ifc_definition_id)
representation_ids = GeometryData.products[oprops.ifc_definition_id] representation_ids = GeometryData.products[oprops.ifc_definition_id]
if not representation_ids: if not representation_ids:
pass # TODO: clear geometry? Make void? Make none type? pass # TODO: clear geometry? Make void? Make none type?
@@ -44,6 +46,7 @@ class AssignType(bpy.types.Operator):
bpy.ops.bim.switch_representation(obj=related_object.name, ifc_definition_id=representation_id) bpy.ops.bim.switch_representation(obj=related_object.name, ifc_definition_id=representation_id)
bpy.ops.bim.disable_editing_type(obj=related_object.name) bpy.ops.bim.disable_editing_type(obj=related_object.name)
MaterialData.load(self.file)
return {"FINISHED"} return {"FINISHED"}