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)
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
def link_element(element, 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:
VoidData.load(IfcStore.get_file(), 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.id_map[opening_id]
modifier = self.element_obj.modifiers.new("IfcOpeningElement", "BOOLEAN")
modifier.operation = "DIFFERENCE"
modifier.object = opening
opening = IfcStore.get_element(opening_id)
if not opening:
continue
modifier = self.element_obj.modifiers.new("IfcOpeningElement", "BOOLEAN")
modifier.operation = "DIFFERENCE"
modifier.object = opening
else:
for modifier in self.element_obj.modifiers:
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)
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("material.assign_material", self.file, product=element, type="IfcMaterialLayerSetUsage")
MaterialData.load(self.file)
obj.select_set(True)
return obj
@@ -106,7 +106,7 @@ def calculate_dumb_quantities(usecase_path, ifc_file, **settings):
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)
layer = settings["layer"]
thickness = settings["attributes"].get("LayerThickness")
@@ -114,7 +114,7 @@ class DumbWallPlaner:
return
delta_thickness = thickness - layer.LayerThickness
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:
continue
for inverse in ifc_file.get_inverse(layer_set):
@@ -131,14 +131,27 @@ class DumbWallPlaner:
for element in rel.RelatedObjects:
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):
parametric = ifcopenshell.util.element.get_psets(element).get("EPset_Parametric")
if not parametric or parametric["Engine"] != "BlenderBIM.DumbWall":
return
try:
obj = IfcStore.id_map[element.id()]
obj.name # In case the object has been deleted
except:
obj = IfcStore.get_element(element.id())
if not obj:
return
bm = bmesh.new()
@@ -206,6 +219,9 @@ class ActivateParametricEngine(bpy.types.Operator):
"geometry.add_representation", IfcStore.get_file(), calculate_dumb_quantities
)
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"}
@@ -38,7 +38,7 @@ class AssignContainer(bpy.types.Operator):
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
if relating_structure_obj:
relating_collection = bpy.data.collections.get(relating_structure_obj.name)
@@ -5,6 +5,7 @@ import ifcopenshell.api
from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.type.data import Data
from ifcopenshell.api.geometry.data import Data as GeometryData
from ifcopenshell.api.material.data import Data as MaterialData
class AssignType(bpy.types.Operator):
@@ -31,6 +32,7 @@ class AssignType(bpy.types.Operator):
)
Data.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]
if not representation_ids:
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.disable_editing_type(obj=related_object.name)
MaterialData.load(self.file)
return {"FINISHED"}