From e1cfa68dcb9efea5be504b208f1359218a2007f2 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Sun, 12 Jan 2020 19:01:35 +1100 Subject: [PATCH] Allow export of material properties. Related to #756. --- .../material/beam/Pset_MaterialCommon.csv | 1 + .../material/beam/Pset_MaterialMechanical.csv | 2 ++ src/ifcblenderexport/blenderbim/export_ifc.py | 29 +++++++++++++++ src/ifcblenderexport/blenderbim/operator.py | 35 +++++++++++++++---- src/ifcblenderexport/blenderbim/prop.py | 12 +++++++ src/ifcblenderexport/blenderbim/ui.py | 17 +++++++++ 6 files changed, 90 insertions(+), 6 deletions(-) create mode 100644 src/ifcblenderexport/blenderbim/data/material/beam/Pset_MaterialCommon.csv create mode 100644 src/ifcblenderexport/blenderbim/data/material/beam/Pset_MaterialMechanical.csv diff --git a/src/ifcblenderexport/blenderbim/data/material/beam/Pset_MaterialCommon.csv b/src/ifcblenderexport/blenderbim/data/material/beam/Pset_MaterialCommon.csv new file mode 100644 index 0000000000..8c06b9362c --- /dev/null +++ b/src/ifcblenderexport/blenderbim/data/material/beam/Pset_MaterialCommon.csv @@ -0,0 +1 @@ +MassDensity,7.8 diff --git a/src/ifcblenderexport/blenderbim/data/material/beam/Pset_MaterialMechanical.csv b/src/ifcblenderexport/blenderbim/data/material/beam/Pset_MaterialMechanical.csv new file mode 100644 index 0000000000..6dcea4cf5b --- /dev/null +++ b/src/ifcblenderexport/blenderbim/data/material/beam/Pset_MaterialMechanical.csv @@ -0,0 +1,2 @@ +YoungModulus,210000000 +PoissonRatio,0.2 diff --git a/src/ifcblenderexport/blenderbim/export_ifc.py b/src/ifcblenderexport/blenderbim/export_ifc.py index 26c4425e80..a5714204c6 100644 --- a/src/ifcblenderexport/blenderbim/export_ifc.py +++ b/src/ifcblenderexport/blenderbim/export_ifc.py @@ -149,6 +149,7 @@ class IfcParser(): self.organisations = self.get_organisations() self.convert_selected_objects_into_products(bpy.context.selected_objects) self.psets = self.get_psets() + self.material_psets = self.get_material_psets() self.documents = self.get_documents() self.classifications = self.get_classifications() self.classification_references = self.get_classification_references() @@ -505,6 +506,23 @@ class IfcParser(): } return psets + def get_material_psets(self): + psets = {} + for filename in Path(self.data_dir + 'material/').glob('**/*.csv'): + with open(filename, 'r') as f: + description = filename.parts[-2] + name = filename.stem + if description not in psets: + psets[description] = {} + psets[description][name] = { + 'ifc': None, + 'raw': {x[0]: x[1] for x in list(csv.reader(f))}, + 'attributes': { + 'Name': name, + 'Description': description} + } + return psets + def get_door_attributes(self): return self.get_predefined_attributes('door') @@ -1176,6 +1194,16 @@ class IfcExporter(): }) pset['ifc'] = self.file.create_entity('IfcPropertySet', **pset['attributes']) + def create_material_psets(self, material): + for pset_dir in material['raw'].BIMMaterialProperties.psets: + for name, properties in self.ifc_parser.material_psets[pset_dir.name].items(): + self.file.create_entity('IfcMaterialProperties', **{ + 'Name': name, + 'Description': pset_dir.name, + 'Properties': self.create_pset_properties(properties), + 'Material': material['ifc'] + }) + def create_pset_properties(self, pset): if pset['attributes']['Name'] in self.ifc_schema.psets: return self.create_templated_pset_properties(pset) @@ -1416,6 +1444,7 @@ class IfcExporter(): styled_representation = self.file.createIfcStyledRepresentation( self.ifc_rep_context['Model']['Body']['MODEL_VIEW']['ifc'], None, None, [styled_item]) material['ifc'] = self.file.createIfcMaterial(material['raw'].name, None, None) + self.create_material_psets(material) self.file.createIfcMaterialDefinitionRepresentation( material['raw'].name, None, [styled_representation], material['ifc']) if material['is_material_layer_set']: diff --git a/src/ifcblenderexport/blenderbim/operator.py b/src/ifcblenderexport/blenderbim/operator.py index 7ead6c980f..95ebff65f7 100644 --- a/src/ifcblenderexport/blenderbim/operator.py +++ b/src/ifcblenderexport/blenderbim/operator.py @@ -283,11 +283,11 @@ class AssignPset(bpy.types.Operator): for object in bpy.context.selected_objects: index = object.BIMObjectProperties.psets.find(bpy.context.scene.BIMProperties.pset_name) if index >= 0: - global_id = object.BIMObjectProperties.psets[index] + pset = object.BIMObjectProperties.psets[index] else: - global_id = object.BIMObjectProperties.psets.add() - global_id.name = bpy.context.scene.BIMProperties.pset_name - global_id.file = bpy.context.scene.BIMProperties.pset_file + pset = object.BIMObjectProperties.psets.add() + pset.name = bpy.context.scene.BIMProperties.pset_name + pset.file = bpy.context.scene.BIMProperties.pset_file return {'FINISHED'} class UnassignPset(bpy.types.Operator): @@ -305,11 +305,13 @@ class AddPset(bpy.types.Operator): bl_idname = 'bim.add_pset' bl_label = 'Add Pset' - # This is a temporary measure until we get a better UI def execute(self, context): - bpy.context.active_object.BIMObjectProperties.psets.add() + pset = bpy.context.active_object.BIMObjectProperties.psets.add() + pset.name = bpy.context.scene.BIMProperties.pset_name + pset.file = bpy.context.scene.BIMProperties.pset_file return {'FINISHED'} + class RemovePset(bpy.types.Operator): bl_idname = 'bim.remove_pset' bl_label = 'Remove Pset' @@ -319,6 +321,27 @@ class RemovePset(bpy.types.Operator): bpy.context.active_object.BIMObjectProperties.psets.remove(self.pset_index) return {'FINISHED'} + +class AddMaterialPset(bpy.types.Operator): + bl_idname = 'bim.add_material_pset' + bl_label = 'Add Material Pset' + + def execute(self, context): + pset = bpy.context.active_object.active_material.BIMMaterialProperties.psets.add() + pset.name = bpy.context.active_object.active_material.BIMMaterialProperties.available_material_psets + return {'FINISHED'} + + +class RemoveMaterialPset(bpy.types.Operator): + bl_idname = 'bim.remove_material_pset' + bl_label = 'Remove Pset' + pset_index: bpy.props.IntProperty() + + def execute(self, context): + bpy.context.active_object.active_material.BIMMaterialProperties.psets.remove(self.pset_index) + return {'FINISHED'} + + class AddDocument(bpy.types.Operator): bl_idname = 'bim.add_document' bl_label = 'Add Document' diff --git a/src/ifcblenderexport/blenderbim/prop.py b/src/ifcblenderexport/blenderbim/prop.py index 29553fcbe9..20ec723f36 100644 --- a/src/ifcblenderexport/blenderbim/prop.py +++ b/src/ifcblenderexport/blenderbim/prop.py @@ -27,6 +27,7 @@ ifc_schema = IfcSchema() diagram_scales_enum = [] classes_enum = [] types_enum = [] +availablematerialpsets_enum = [] psetnames_enum = [] psetfiles_enum = [] classification_enum = [] @@ -115,6 +116,15 @@ def getOrganisations(self, context): return organisations_enum +def getAvailableMaterialPsets(self, context): + global availablematerialpsets_enum + if len(availablematerialpsets_enum) < 1: + availablematerialpsets_enum.clear() + files = os.listdir(os.path.join(context.scene.BIMProperties.data_dir, 'material')) + availablematerialpsets_enum.extend([(f, f, '') for f in files]) + return availablematerialpsets_enum + + def getPsetNames(self, context): global psetnames_enum if len(psetnames_enum) < 1: @@ -347,6 +357,8 @@ class BIMMaterialProperties(PropertyGroup): location: StringProperty(name="Location") identification: StringProperty(name="Identification") name: StringProperty(name="Name") + available_material_psets: EnumProperty(items=getAvailableMaterialPsets, name="Material Pset") + psets: CollectionProperty(name="Psets", type=Pset) class SweptSolid(PropertyGroup): diff --git a/src/ifcblenderexport/blenderbim/ui.py b/src/ifcblenderexport/blenderbim/ui.py index 08ba7948b5..bc585f6483 100644 --- a/src/ifcblenderexport/blenderbim/ui.py +++ b/src/ifcblenderexport/blenderbim/ui.py @@ -39,6 +39,10 @@ class BIM_PT_object(Panel): layout.label(text="Property Sets:") row = layout.row() + row.prop(context.scene.BIMProperties, "pset_name") + row = layout.row() + row.prop(context.scene.BIMProperties, "pset_file") + row = layout.row() row.operator('bim.add_pset') for index, pset in enumerate(props.psets): @@ -157,6 +161,19 @@ class BIM_PT_material(Panel): row = layout.row() row.operator('bim.fetch_external_material') + layout.label(text="Property Sets:") + row = layout.row(align=True) + row.prop(props, 'available_material_psets', text='') + row.operator('bim.add_material_pset') + + for index, pset in enumerate(props.psets): + row = layout.row(align=True) + row.prop(pset, 'name', text='') + row.operator('bim.remove_material_pset', icon='X', text='').pset_index = index + + row = layout.row() + row.prop(props, 'psets', text='') + class BIM_PT_gis(Panel): bl_label = 'IFC Georeferencing'