mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-21 14:23:53 +00:00
api.project.append_asset deduplicate material sets
When appending a wall type and a slab type in turn, if their material layer sets have the same name then the slab type would have a wall construction. Now the material sets are compared before reusing an existing material set.
This commit is contained in:
@@ -243,6 +243,59 @@ class Usecase:
|
|||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def material_sets_are_equal(self, set1: ifcopenshell.entity_instance, set2: ifcopenshell.entity_instance) -> bool:
|
||||||
|
"""Check if two material sets are structurally equivalent."""
|
||||||
|
if set1.is_a() != set2.is_a():
|
||||||
|
return False
|
||||||
|
|
||||||
|
ifc_class = set1.is_a()
|
||||||
|
|
||||||
|
if ifc_class == "IfcMaterialLayerSet":
|
||||||
|
layers1 = set1.MaterialLayers or []
|
||||||
|
layers2 = set2.MaterialLayers or []
|
||||||
|
if len(layers1) != len(layers2):
|
||||||
|
return False
|
||||||
|
for l1, l2 in zip(layers1, layers2):
|
||||||
|
if (l1.Material is None) != (l2.Material is None):
|
||||||
|
return False
|
||||||
|
if l1.Material and l1.Material.Name != l2.Material.Name:
|
||||||
|
return False
|
||||||
|
if l1.LayerThickness != l2.LayerThickness:
|
||||||
|
return False
|
||||||
|
|
||||||
|
elif ifc_class == "IfcMaterialConstituentSet":
|
||||||
|
constituents1 = set1.MaterialConstituents or []
|
||||||
|
constituents2 = set2.MaterialConstituents or []
|
||||||
|
if len(constituents1) != len(constituents2):
|
||||||
|
return False
|
||||||
|
for c1, c2 in zip(constituents1, constituents2):
|
||||||
|
if (c1.Material is None) != (c2.Material is None):
|
||||||
|
return False
|
||||||
|
if c1.Material and c1.Material.Name != c2.Material.Name:
|
||||||
|
return False
|
||||||
|
if c1.Name != c2.Name:
|
||||||
|
return False
|
||||||
|
|
||||||
|
elif ifc_class == "IfcMaterialProfileSet":
|
||||||
|
profiles1 = set1.MaterialProfiles or []
|
||||||
|
profiles2 = set2.MaterialProfiles or []
|
||||||
|
if len(profiles1) != len(profiles2):
|
||||||
|
return False
|
||||||
|
for p1, p2 in zip(profiles1, profiles2):
|
||||||
|
if (p1.Material is None) != (p2.Material is None):
|
||||||
|
return False
|
||||||
|
if p1.Material and p1.Material.Name != p2.Material.Name:
|
||||||
|
return False
|
||||||
|
if (p1.Profile is None) != (p2.Profile is None):
|
||||||
|
return False
|
||||||
|
if p1.Profile:
|
||||||
|
profile_name1 = getattr(p1.Profile, "ProfileName", None)
|
||||||
|
profile_name2 = getattr(p2.Profile, "ProfileName", None)
|
||||||
|
if profile_name1 != profile_name2:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def get_existing_element(self, element: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]:
|
def get_existing_element(self, element: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]:
|
||||||
"""Get existing element for a library element.
|
"""Get existing element for a library element.
|
||||||
|
|
||||||
@@ -270,7 +323,11 @@ class Usecase:
|
|||||||
material_set_name = getattr(element, name_attr)
|
material_set_name = getattr(element, name_attr)
|
||||||
if material_set_name is None:
|
if material_set_name is None:
|
||||||
return
|
return
|
||||||
return next((e for e in self.file.by_type(ifc_class) if getattr(e, name_attr) == material_set_name), None)
|
for candidate in self.file.by_type(ifc_class):
|
||||||
|
if getattr(candidate, name_attr) == material_set_name:
|
||||||
|
if self.material_sets_are_equal(element, candidate):
|
||||||
|
return candidate
|
||||||
|
return None
|
||||||
|
|
||||||
elif element.is_a("IfcProfileDef"):
|
elif element.is_a("IfcProfileDef"):
|
||||||
profile_name = element.ProfileName
|
profile_name = element.ProfileName
|
||||||
@@ -665,12 +722,11 @@ class Usecase:
|
|||||||
name_attr = "LayerSetName" if ifc_class == "IfcMaterialLayerSet" else "Name"
|
name_attr = "LayerSetName" if ifc_class == "IfcMaterialLayerSet" else "Name"
|
||||||
material_set_name = getattr(element, name_attr)
|
material_set_name = getattr(element, name_attr)
|
||||||
if material_set_name is not None:
|
if material_set_name is not None:
|
||||||
existing_material_set = next(
|
for candidate in ifc_file.by_type(ifc_class):
|
||||||
(e for e in ifc_file.by_type(ifc_class) if getattr(e, name_attr) == material_set_name), None
|
if getattr(candidate, name_attr) == material_set_name:
|
||||||
)
|
if self.material_sets_are_equal(element, candidate):
|
||||||
if existing_material_set is not None:
|
reuse_identities[element_identity] = candidate
|
||||||
reuse_identities[element_identity] = existing_material_set
|
return candidate
|
||||||
return existing_material_set
|
|
||||||
|
|
||||||
elif element.is_a("IfcPresentationStyle"):
|
elif element.is_a("IfcPresentationStyle"):
|
||||||
style_name = element.Name
|
style_name = element.Name
|
||||||
|
|||||||
Reference in New Issue
Block a user