I know the architects around here will think this is dumb but I'm mostly working on existing buildings, and while there are standard wall thickness you want to adhere to when drafting a building, I've personaly witnessed them in all colors, shapes and forms. Even varying thickness along the main axis, which I've yet to learn how to do parametrically in IFC.
So I thought to myself, why not build a library of IfcWallType elements with different thickness I could dynamically load into my projects when I need them ?
I'm posting this to gauge if somehow I've missed something somewhere or if it may be useful to someone, somewhere. :)
Before diving into the code here's the resulting file contents.
and me casually browsing through the library (might be nice to have a search feature in there ?)
And me playing with my new toys
Woops, did I uncover a bug at the end there @Moult ? or is this intended ? Is there a way or a point to Mitre 3 wall segments at once ?
Also me playing with the resulting file in Revit
And finally the code. It's only using very high level functions and operators so naturally it is very slow. It took around 2 minutes to generate the ~500 IfcWallType elements. I'm sure it can be optimised by digging a bit more in the core of ifcopenshell, but that will be the task of another day :).
Cheers
import bpy
from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.material.data import Data as MaterialData
def run():
file = IfcStore.file
if file is None:
bpy.ops.bim.create_project()
file = IfcStore.file
for i in range(1, 501):
add_wall_type(i)
def add_wall_type(depth):
depth_str = str(depth).zfill(4)
bpy.ops.object.empty_add(type="PLAIN_AXES")
obj = bpy.context.active_object
obj.name = "Wall_" + depth_str
bpy.context.scene.BIMRootProperties.ifc_product = "IfcElementType"
bpy.context.scene.BIMRootProperties.ifc_class = "IfcWallType"
bpy.context.scene.BIMRootProperties.ifc_predefined_type = "STANDARD"
bpy.ops.bim.assign_class(ifc_class="IfcWallType", predefined_type="STANDARD")
bpy.ops.bim.add_material(obj="")
obj.BIMObjectMaterialProperties.material_type = "IfcMaterialLayerSet"
bpy.ops.bim.assign_material()
bpy.ops.bim.enable_editing_assigned_material()
obj.BIMObjectMaterialProperties.material_set_attributes[0].string_value = obj.name
if not MaterialData.is_loaded:
MaterialData.load(IfcStore.get_file())
oprops = obj.BIMObjectProperties
product_data = MaterialData.products[oprops.ifc_definition_id]
material_set_id = product_data["id"]
bpy.ops.bim.add_layer(layer_set=int(material_set_id))
material_set_data = MaterialData.layer_sets[material_set_id]
set_items = material_set_data["MaterialLayers"] or []
layer_0 = set_items[0]
bpy.ops.bim.enable_editing_material_set_item(material_set_item=int(layer_0))
obj.BIMObjectMaterialProperties.material_set_item_attributes[2].string_value = depth_str
obj.BIMObjectMaterialProperties.material_set_item_attributes[0].float_value = depth / 1000
bpy.ops.bim.disable_editing_material_set_item(obj=obj.name)
bpy.ops.bim.edit_material_set_item(material_set_item=int(layer_0))
bpy.ops.bim.disable_editing_assigned_material(obj=obj.name)
bpy.ops.bim.edit_assigned_material(material_set=material_set_id)
if __name__ == "__main__":
run()