mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-30 12:09:51 +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)
|
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"}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user