diff --git a/src/ifcblenderexport/blenderbim/bim/module/attribute/data.py b/src/ifcblenderexport/blenderbim/bim/module/attribute/data.py index be39c428ef..2458759c89 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/attribute/data.py +++ b/src/ifcblenderexport/blenderbim/bim/module/attribute/data.py @@ -1,4 +1,5 @@ import ifcopenshell +import ifcopenshell.util.attribute from blenderbim.bim.ifc import IfcStore @@ -18,37 +19,25 @@ class Data: cls.products[product_id] = [] declaration = IfcStore.get_schema().declaration_by_name(product.is_a()) for attribute in declaration.all_attributes(): - data_type = str(attribute.type_of_attribute()) + data_type = ifcopenshell.util.attribute.get_primitive_type(attribute) value = getattr(product, attribute.name()) list_type = None enum_items = () - if "" in data_type: - list_type = "string" - elif "" in data_type: - list_type = "float" - elif "" in data_type: - list_type = "integer" - data_type = "list" - value = None if value is None else str(value) - elif "" in data_type: - data_type = "string" - value = None if value is None else str(value) - elif "" in data_type: - data_type = "float" + elif data_type == "float": value = None if value is None else float(value) - elif "" in data_type: - data_type = "integer" + elif data_type == "integer": value = None if value is None else int(value) - elif "" in data_type: + new.data_type = data_type + if data_type == "string": new.string_value = "" if new.is_null else data[attribute.name()] - new.data_type = "string" - elif "" in data_type: + new.data_type = data_type + if data_type == "string": new.string_value = "" if new.is_null else data[attribute.name()] - new.data_type = "string" - elif "" in data_type: + new.data_type = data_type + if data_type == "string": new.string_value = "" if new.is_null else Data.map_conversion[attribute.name()] - new.data_type = "string" - elif "" in data_type: + elif data_type == "float": new.float_value = 0.0 if new.is_null else Data.map_conversion[attribute.name()] - new.data_type = "float" - elif "" in data_type: + elif data_type == "integer": new.int_value = 0 if new.is_null else Data.map_conversion[attribute.name()] - new.data_type = "integer" - elif "" in data_type or "" in data_type: + elif data_type == "boolean": new.bool_value = False if new.is_null else Data.map_conversion[attribute.name()] - new.data_type = "boolean" while len(props.projected_crs) > 0: props.projected_crs.remove(0) for attribute in IfcStore.get_schema().declaration_by_name("IfcProjectedCRS").all_attributes(): - data_type = str(attribute.type_of_attribute) - if "" in data_type: + new.data_type = data_type + if data_type == "string": new.string_value = "" if new.is_null else Data.projected_crs[attribute.name()] - new.data_type = "string" - elif "" in data_type: + elif data_type == "float": new.float_value = 0.0 if new.is_null else Data.projected_crs[attribute.name()] - new.data_type = "float" - elif "" in data_type: + elif data_type == "integer": new.int_value = 0 if new.is_null else Data.projected_crs[attribute.name()] - new.data_type = "integer" - elif "" in data_type or "" in data_type: + elif data_type == "boolean": new.bool_value = False if new.is_null else Data.projected_crs[attribute.name()] - new.data_type = "boolean" props.is_map_unit_null = Data.projected_crs["MapUnit"] is None if not props.is_map_unit_null: @@ -100,8 +95,8 @@ class EditGeoreferencing(bpy.types.Operator): map_conversion = {} for attribute in IfcStore.get_schema().declaration_by_name("IfcMapConversion").all_attributes(): - data_type = str(attribute.type_of_attribute) - if "" in data_type: + new.data_type = data_type + if data_type == "string": new.string_value = "" if new.is_null else material_set_item_data[attribute.name()] - new.data_type = "string" - elif "" in data_type: + elif data_type == "float": new.float_value = 0.0 if new.is_null else material_set_item_data[attribute.name()] - new.data_type = "float" - elif "" in data_type: + elif data_type == "integer": new.int_value = 0 if new.is_null else material_set_item_data[attribute.name()] - new.data_type = "integer" - elif "" in data_type or "" in data_type: + elif data_type == "boolean": new.bool_value = False if new.is_null else material_set_item_data[attribute.name()] - new.data_type = "boolean" return {"FINISHED"} diff --git a/src/ifcblenderexport/blenderbim/bim/module/pset/data.py b/src/ifcblenderexport/blenderbim/bim/module/pset/data.py index 9a6469d3ae..4632a085be 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/pset/data.py +++ b/src/ifcblenderexport/blenderbim/bim/module/pset/data.py @@ -1,5 +1,6 @@ import ifcopenshell -import blenderbim.bim.schema # TODO: refactor elsewhere +import ifcopenshell.util.attribute +import blenderbim.bim.schema # TODO: refactor elsewhere from blenderbim.bim.ifc import IfcStore @@ -31,7 +32,7 @@ class Data: @classmethod def add_type_product_psets(cls, product, product_id): if not hasattr(product, "HasPropertySets") or not product.HasPropertySets: - return # TODO + return # TODO for definition in product.HasPropertySets: if definition.is_a("IfcPropertySet"): cls.add_pset(definition, product_id) @@ -60,17 +61,17 @@ class Data: new_pset = { "Name": pset.Name, "is_expanded": True, - "Properties": cls.get_properties_from_template(pset.Name) or [] + "Properties": cls.get_properties_from_template(pset.Name) or [], } cls.products[product_id]["psets"].add(int(pset.id())) cls.psets[int(pset.id())] = new_pset try: if hasattr(pset, "HasProperties"): props = pset.HasProperties - elif hasattr(pset, "Properties"): # For IfcMaterialProperties + elif hasattr(pset, "Properties"): # For IfcMaterialProperties props = pset.Properties except: - return # I've seen ArchiCAD produce invalid IFCs with empty data + return # I've seen ArchiCAD produce invalid IFCs with empty data # Invalid IFC, but some vendors like Solidworks do this so we accomodate it if not props: return @@ -107,20 +108,22 @@ class Data: else: data_type = "string" value = str(value) - new_pset["Properties"].append({ - "Name": prop.Name, - "value": value, - "type": data_type, - "enum_items": [], - "is_null": prop.NominalValue.wrappedValue is None - }) + new_pset["Properties"].append( + { + "Name": prop.Name, + "value": value, + "type": data_type, + "enum_items": [], + "is_null": prop.NominalValue.wrappedValue is None, + } + ) @classmethod def add_qto(cls, qto, product_id): new_qto = { "Name": qto.Name, "is_expanded": True, - "Properties": cls.get_properties_from_template(qto.Name) or [] + "Properties": cls.get_properties_from_template(qto.Name) or [], } cls.products[product_id]["qtos"].add(int(qto.id())) cls.qtos[int(qto.id())] = new_qto @@ -135,13 +138,15 @@ class Data: has_existing_prop = True break if not has_existing_prop: - new_qto["Properties"].append({ - "Name": prop.Name, - "value": float(value), - "type": "float", - "enum_items": [], - "is_null": value is None - }) + new_qto["Properties"].append( + { + "Name": prop.Name, + "value": float(value), + "type": "float", + "enum_items": [], + "is_null": value is None, + } + ) @classmethod def get_properties_from_template(cls, name): @@ -151,12 +156,14 @@ class Data: properties = [] for prop_template in template.HasPropertyTemplates: if not prop_template.is_a("IfcSimplePropertyTemplate"): - continue # Other types not yet supported + continue # Other types not yet supported enum_items = [] if prop_template.TemplateType == "P_SINGLEVALUE": try: - data_type = str(IfcStore.get_schema().declaration_by_name(prop_template.PrimaryMeasureType or "IfcLabel")) + data_type = ifcopenshell.util.attribute.get_primitive_type( + IfcStore.get_schema().declaration_by_name(prop_template.PrimaryMeasureType or "IfcLabel") + ) except: # TODO: Occurs if the data type is something that exists in IFC4 and not in IFC2X3. To fully fix # this we need to generate the IFC2X3 pset template definitions. @@ -169,26 +176,15 @@ class Data: elif prop_template.TemplateType == "Q_COUNT": data_type = "integer" else: - continue # Other types not yet supported + continue # Other types not yet supported - if "" in data_type: - data_type = "string" - elif "" in data_type: - data_type = "float" - elif "" in data_type: - data_type = "integer" - elif "" in data_type: - data_type = "integer" - elif "" in data_type or "" in data_type: - data_type = "boolean" - elif "" in data_type: + elif data_type == "string": new.string_value = "" if new.is_null else data[attribute.name()] - new.data_type = "string" props.is_editing_boundary_condition = True return {"FINISHED"} diff --git a/src/ifcopenshell-python/ifcopenshell/util/attribute.py b/src/ifcopenshell-python/ifcopenshell/util/attribute.py new file mode 100644 index 0000000000..35d61c7b0a --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/util/attribute.py @@ -0,0 +1,29 @@ +def get_primitive_type(attribute_or_data_type): + if hasattr(attribute_or_data_type, "type_of_attribute"): + data_type = str(attribute_or_data_type.type_of_attribute()) + else: + data_type = str(attribute_or_data_type) + if "" in data_type: + return "string" + elif "" in data_type: + return "float" + elif "" in data_type or "" in data_type: + return "integer" + elif "" in data_type or "" in data_type: + return "boolean" + elif "