mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-12 02:23:34 +00:00
Refactor getting primitive data type into util
This commit is contained in:
@@ -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 "<entity" in data_type:
|
||||
data_type = "entity"
|
||||
|
||||
if isinstance(data_type, tuple):
|
||||
list_type = data_type[1]
|
||||
data_type = data_type[0]
|
||||
|
||||
if data_type in ["entity", "list", "string", "enum"]:
|
||||
value = None if value is None else str(value)
|
||||
elif "<list" in data_type:
|
||||
if "<entity" in data_type:
|
||||
list_type = "entity"
|
||||
elif "<string>" in data_type:
|
||||
list_type = "string"
|
||||
elif "<real>" in data_type:
|
||||
list_type = "float"
|
||||
elif "<integer>" in data_type:
|
||||
list_type = "integer"
|
||||
data_type = "list"
|
||||
value = None if value is None else str(value)
|
||||
elif "<string>" in data_type:
|
||||
data_type = "string"
|
||||
value = None if value is None else str(value)
|
||||
elif "<real>" in data_type:
|
||||
data_type = "float"
|
||||
elif data_type == "float":
|
||||
value = None if value is None else float(value)
|
||||
elif "<integer>" in data_type:
|
||||
data_type = "integer"
|
||||
elif data_type == "integer":
|
||||
value = None if value is None else int(value)
|
||||
elif "<enumeration" in data_type:
|
||||
data_type = "enum"
|
||||
value = None if value is None else str(value)
|
||||
enum_items = attribute.type_of_attribute().declared_type().enumeration_items()
|
||||
|
||||
if data_type == "enum":
|
||||
enum_items = ifcopenshell.util.attribute.get_enum_items(attribute)
|
||||
|
||||
cls.products[product_id].append({
|
||||
"name": attribute.name(),
|
||||
"value": value,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import bpy
|
||||
import json
|
||||
import ifcopenshell.util.attribute
|
||||
import blenderbim.bim.module.constraint.add_objective as add_objective
|
||||
import blenderbim.bim.module.constraint.edit_objective as edit_objective
|
||||
import blenderbim.bim.module.constraint.remove_constraint as remove_constraint
|
||||
@@ -50,19 +51,18 @@ class EnableEditingConstraint(bpy.types.Operator):
|
||||
data = Data.objectives[self.constraint]
|
||||
|
||||
for attribute in IfcStore.get_schema().declaration_by_name(props.is_editing).all_attributes():
|
||||
data_type = str(attribute.type_of_attribute)
|
||||
if "<entity" in data_type:
|
||||
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
|
||||
if data_type == "entity":
|
||||
continue
|
||||
new = props.constraint_attributes.add()
|
||||
new.name = attribute.name()
|
||||
new.is_null = data[attribute.name()] is None
|
||||
new.is_optional = attribute.optional()
|
||||
if "<string>" 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 "<enumeration" in data_type:
|
||||
new.enum_items = json.dumps(attribute.type_of_attribute().declared_type().enumeration_items())
|
||||
new.data_type = "enum"
|
||||
elif data_type == "enum":
|
||||
new.enum_items = json.dumps(ifcopenshell.util.attribute.get_enum_items(attribute))
|
||||
if data[attribute.name()]:
|
||||
new.enum_value = data[attribute.name()]
|
||||
props.active_constraint_id = self.constraint
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import bpy
|
||||
import json
|
||||
import ifcopenshell.util.attribute
|
||||
import blenderbim.bim.module.document.add_information as add_information
|
||||
import blenderbim.bim.module.document.add_reference as add_reference
|
||||
import blenderbim.bim.module.document.edit_information as edit_information
|
||||
@@ -83,19 +84,18 @@ class EnableEditingDocument(bpy.types.Operator):
|
||||
ifc_class = "IfcDocumentReference"
|
||||
|
||||
for attribute in IfcStore.get_schema().declaration_by_name(ifc_class).all_attributes():
|
||||
data_type = str(attribute.type_of_attribute)
|
||||
if "<entity" in data_type:
|
||||
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
|
||||
if data_type == "entity":
|
||||
continue
|
||||
new = props.document_attributes.add()
|
||||
new.name = attribute.name()
|
||||
new.is_null = data[attribute.name()] is None
|
||||
new.is_optional = attribute.optional()
|
||||
if "<string>" 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 "<enumeration" in data_type:
|
||||
new.enum_items = json.dumps(attribute.type_of_attribute().declared_type().enumeration_items())
|
||||
new.data_type = "enum"
|
||||
elif data_type == "enum":
|
||||
new.enum_items = json.dumps(ifcopenshell.util.attribute.get_enum_items(attribute))
|
||||
if data[attribute.name()]:
|
||||
new.enum_value = data[attribute.name()]
|
||||
props.active_document_id = self.document
|
||||
|
||||
@@ -2,6 +2,7 @@ import bpy
|
||||
import json
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.unit
|
||||
import ifcopenshell.util.attribute
|
||||
import blenderbim.bim.module.georeference.add_georeferencing as add_georeferencing
|
||||
import blenderbim.bim.module.georeference.edit_georeferencing as edit_georeferencing
|
||||
import blenderbim.bim.module.georeference.remove_georeferencing as remove_georeferencing
|
||||
@@ -22,49 +23,43 @@ class EnableEditingGeoreferencing(bpy.types.Operator):
|
||||
props.map_conversion.remove(0)
|
||||
|
||||
for attribute in IfcStore.get_schema().declaration_by_name("IfcMapConversion").all_attributes():
|
||||
data_type = str(attribute.type_of_attribute)
|
||||
if "<entity" in data_type:
|
||||
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
|
||||
if data_type == "entity":
|
||||
continue
|
||||
new = props.map_conversion.add()
|
||||
new.name = attribute.name()
|
||||
new.is_null = Data.map_conversion[attribute.name()] is None
|
||||
new.is_optional = attribute.optional()
|
||||
if "<string>" 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 "<real>" 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 "<integer>" 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 "<boolean>" in data_type or "<logical>" 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 "<entity" in data_type:
|
||||
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
|
||||
if data_type == "entity":
|
||||
continue
|
||||
new = props.projected_crs.add()
|
||||
new.name = attribute.name()
|
||||
new.is_null = Data.projected_crs[attribute.name()] is None
|
||||
new.is_optional = attribute.optional()
|
||||
if "<string>" 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 "<real>" 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 "<integer>" 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 "<boolean>" in data_type or "<logical>" 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 "<entity" in data_type:
|
||||
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
|
||||
if data_type == "entity":
|
||||
continue
|
||||
blender_attribute = props.map_conversion.get(attribute.name())
|
||||
if blender_attribute.is_null:
|
||||
@@ -117,8 +112,8 @@ class EditGeoreferencing(bpy.types.Operator):
|
||||
|
||||
projected_crs = {}
|
||||
for attribute in IfcStore.get_schema().declaration_by_name("IfcProjectedCRS").all_attributes():
|
||||
data_type = str(attribute.type_of_attribute)
|
||||
if "<entity" in data_type:
|
||||
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
|
||||
if data_type == "entity":
|
||||
continue
|
||||
blender_attribute = props.projected_crs.get(attribute.name())
|
||||
if blender_attribute.is_null:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import bpy
|
||||
import ifcopenshell.util.attribute
|
||||
import blenderbim.bim.module.group.add_group as add_group
|
||||
import blenderbim.bim.module.group.edit_group as edit_group
|
||||
import blenderbim.bim.module.group.remove_group as remove_group
|
||||
@@ -94,8 +95,8 @@ class EnableEditingGroup(bpy.types.Operator):
|
||||
data = Data.groups[self.group]
|
||||
|
||||
for attribute in IfcStore.get_schema().declaration_by_name("IfcGroup").all_attributes():
|
||||
data_type = str(attribute.type_of_attribute)
|
||||
if "<entity" in data_type:
|
||||
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
|
||||
if data_type == "entity":
|
||||
continue
|
||||
new = props.group_attributes.add()
|
||||
new.name = attribute.name()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import bpy
|
||||
import json
|
||||
import ifcopenshell.util.attribute
|
||||
import blenderbim.bim.module.layer.add_layer as add_layer
|
||||
import blenderbim.bim.module.layer.edit_layer as edit_layer
|
||||
import blenderbim.bim.module.layer.remove_layer as remove_layer
|
||||
@@ -49,8 +50,8 @@ class EnableEditingLayer(bpy.types.Operator):
|
||||
data = Data.layers[self.layer]
|
||||
|
||||
for attribute in IfcStore.get_schema().declaration_by_name("IfcPresentationLayerAssignment").all_attributes():
|
||||
data_type = str(attribute.type_of_attribute)
|
||||
if "<entity" in data_type:
|
||||
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
|
||||
if data_type == "entity":
|
||||
continue
|
||||
new = props.layer_attributes.add()
|
||||
new.name = attribute.name()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import bpy
|
||||
import ifcopenshell.util.attribute
|
||||
import blenderbim.bim.module.material.add_material as add_material
|
||||
import blenderbim.bim.module.material.remove_material as remove_material
|
||||
import blenderbim.bim.module.material.assign_material as assign_material
|
||||
@@ -351,25 +352,22 @@ class EnableEditingMaterialSetItem(bpy.types.Operator):
|
||||
props.material_set_item_attributes.remove(0)
|
||||
|
||||
for attribute in IfcStore.get_schema().declaration_by_name(material_set_item.is_a()).all_attributes():
|
||||
data_type = str(attribute.type_of_attribute)
|
||||
if "<entity" in data_type:
|
||||
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
|
||||
if data_type == "entity":
|
||||
continue
|
||||
if attribute.name() in material_set_item_data:
|
||||
new = props.material_set_item_attributes.add()
|
||||
new.name = attribute.name()
|
||||
new.is_null = material_set_item_data[attribute.name()] is None
|
||||
if "<string>" 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 "<real>" 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 "<integer>" 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 "<boolean>" in data_type or "<logical>" 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"}
|
||||
|
||||
|
||||
|
||||
@@ -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 "<string>" in data_type:
|
||||
data_type = "string"
|
||||
elif "<real>" in data_type:
|
||||
data_type = "float"
|
||||
elif "<number>" in data_type:
|
||||
data_type = "integer"
|
||||
elif "<integer>" in data_type:
|
||||
data_type = "integer"
|
||||
elif "<boolean>" in data_type or "<logical>" in data_type:
|
||||
data_type = "boolean"
|
||||
elif "<enumeration" in data_type:
|
||||
data_type = "enum"
|
||||
enum_items = attribute.type_of_attribute().declared_type().enumeration_items()
|
||||
properties.append({
|
||||
"Name": prop_template.Name,
|
||||
"value": None,
|
||||
"type": data_type,
|
||||
"enum_items": enum_items,
|
||||
"is_null": True
|
||||
})
|
||||
properties.append(
|
||||
{
|
||||
"Name": prop_template.Name,
|
||||
"value": None,
|
||||
"type": data_type,
|
||||
"enum_items": enum_items,
|
||||
"is_null": True,
|
||||
}
|
||||
)
|
||||
return properties
|
||||
|
||||
@@ -53,13 +53,13 @@ class EnableEditingStructuralBoundaryCondition(bpy.types.Operator):
|
||||
|
||||
for attribute in IfcStore.get_schema().declaration_by_name(data["type"]).all_attributes():
|
||||
value = data[attribute.name()]
|
||||
data_type = str(attribute.type_of_attribute)
|
||||
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
|
||||
new = props.boundary_condition_attributes.add()
|
||||
new.name = attribute.name()
|
||||
new.is_null = value is None
|
||||
new.is_optional = attribute.optional()
|
||||
if "<select" in data_type:
|
||||
enum_items = [s.name() for s in attribute.type_of_attribute().declared_type().select_list()]
|
||||
if data_type == "select":
|
||||
enum_items = [s.name() for s in ifcopenshell.get_select_items(attribute)]
|
||||
new.enum_items = json.dumps(enum_items)
|
||||
if isinstance(value, bool):
|
||||
new.bool_value = False if new.is_null else data[attribute.name()]
|
||||
@@ -69,9 +69,8 @@ class EnableEditingStructuralBoundaryCondition(bpy.types.Operator):
|
||||
new.float_value = 0.0 if new.is_null else data[attribute.name()]
|
||||
new.data_type = "float"
|
||||
new.enum_value = [i for i in enum_items if i != "IfcBoolean"][0]
|
||||
elif "<string>" 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"}
|
||||
|
||||
@@ -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 "<list" in data_type:
|
||||
return ("list", get_primitive_type(data_type.replace("<list", "")))
|
||||
elif "<entity" in data_type:
|
||||
return "entity"
|
||||
elif "<string>" in data_type:
|
||||
return "string"
|
||||
elif "<real>" in data_type:
|
||||
return "float"
|
||||
elif "<number>" in data_type or "<integer>" in data_type:
|
||||
return "integer"
|
||||
elif "<boolean>" in data_type or "<logical>" in data_type:
|
||||
return "boolean"
|
||||
elif "<enumeration" in data_type:
|
||||
return "enum"
|
||||
elif "<select" in data_type:
|
||||
return "select"
|
||||
|
||||
|
||||
def get_enum_items(attribute):
|
||||
return attribute.type_of_attribute().declared_type().enumeration_items()
|
||||
|
||||
|
||||
def get_select_items(attribute):
|
||||
return attribute.type_of_attribute().declared_type().select_list()
|
||||
Reference in New Issue
Block a user