mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-20 23:36:20 +00:00
ifc2x3 pset library - fix bunch of unit related vlaidation errors #3929
This commit is contained in:
@@ -20,10 +20,12 @@ RUN_FROM_DEV_REPO = False
|
|||||||
|
|
||||||
import ifcopenshell.api
|
import ifcopenshell.api
|
||||||
import ifcopenshell.util.attribute
|
import ifcopenshell.util.attribute
|
||||||
from pathlib import Path
|
|
||||||
from lxml import etree
|
|
||||||
import glob
|
import glob
|
||||||
import sys
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
from lxml import etree
|
||||||
|
from itertools import chain
|
||||||
|
|
||||||
|
|
||||||
if not RUN_FROM_DEV_REPO:
|
if not RUN_FROM_DEV_REPO:
|
||||||
import zipfile
|
import zipfile
|
||||||
@@ -47,8 +49,9 @@ IFC2x3_OUTPUT_PATH = BASE_MODULE_PATH / "schema/Pset_IFC2X3.ifc"
|
|||||||
PROPERTY_TYPES_DICT = {
|
PROPERTY_TYPES_DICT = {
|
||||||
"TypePropertySingleValue": ("P_SINGLEVALUE", "type"),
|
"TypePropertySingleValue": ("P_SINGLEVALUE", "type"),
|
||||||
# in IFC2X3 weirdly xmls have TypeSimpleProperty
|
# in IFC2X3 weirdly xmls have TypeSimpleProperty
|
||||||
# no difference with TypePropertySingleValue though
|
# which is actually more P_REFERENCEVALUE value, not P_SINGLEVALUE
|
||||||
"TypeSimpleProperty": ("P_SINGLEVALUE", "type"),
|
# because it utilizes IfcTimeSeries
|
||||||
|
"TypeSimpleProperty": ("P_REFERENCEVALUE", "type"),
|
||||||
"TypePropertyListValue": ("P_LISTVALUE", "type"),
|
"TypePropertyListValue": ("P_LISTVALUE", "type"),
|
||||||
"TypePropertyBoundedValue": ("P_BOUNDEDVALUE", "type"),
|
"TypePropertyBoundedValue": ("P_BOUNDEDVALUE", "type"),
|
||||||
"TypePropertyReferenceValue": ("P_REFERENCEVALUE", "reftype"),
|
"TypePropertyReferenceValue": ("P_REFERENCEVALUE", "reftype"),
|
||||||
@@ -121,12 +124,15 @@ class PsetTemplatesGenerator:
|
|||||||
def parse_psets_data(self, schema_name, pset_data_glob, project_name, ifc_output_path):
|
def parse_psets_data(self, schema_name, pset_data_glob, project_name, ifc_output_path):
|
||||||
schema_name = schema_name.upper()
|
schema_name = schema_name.upper()
|
||||||
self.ifc_file = ifcopenshell.api.run("project.create_file", version=schema_name)
|
self.ifc_file = ifcopenshell.api.run("project.create_file", version=schema_name)
|
||||||
|
self.units = dict()
|
||||||
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name)
|
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(schema_name)
|
||||||
|
|
||||||
self.ifc_derived_unit_enum = (
|
self.ifc_derived_unit_enum = (
|
||||||
schema.declaration_by_name("IfcDerivedUnitEnum").as_enumeration_type().enumeration_items()
|
schema.declaration_by_name("IfcDerivedUnitEnum").as_enumeration_type().enumeration_items()
|
||||||
)
|
)
|
||||||
self.ifc_unit_enum = schema.declaration_by_name("IfcUnitEnum").as_enumeration_type().enumeration_items()
|
self.ifc_unit_enum = schema.declaration_by_name("IfcUnitEnum").as_enumeration_type().enumeration_items()
|
||||||
|
select_types = schema.declaration_by_name("IfcValue").select_list()
|
||||||
|
self.ifc_value_types = [t.name() for t in chain(*[select_type.select_list() for select_type in select_types])]
|
||||||
|
|
||||||
project = self.ifc_entity("IfcProject", Name=project_name, GlobalId=ifcopenshell.guid.new())
|
project = self.ifc_entity("IfcProject", Name=project_name, GlobalId=ifcopenshell.guid.new())
|
||||||
psets_list = []
|
psets_list = []
|
||||||
@@ -246,11 +252,38 @@ class PsetTemplatesGenerator:
|
|||||||
self.add_prop_type_params_to_prop(pset_type, pdef, pset_property, property_type_tag)
|
self.add_prop_type_params_to_prop(pset_type, pdef, pset_property, property_type_tag)
|
||||||
return pset_property
|
return pset_property
|
||||||
|
|
||||||
|
def get_unit(self, unit_type):
|
||||||
|
# to define USERDEFINED unit type we'd need more info
|
||||||
|
# like UserDefinedType name and elements for IfcDerivedUnit
|
||||||
|
# which is not provided in .xmls
|
||||||
|
if unit_type != "USERDEFINED":
|
||||||
|
return None
|
||||||
|
|
||||||
|
if unit_type in self.units:
|
||||||
|
return self.units[unit_type]
|
||||||
|
|
||||||
|
unit_entity = None
|
||||||
|
if unit_type in self.ifc_derived_unit_enum:
|
||||||
|
# TODO: define derived units if there will be someday api like `ifcopenshell.api.run("unit.add_derived_unit", ...)`
|
||||||
|
# since creating IfcDerivedUnit is more complex and requiring settting up elements it consists of
|
||||||
|
# and related IfcNamedUnits
|
||||||
|
# unit_entity = ifcopenshell.api.run("unit.add_derived_unit", self.ifc_file, unit_type=unit_type)
|
||||||
|
pass
|
||||||
|
elif unit_type in self.ifc_unit_enum:
|
||||||
|
unit_entity = ifcopenshell.api.run("unit.add_si_unit", self.ifc_file, unit_type=unit_type)
|
||||||
|
elif unit_type == "IFCMONETARYUNIT":
|
||||||
|
self.ifc_entity("IFCMONETARYUNIT", Currency="")
|
||||||
|
else:
|
||||||
|
print(f"WARNING. Wasn't able to find units {unit_type} in schema.")
|
||||||
|
self.units[unit_type] = unit_entity
|
||||||
|
return unit_entity
|
||||||
|
|
||||||
def add_prop_type_params_to_prop(self, pset_type, pdef, pset_property, property_type_tag):
|
def add_prop_type_params_to_prop(self, pset_type, pdef, pset_property, property_type_tag):
|
||||||
if not pset_type:
|
if not pset_type:
|
||||||
property_type = pdef.find("QtoType").text
|
property_type = pdef.find("QtoType").text
|
||||||
else:
|
else:
|
||||||
property_type, property_type_parse = PROPERTY_TYPES_DICT[property_type_tag]
|
property_type, property_type_parse = PROPERTY_TYPES_DICT[property_type_tag]
|
||||||
|
|
||||||
pset_property.TemplateType = property_type
|
pset_property.TemplateType = property_type
|
||||||
|
|
||||||
if not pset_type or property_type == "P_COMPLEX":
|
if not pset_type or property_type == "P_COMPLEX":
|
||||||
@@ -285,7 +318,24 @@ class PsetTemplatesGenerator:
|
|||||||
pset_property.SecondaryMeasureType = property_type_xml.find("DefinedValue/DataType").get("type")
|
pset_property.SecondaryMeasureType = property_type_xml.find("DefinedValue/DataType").get("type")
|
||||||
else:
|
else:
|
||||||
if property_type == "P_REFERENCEVALUE":
|
if property_type == "P_REFERENCEVALUE":
|
||||||
pset_property.PrimaryMeasureType = property_type_xml.get(property_type_parse)
|
if property_type_tag == "TypeSimpleProperty":
|
||||||
|
type_xml = property_type_xml.find("DataType")
|
||||||
|
primary_measure_type = type_xml.get(property_type_parse)
|
||||||
|
unit_type = property_type_xml.find("UnitType")
|
||||||
|
secondary_measure_type = (
|
||||||
|
unit_type.get(property_type_parse).strip() if unit_type is not None else None
|
||||||
|
)
|
||||||
|
|
||||||
|
if primary_measure_type != "IfcTimeSeries":
|
||||||
|
unit = self.get_unit(secondary_measure_type)
|
||||||
|
secondary_measure_type = primary_measure_type
|
||||||
|
primary_measure_type = "IfcTimeSeries"
|
||||||
|
pset_property.PrimaryUnit = unit
|
||||||
|
|
||||||
|
pset_property.PrimaryMeasureType = primary_measure_type
|
||||||
|
pset_property.SecondaryMeasureType = secondary_measure_type
|
||||||
|
else:
|
||||||
|
pset_property.PrimaryMeasureType = property_type_xml.get(property_type_parse)
|
||||||
# TODO: ifc4add2 seems to have some secondary measure types
|
# TODO: ifc4add2 seems to have some secondary measure types
|
||||||
# need to add it in ifc4x3 too
|
# need to add it in ifc4x3 too
|
||||||
# if https://github.com/buildingSMART/IFC4.3.x-development/issues/586 is resolved
|
# if https://github.com/buildingSMART/IFC4.3.x-development/issues/586 is resolved
|
||||||
@@ -297,17 +347,10 @@ class PsetTemplatesGenerator:
|
|||||||
|
|
||||||
# only used only in ifc2x3, omitted in ifc4 and ifc4x3
|
# only used only in ifc2x3, omitted in ifc4 and ifc4x3
|
||||||
unit_type_xml = property_type_xml.find("UnitType")
|
unit_type_xml = property_type_xml.find("UnitType")
|
||||||
|
|
||||||
if unit_type_xml is not None:
|
if unit_type_xml is not None:
|
||||||
unit_type = unit_type_xml.get(property_type_parse).strip()
|
unit_type = unit_type_xml.get(property_type_parse).strip()
|
||||||
if unit_type.lower().startswith("ifc"):
|
unit_entity = self.get_unit(unit_type)
|
||||||
unit_entity = self.ifc_entity(unit_type)
|
|
||||||
else:
|
|
||||||
if unit_type in self.ifc_derived_unit_enum:
|
|
||||||
unit_entity = self.ifc_entity("IfcDerivedUnit", UnitType=unit_type)
|
|
||||||
elif unit_type in self.ifc_unit_enum:
|
|
||||||
unit_entity = self.ifc_entity("IfcNamedUnit", UnitType=unit_type)
|
|
||||||
else:
|
|
||||||
print("WARNING. Wasn't able to find units {unit_type} in schema.")
|
|
||||||
pset_property.PrimaryUnit = unit_entity
|
pset_property.PrimaryUnit = unit_entity
|
||||||
|
|
||||||
type_xml = property_type_xml.find(property_type_node)
|
type_xml = property_type_xml.find(property_type_node)
|
||||||
@@ -317,6 +360,12 @@ class PsetTemplatesGenerator:
|
|||||||
else:
|
else:
|
||||||
primary_measure_type = type_xml.get(property_type_parse)
|
primary_measure_type = type_xml.get(property_type_parse)
|
||||||
|
|
||||||
|
primary_measure_type = primary_measure_type.strip()
|
||||||
|
if property_type == "P_SINGLEVALUE" and primary_measure_type not in self.ifc_value_types:
|
||||||
|
print(
|
||||||
|
f"Error assinging {primary_measure_type} as PrimaryMeasureType - it's not IfcValue, {property_type_tag}"
|
||||||
|
)
|
||||||
|
|
||||||
pset_property.PrimaryMeasureType = primary_measure_type
|
pset_property.PrimaryMeasureType = primary_measure_type
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user