append_asset - ensure to update existing rels appending second asset

E.g. in #5890 pset was shared by 2 elements and they it worked is
1) it appended first element and it's rel to pset
2) it appended second element and skipped updating it's rel as it was appended before. Now it's going to update it to ensure it encludes second element too.

I believe, issue occurred after 8c28f52 when we stopped duplicating inverses and started to reuse them.
This commit is contained in:
Andrej730
2024-12-20 12:45:39 +05:00
parent 8c6eddfb66
commit 74fe1b4eb9
2 changed files with 38 additions and 6 deletions
@@ -323,12 +323,16 @@ class Usecase:
element_identity = element.wrapped_data.identity() element_identity = element.wrapped_data.identity()
# check if inverse element were created before # Check if inverse element was created before.
if self.reuse_identities.get(element_identity) is not None: # Still need to recreate it again - e.g. it could be some rel
return # that now needs it's RelatingObjects to be extended by the current asset.
if (new := self.reuse_identities.get(element_identity)) is not None:
new = self.file.create_entity(element.is_a()) # Currently known cases requiring attributes reassignment are rels.
self.reuse_identities[element_identity] = new if not new.is_a("IfcRelationship"):
return
else:
new = self.file.create_entity(element.is_a())
self.reuse_identities[element_identity] = new
for i, attribute in enumerate(element): for i, attribute in enumerate(element):
new_attribute = None new_attribute = None
@@ -346,11 +350,21 @@ class Usecase:
new[i] = new_attribute new[i] = new_attribute
def is_another_asset(self, element: ifcopenshell.entity_instance) -> bool: def is_another_asset(self, element: ifcopenshell.entity_instance) -> bool:
"""Is IFC entity from inverse attribute is another asset to append that should be skipped."""
def by_guid(guid: str) -> Union[ifcopenshell.entity_instance, None]:
try:
return self.file.by_guid(guid)
except RuntimeError:
return None
if element == self.settings["element"]: if element == self.settings["element"]:
return False return False
elif element.is_a("IfcFeatureElement"): elif element.is_a("IfcFeatureElement"):
# Feature elements match the target class but aren't considered "assets" # Feature elements match the target class but aren't considered "assets"
return False return False
elif element.is_a("IfcRoot") and by_guid(element.GlobalId) is not None:
return False
elif element.is_a(self.target_class): elif element.is_a(self.target_class):
return True return True
elif self.target_class == "IfcProduct" and element.is_a("IfcTypeProduct"): elif self.target_class == "IfcProduct" and element.is_a("IfcTypeProduct"):
@@ -433,6 +433,24 @@ class TestAppendAssetIFC2X3(test.bootstrap.IFC2X3):
del shading_colour_info["id"], shading_colour_info["type"] del shading_colour_info["id"], shading_colour_info["type"]
assert shading_colour_info == shading_attrs["SurfaceColour"] assert shading_colour_info == shading_attrs["SurfaceColour"]
def test_update_rels_appending_subsequent_assets(self):
library = ifcopenshell.api.project.create_file(version=self.file.schema)
element1 = ifcopenshell.api.root.create_entity(library, ifc_class="IfcWall")
pset = ifcopenshell.api.pset.add_pset(library, product=element1, name="Test")
element2 = ifcopenshell.api.root.create_entity(library, ifc_class="IfcWall")
ifcopenshell.api.pset.assign_pset(library, pset=pset, products=[element2])
reuse_identities = {}
element1_ = ifcopenshell.api.project.append_asset(
self.file, library, element1, reuse_identities=reuse_identities
)
element2_ = ifcopenshell.api.project.append_asset(
self.file, library, element2, reuse_identities=reuse_identities
)
pset_data = ifcopenshell.util.element.get_psets(element1_)
assert "Test" in pset_data
assert ifcopenshell.util.element.get_psets(element2_) == pset_data
class TestAppendAssetIFC4(test.bootstrap.IFC4, TestAppendAssetIFC2X3): class TestAppendAssetIFC4(test.bootstrap.IFC4, TestAppendAssetIFC2X3):
# NOTE: breaks in IFC2X3 since IfcProfileDef doesn't have "HasProperties" inverse in ifc2x3 # NOTE: breaks in IFC2X3 since IfcProfileDef doesn't have "HasProperties" inverse in ifc2x3