mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-17 10:59:17 +00:00
Changing types of a dumb wall now auto updates their wall thicknesses
This commit is contained in:
@@ -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"}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user