diff --git a/src/ifcopenshell-python/ifcopenshell/util/schema.py b/src/ifcopenshell-python/ifcopenshell/util/schema.py index 7a5f2bcce5..8b976cbd3b 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/schema.py +++ b/src/ifcopenshell-python/ifcopenshell/util/schema.py @@ -49,22 +49,40 @@ def get_subtypes(entity): def reassign_class(ifc_file, element, new_class): + schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(ifc_file.schema) try: - new_element = ifcopenshell.create_entity(new_class) - new_element.GlobalId = element.GlobalId + declaration = schema.declaration_by_name(new_class) + except: + print(f"Class of {element} could not be changed to {new_class} as the class does not exist") + + info = element.get_info() + + new_attributes = {} + for attribute in declaration.all_attributes(): + name = attribute.name() + old_attribute = info.get(name, None) + if old_attribute: + new_attributes[name] = old_attribute + + inverse_pairs = ifc_file.get_inverse(element, allow_duplicate=True, with_attribute_indices=True) + ifc_file.remove(element) + + try: + new_element = ifc_file.create_entity(new_class, id=info["id"], **new_attributes) except: print(f"Class of {element} could not be changed to {new_class}") - return element - new_attributes = [new_element.attribute_name(i) for i, attribute in enumerate(new_element)] - for i, attribute in enumerate(element): - try: - new_element[new_attributes.index(element.attribute_name(i))] = attribute - except: - continue - for inverse in ifc_file.get_inverse(element): - ifcopenshell.util.element.replace_attribute(inverse, element, new_element) - ifc_file.remove(element) - ifc_file.add(new_element, element.id()) + old_class = info.pop("type") + return ifc_file.create_entity(old_class, **info) + + for inverse_pair in inverse_pairs: + inverse, index = inverse_pair + if inverse[index] is None: + inverse[index] = new_element + elif isinstance(inverse[index], tuple): + item = list(inverse[index]) + item.append(new_element) + inverse[index] = item + return new_element diff --git a/src/ifcopenshell-python/test/api/root/test_reassign_class.py b/src/ifcopenshell-python/test/api/root/test_reassign_class.py index 4400b4a159..aef105d1ce 100644 --- a/src/ifcopenshell-python/test/api/root/test_reassign_class.py +++ b/src/ifcopenshell-python/test/api/root/test_reassign_class.py @@ -25,7 +25,7 @@ class TestReassignClass(test.bootstrap.IFC4): element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") new = ifcopenshell.api.run("root.reassign_class", self.file, product=element, ifc_class="IfcSlab") assert len([e for e in self.file]) == 1 - assert new.id() == 2 + assert new.id() == 1 assert new.is_a("IfcSlab") def test_reassigning_a_predefined_type(self):