From 68208d88ea6695ef859e41d48d2f01e9c4e38b09 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Mon, 18 Nov 2024 14:27:40 +0500 Subject: [PATCH] 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'. --- .../ifcopenshell/util/schema.py | 31 +++++++++--- .../test/util/test_schema.py | 47 +++++++++++++++++++ 2 files changed, 71 insertions(+), 7 deletions(-) diff --git a/src/ifcopenshell-python/ifcopenshell/util/schema.py b/src/ifcopenshell-python/ifcopenshell/util/schema.py index fdae211b44..2587bb0dd1 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/schema.py +++ b/src/ifcopenshell-python/ifcopenshell/util/schema.py @@ -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 diff --git a/src/ifcopenshell-python/test/util/test_schema.py b/src/ifcopenshell-python/test/util/test_schema.py index d814ecf7b5..071ffb8cea 100644 --- a/src/ifcopenshell-python/test/util/test_schema.py +++ b/src/ifcopenshell-python/test/util/test_schema.py @@ -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