Migrate - convert IfcQuantityCounts using float values to IfcQuantityNumber in ifc4x3 #5752

Traceback:
Traceback (most recent call last):
File "\bonsai\bim\module\patch\operator.py", line 187, in execute
core.run_migrate_patch(tool.Patch, infile=self.infile, outfile=self.outfile, schema=self.schema)
File "\bonsai\core\patch.py", line 30, in run_migrate_patch
patch.run_migrate_patch(infile, outfile, schema)
File "\bonsai\tool\patch.py", line 28, in run_migrate_patch
output = ifcpatch.execute(
^^^^^^^^^^^^^^^^^
File "\ifcpatch\__init__.py", line 85, in execute
patcher.patch()
File "\ifcpatch\recipes\Migrate.py", line 58, in patch
new_element = migrator.migrate(element, self.file_patched)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "\ifcopenshell\util\schema.py", line 363, in migrate
new_element = self.migrate_attributes(element, new_file, new_element, new_element_schema)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "\ifcopenshell\util\schema.py", line 393, in migrate_attributes
self.migrate_attribute(attribute, element, new_file, new_element, new_element_schema)
File "\ifcopenshell\util\schema.py", line 494, in migrate_attribute
new_value.append(self.migrate(item, new_file))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "\ifcopenshell\util\schema.py", line 363, in migrate
new_element = self.migrate_attributes(element, new_file, new_element, new_element_schema)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "\ifcopenshell\util\schema.py", line 393, in migrate_attributes
self.migrate_attribute(attribute, element, new_file, new_element, new_element_schema)
File "\ifcopenshell\util\schema.py", line 497, in migrate_attribute
setattr(new_element, attribute.name(), value)
File "\ifcopenshell\entity_instance.py", line 325, in __setattr__
self[index] = value
~~~~^^^^^^^
File "\ifcopenshell\entity_instance.py", line 363, in __setitem__
raise TypeError(
TypeError: attribute 'CountValue' for entity 'IFC4X3_ADD2.IfcQuantityCount' is expecting value of type 'INT', got 'float'.
Error: Python: Traceback (most recent call last):
File "\ifcopenshell\entity_instance.py", line 361, in __setitem__
self.method_list[idx](self.wrapped_data, idx, entity_instance.unwrap_value(value))
File "\ifcopenshell\ifcopenshell_wrapper.py", line 9271, in setArgumentAsInt
return _ifcopenshell_wrapper.entity_instance_setArgumentAsInt(self, i, v)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: in method 'entity_instance_setArgumentAsInt', argument 3 of type 'int'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "\ifcopenshell\entity_instance.py", line 325, in __setattr__
self[index] = value
~~~~^^^^^^^
File "\ifcopenshell\entity_instance.py", line 363, in __setitem__
raise TypeError(
TypeError: attribute 'CountValue' for entity 'IFC4X3_ADD2.IfcQuantityCount' is expecting value of type 'INT', got 'float'.
This commit is contained in:
Andrej730
2024-11-18 14:27:40 +05:00
parent 818c2714e8
commit 68208d88ea
2 changed files with 71 additions and 7 deletions
@@ -364,15 +364,21 @@ class Migrator:
def migrate_class(
self, element: ifcopenshell.entity_instance, new_file: ifcopenshell.file
) -> ifcopenshell.entity_instance:
ifc_class = element.is_a()
if ifc_class == "IfcQuantityCount" and new_file.schema == "IFC4X3":
# 3 IfcPhysicalSimpleQuantity Value
value = element[3]
if isinstance(value, float):
ifc_class = "IfcQuantityNumber"
try:
new_element = new_file.create_entity(element.is_a())
new_element = new_file.create_entity(ifc_class)
except:
# The element does not exist in this schema
# Complex migration is not yet supported (e.g. polygonal face set to faceted brep)
if new_file.schema == "IFC2X3":
new_element = new_file.create_entity(self.class_4_to_2x3[element.is_a()])
new_element = new_file.create_entity(self.class_4_to_2x3[ifc_class])
elif new_file.schema == "IFC4":
new_element = new_file.create_entity(self.class_2x3_to_4[element.is_a()])
new_element = new_file.create_entity(self.class_2x3_to_4[ifc_class])
return new_element
def migrate_attributes(self, element, new_file, new_element, new_element_schema):
@@ -393,21 +399,32 @@ class Migrator:
reverse_mapping: bool = False,
) -> Union[Any, None]:
# print("Searching for an equivalent", element, new_element, attribute.name())
ifc_class = new_element.is_a()
attr_name = attribute.name()
try:
if reverse_mapping:
equivalent_map = attributes_mapping[new_element.is_a()]
equivalent = list(equivalent_map.keys())[list(equivalent_map.values()).index(attribute.name())]
equivalent_map = attributes_mapping[ifc_class]
equivalent = list(equivalent_map.keys())[list(equivalent_map.values()).index(attr_name)]
else:
equivalent = attributes_mapping[new_element.is_a()][attribute.name()]
equivalent = attributes_mapping[ifc_class][attr_name]
if hasattr(element, equivalent):
# print("Equivalent found", equivalent)
return getattr(element, equivalent)
else:
return
except Exception as e:
if (
ifc_class == "IfcQuantityNumber"
and attr_name == "NumberValue"
and new_element.file.schema == "IFC4X3"
and element.is_a("IfcQuantityCount")
):
# 3 IfcPhysicalSimpleQuantity Value
return element[3]
print(
"Unable to find equivalent attribute of {} to migrate from {} to {}".format(
attribute.name(), element, new_element
attr_name, element, new_element
)
)
raise e
@@ -71,3 +71,50 @@ class TestMigrator(test.bootstrap.IFC4):
new_element = ifc2x3_file.by_type(original_element.is_a())[0]
assert original_element.Mode == new_element.TextureType
def test_migrate_ifccountmeasure_to_ifc4x3(self):
ifc_str = """
ISO-10303-21;
HEADER;
FILE_DESCRIPTION(('ViewDefinition[DesignTransferView]'),'2;1');
FILE_NAME('count.ifc','2024-11-18T12:44:20+05:00',(''),(''),'','','Nobody');
FILE_SCHEMA(('IFC4'));
ENDSEC;
DATA;
#1=IFCPROPERTYSINGLEVALUE('PropCountInt',$,IFCCOUNTMEASURE(232),$);
#2=IFCPROPERTYSINGLEVALUE('PropCountFloat',$,IFCCOUNTMEASURE(232.),$);
#3=IFCQUANTITYCOUNT('QuantityCountInt',$,$,723,$);
#4=IFCQUANTITYCOUNT('QuantityCountFloat',$,$,723.,$);
ENDSEC;
END-ISO-10303-21;
"""
ifc4_file = ifcopenshell.file.from_string(ifc_str)
ifc4x3_file = ifcopenshell.api.project.create_file(version="IFC4X3")
migrator = subject.Migrator()
prop_int_count_measure = ifc4_file.by_id(1)
prop_int_count_measure_ifc4x3 = migrator.migrate(prop_int_count_measure, ifc4x3_file)
value = prop_int_count_measure_ifc4x3.NominalValue
assert value.is_a("IfcCountMeasure")
assert isinstance(value.wrappedValue, int)
assert value.wrappedValue == 232
float_count_measure = ifc4_file.by_id(2)
float_count_measure_ifc4x3 = migrator.migrate(float_count_measure, ifc4x3_file)
value = float_count_measure_ifc4x3.NominalValue
assert value.is_a("IfcNumericMeasure")
assert isinstance(value.wrappedValue, float)
assert value.wrappedValue == 232.0
qt_int_count_measure = ifc4_file.by_id(3)
qt_int_count_measure_ifc4x3 = migrator.migrate(qt_int_count_measure, ifc4x3_file)
assert qt_int_count_measure_ifc4x3.is_a("IfcQuantityCount")
assert isinstance(qt_int_count_measure_ifc4x3[3], int)
assert qt_int_count_measure_ifc4x3[3] == 723
qt_float_count_measure = ifc4_file.by_id(4)
qt_float_count_measure_ifc4x3 = migrator.migrate(qt_float_count_measure, ifc4x3_file)
assert qt_float_count_measure_ifc4x3.is_a("IfcQuantityNumber")
assert isinstance(qt_float_count_measure_ifc4x3[3], float)
assert qt_float_count_measure_ifc4x3[3] == 723.0