material.unassign_material - support batching #4474

This commit is contained in:
Andrej730
2024-04-12 16:15:14 +05:00
parent 59cc9c0a16
commit eb46de9658
9 changed files with 181 additions and 86 deletions
@@ -324,8 +324,8 @@ class UpdateRepresentation(bpy.types.Operator, Operator):
# We are explicitly casting to a tessellation, so remove all parametric materials. # We are explicitly casting to a tessellation, so remove all parametric materials.
element_type = ifcopenshell.util.element.get_type(product) element_type = ifcopenshell.util.element.get_type(product)
if element_type: # Some invalid IFCs use material sets without a type. if element_type: # Some invalid IFCs use material sets without a type.
ifcopenshell.api.run("material.unassign_material", tool.Ifc.get(), product=element_type) ifcopenshell.api.run("material.unassign_material", tool.Ifc.get(), products=[element_type])
ifcopenshell.api.run("material.unassign_material", tool.Ifc.get(), product=product) ifcopenshell.api.run("material.unassign_material", tool.Ifc.get(), products=[product])
else: else:
# These objects are parametrically based on an axis and should not be modified as a mesh # These objects are parametrically based on an axis and should not be modified as a mesh
return return
@@ -551,7 +551,7 @@ def ensure_material_assigned(usecase_path, ifc_file, settings):
def ensure_material_unassigned(usecase_path, ifc_file, settings): def ensure_material_unassigned(usecase_path, ifc_file, settings):
elements = [settings["product"]] elements = settings["products"]
if elements[0].is_a("IfcElementType"): if elements[0].is_a("IfcElementType"):
elements.extend(ifcopenshell.util.element.get_types(elements[0])) elements.extend(ifcopenshell.util.element.get_types(elements[0]))
for element in elements: for element in elements:
+3 -3
View File
@@ -116,12 +116,12 @@ def unassign_material(ifc, material_tool, objects):
inherited_material = material_tool.get_material(element, should_inherit=True) inherited_material = material_tool.get_material(element, should_inherit=True)
if material and "Usage" in material.is_a(): if material and "Usage" in material.is_a():
element_type = material_tool.get_type(element) element_type = material_tool.get_type(element)
ifc.run("material.unassign_material", product=element_type) ifc.run("material.unassign_material", products=[element_type])
elif not material and inherited_material: elif not material and inherited_material:
element_type = material_tool.get_type(element) element_type = material_tool.get_type(element)
ifc.run("material.unassign_material", product=element_type) ifc.run("material.unassign_material", products=[element_type])
elif material: elif material:
ifc.run("material.unassign_material", product=element) ifc.run("material.unassign_material", products=[element])
def patch_non_parametric_mep_segment(ifc, material_tool, profile_tool, obj): def patch_non_parametric_mep_segment(ifc, material_tool, profile_tool, obj):
@@ -79,15 +79,14 @@ ARGUMENTS_DEPRECATION = {
"type.unassign_type": partial( "type.unassign_type": partial(
batching_argument_deprecation, prev_argument="related_object", new_argument="related_objects" batching_argument_deprecation, prev_argument="related_object", new_argument="related_objects"
), ),
"system.assign_system": partial( "system.assign_system": partial(batching_argument_deprecation, prev_argument="product", new_argument="products"),
batching_argument_deprecation, prev_argument="product", new_argument="products" "system.unassign_system": partial(batching_argument_deprecation, prev_argument="product", new_argument="products"),
),
"system.unassign_system": partial(
batching_argument_deprecation, prev_argument="product", new_argument="products"
),
"material.assign_material": partial( "material.assign_material": partial(
batching_argument_deprecation, prev_argument="product", new_argument="products" batching_argument_deprecation, prev_argument="product", new_argument="products"
), ),
"material.unassign_material": partial(
batching_argument_deprecation, prev_argument="product", new_argument="products"
),
} }
@@ -155,10 +155,9 @@ class Usecase:
return return
# NOTE: we always reassign material, even if it might be assigned before # NOTE: we always reassign material, even if it might be assigned before
for product in self.products: products_to_unassign_material = [p for p in self.products if ifcopenshell.util.element.get_material(p)]
material = ifcopenshell.util.element.get_material(product) if products_to_unassign_material:
if material: ifcopenshell.api.run("material.unassign_material", self.file, products=products_to_unassign_material)
ifcopenshell.api.run("material.unassign_material", self.file, product=product)
if self.settings["type"] == "IfcMaterial" or ( if self.settings["type"] == "IfcMaterial" or (
self.settings["material"] and not self.settings["material"].is_a("IfcMaterial") self.settings["material"] and not self.settings["material"].is_a("IfcMaterial")
@@ -17,12 +17,13 @@
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>. # along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
import ifcopenshell import ifcopenshell
import ifcopenshell.api
import ifcopenshell.util.element import ifcopenshell.util.element
class Usecase: class Usecase:
def __init__(self, file, product=None): def __init__(self, file: ifcopenshell.file, products: list[ifcopenshell.entity_instance]):
"""Removes any material relationship with a product """Removes any material relationship with the list of products
A product can only have one material assigned to it, which is why it is A product can only have one material assigned to it, which is why it is
not necessary to specify the material to unassign. The material is not not necessary to specify the material to unassign. The material is not
@@ -30,8 +31,8 @@ class Usecase:
If the product does not have a material, nothing happens. If the product does not have a material, nothing happens.
:param product: The IfcProduct that may or may not have a material :param products: The list IfcProducts that may or may not have a material
:type product: ifcopenshell.entity_instance.entity_instance :type product: list[ifcopenshell.entity_instance.entity_instance]
:return: None :return: None
:rtype: None :rtype: None
@@ -49,20 +50,34 @@ class Usecase:
# Let's change our mind and remove the concrete assignment. The # Let's change our mind and remove the concrete assignment. The
# concrete material still exists, but the bench is no longer made # concrete material still exists, but the bench is no longer made
# out of concrete now. # out of concrete now.
ifcopenshell.api.run("material.unassign_material", model, product=bench_type) ifcopenshell.api.run("material.unassign_material", model, products=[bench_type])
""" """
self.file = file self.file = file
self.settings = {"product": product} self.settings = {"products": products}
def execute(self): def execute(self) -> None:
if self.settings["product"].is_a("IfcTypeObject"): self.products = set(self.settings["products"])
material = ifcopenshell.util.element.get_material(self.settings["product"]) if not self.products:
return
self.remove_material_usages_from_types()
self.unassign_materials()
def remove_material_usages_from_types(self) -> None:
# remove material usages from types
for product in self.products:
if not product.is_a("IfcTypeObject"):
continue
material = ifcopenshell.util.element.get_material(product)
if not material:
continue
if material.is_a() in ["IfcMaterialLayerSet", "IfcMaterialProfileSet"]: if material.is_a() in ["IfcMaterialLayerSet", "IfcMaterialProfileSet"]:
# Remove set usages # Remove set usages
for inverse in self.file.get_inverse(material): for inverse in self.file.get_inverse(material):
if self.file.schema == "IFC2X3": if self.file.schema == "IFC2X3":
if not inverse.is_a("IfcMaterialLayerSetUsage"): if not inverse.is_a("IfcMaterialLayerSetUsage"):
continue continue
# in IFC2X3 there is no .AssociatedTo
for inverse2 in self.file.get_inverse(inverse): for inverse2 in self.file.get_inverse(inverse):
if inverse2.is_a("IfcRelAssociatesMaterial"): if inverse2.is_a("IfcRelAssociatesMaterial"):
history = inverse2.OwnerHistory history = inverse2.OwnerHistory
@@ -73,21 +88,40 @@ class Usecase:
if not inverse.is_a("IfcMaterialUsageDefinition"): if not inverse.is_a("IfcMaterialUsageDefinition"):
continue continue
for rel in inverse.AssociatedTo: for rel in inverse.AssociatedTo:
history = rel.OwnerHistory
self.file.remove(rel) self.file.remove(rel)
if history:
ifcopenshell.util.element.remove_deep2(self.file, history)
self.file.remove(inverse) self.file.remove(inverse)
for rel in self.settings["product"].HasAssociations: def unassign_materials(self) -> None:
if rel.is_a("IfcRelAssociatesMaterial"): associations: set[ifcopenshell.entity_instance] = set()
if rel.RelatingMaterial.is_a() in ["IfcMaterialLayerSetUsage", "IfcMaterialProfileSetUsage"]: for product in self.products:
associations.update(product.HasAssociations)
# we ensure that `associations` won't have removed elements
# to avoid crash during `material_inverses.issubset(associations)`
while associations:
rel = next(iter(associations))
if not rel.is_a("IfcRelAssociatesMaterial"):
associations.remove(rel)
else:
material = rel.RelatingMaterial
related_objects = set(rel.RelatedObjects) - self.products
if material.is_a() in ["IfcMaterialLayerSetUsage", "IfcMaterialProfileSetUsage"]:
# Warning: this may leave the model in a non-compliant state. # Warning: this may leave the model in a non-compliant state.
if self.file.get_total_inverses(rel.RelatingMaterial) == 1 and len(rel.RelatedObjects) == 1: material_inverses = set(self.file.get_inverse(material))
self.file.remove(rel.RelatingMaterial) if material_inverses.issubset(associations) and not related_objects:
if len(rel.RelatedObjects) == 1: self.file.remove(material)
associations.remove(rel)
if not related_objects:
history = rel.OwnerHistory history = rel.OwnerHistory
self.file.remove(rel) self.file.remove(rel)
if history: if history:
ifcopenshell.util.element.remove_deep2(self.file, history) ifcopenshell.util.element.remove_deep2(self.file, history)
continue continue
related_objects = set(rel.RelatedObjects)
related_objects.remove(self.settings["product"])
rel.RelatedObjects = list(related_objects) rel.RelatedObjects = list(related_objects)
ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": rel})
@@ -126,7 +126,7 @@ class Usecase:
pset=inverse.RelatingPropertyDefinition, pset=inverse.RelatingPropertyDefinition,
) )
elif inverse.is_a("IfcRelAssociatesMaterial"): elif inverse.is_a("IfcRelAssociatesMaterial"):
ifcopenshell.api.run("material.unassign_material", self.file, product=self.settings["product"]) ifcopenshell.api.run("material.unassign_material", self.file, products=[self.settings["product"]])
elif inverse.is_a("IfcRelDefinesByType"): elif inverse.is_a("IfcRelDefinesByType"):
if inverse.RelatingType == self.settings["product"]: if inverse.RelatingType == self.settings["product"]:
ifcopenshell.api.run("type.unassign_type", self.file, related_objects=inverse.RelatedObjects) ifcopenshell.api.run("type.unassign_type", self.file, related_objects=inverse.RelatedObjects)
@@ -21,16 +21,17 @@ import ifcopenshell.api
import ifcopenshell.util.element import ifcopenshell.util.element
class TestUnassignMaterial(test.bootstrap.IFC4): class TestUnassignMaterialIFC2X3(test.bootstrap.IFC2X3):
def test_unassign_single_material(self): def test_unassign_single_material(self):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") element1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
material = ifcopenshell.api.run("material.add_material", self.file, name="CON01") material = ifcopenshell.api.run("material.add_material", self.file, name="CON01")
ifcopenshell.api.run( ifcopenshell.api.run(
"material.assign_material", self.file, products=[element], type="IfcMaterial", material=material "material.assign_material", self.file, products=[element1, element2], type="IfcMaterial", material=material
) )
ifcopenshell.api.run("material.unassign_material", self.file, product=element) ifcopenshell.api.run("material.unassign_material", self.file, products=[element1, element2])
assert len(self.file.by_type("IfcRelAssociatesMaterial")) == 0 assert len(self.file.by_type("IfcRelAssociatesMaterial")) == 0
assert len(self.file.by_type("IfcWall")) == 1 assert len(self.file.by_type("IfcWall")) == 2
assert len(self.file.by_type("IfcMaterial")) == 1 assert len(self.file.by_type("IfcMaterial")) == 1
def test_unassign_single_material_with_multiple_elements(self): def test_unassign_single_material_with_multiple_elements(self):
@@ -38,12 +39,9 @@ class TestUnassignMaterial(test.bootstrap.IFC4):
element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
material = ifcopenshell.api.run("material.add_material", self.file, name="CON01") material = ifcopenshell.api.run("material.add_material", self.file, name="CON01")
ifcopenshell.api.run( ifcopenshell.api.run(
"material.assign_material", self.file, products=[element1], type="IfcMaterial", material=material "material.assign_material", self.file, products=[element1, element2], type="IfcMaterial", material=material
) )
ifcopenshell.api.run( ifcopenshell.api.run("material.unassign_material", self.file, products=[element2])
"material.assign_material", self.file, products=[element2], type="IfcMaterial", material=material
)
ifcopenshell.api.run("material.unassign_material", self.file, product=element2)
assert element1.HasAssociations assert element1.HasAssociations
assert not element2.HasAssociations assert not element2.HasAssociations
assert len(self.file.by_type("IfcRelAssociatesMaterial")) == 1 assert len(self.file.by_type("IfcRelAssociatesMaterial")) == 1
@@ -51,36 +49,63 @@ class TestUnassignMaterial(test.bootstrap.IFC4):
assert len(self.file.by_type("IfcMaterial")) == 1 assert len(self.file.by_type("IfcMaterial")) == 1
def test_unassign_material_layer_set_from_type(self): def test_unassign_material_layer_set_from_type(self):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType") element1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType")
material = ifcopenshell.api.run("material.add_material", self.file, name="CON01") element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType")
ifcopenshell.api.run("material.assign_material", self.file, products=[element], type="IfcMaterialLayerSet") ifcopenshell.api.run(
ifcopenshell.api.run("material.unassign_material", self.file, product=element) "material.assign_material", self.file, products=[element1, element2], type="IfcMaterialLayerSet"
)
ifcopenshell.api.run("material.unassign_material", self.file, products=[element1, element2])
assert len(self.file.by_type("IfcRelAssociatesMaterial")) == 0 assert len(self.file.by_type("IfcRelAssociatesMaterial")) == 0
assert len(self.file.by_type("IfcWallType")) == 1 assert len(self.file.by_type("IfcWallType")) == 2
assert len(self.file.by_type("IfcMaterialLayerSet")) == 1 assert len(self.file.by_type("IfcMaterialLayerSet")) == 1
def test_unassign_material_layer_set_usage_from_element(self): def test_unassign_material_layer_set_usage_from_element(self):
element_type = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType") element_type = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType")
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") element1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
ifcopenshell.api.run("type.assign_type", self.file, related_objects=[element], relating_type=element_type) element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
material = ifcopenshell.api.run("material.add_material", self.file, name="CON01") ifcopenshell.api.run(
"type.assign_type", self.file, related_objects=[element1, element2], relating_type=element_type
)
ifcopenshell.api.run("material.assign_material", self.file, products=[element_type], type="IfcMaterialLayerSet") ifcopenshell.api.run("material.assign_material", self.file, products=[element_type], type="IfcMaterialLayerSet")
ifcopenshell.api.run("material.assign_material", self.file, products=[element], type="IfcMaterialLayerSetUsage") ifcopenshell.api.run(
ifcopenshell.api.run("material.unassign_material", self.file, product=element) "material.assign_material", self.file, products=[element1, element2], type="IfcMaterialLayerSetUsage"
)
ifcopenshell.api.run("material.unassign_material", self.file, products=[element1, element2])
assert len(self.file.by_type("IfcRelAssociatesMaterial")) == 1 assert len(self.file.by_type("IfcRelAssociatesMaterial")) == 1
assert element_type.HasAssociations assert element_type.HasAssociations
assert len(self.file.by_type("IfcWallType")) == 1 assert len(self.file.by_type("IfcWallType")) == 1
assert len(self.file.by_type("IfcWall")) == 1 assert len(self.file.by_type("IfcWall")) == 2
assert len(self.file.by_type("IfcMaterialLayerSet")) == 1 assert len(self.file.by_type("IfcMaterialLayerSet")) == 1
assert len(self.file.by_type("IfcMaterialLayerSetUsage")) == 0 assert len(self.file.by_type("IfcMaterialLayerSetUsage")) == 0
def test_unassign_material_layer_set_usage_shouldnt_remove_other_usages_of_the_type(self):
element_type = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType")
element1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
ifcopenshell.api.run(
"type.assign_type", self.file, related_objects=[element1, element2], relating_type=element_type
)
ifcopenshell.api.run("material.assign_material", self.file, products=[element_type], type="IfcMaterialLayerSet")
ifcopenshell.api.run(
"material.assign_material", self.file, products=[element1], type="IfcMaterialLayerSetUsage"
)
ifcopenshell.api.run(
"material.assign_material", self.file, products=[element2], type="IfcMaterialLayerSetUsage"
)
ifcopenshell.api.run("material.unassign_material", self.file, products=[element1])
assert len(self.file.by_type("IfcRelAssociatesMaterial")) == 2
assert element_type.HasAssociations
assert len(self.file.by_type("IfcWallType")) == 1
assert len(self.file.by_type("IfcWall")) == 2
assert len(self.file.by_type("IfcMaterialLayerSet")) == 1
assert len(self.file.by_type("IfcMaterialLayerSetUsage")) == 1
def test_unassign_material_layer_set_usage_from_element_with_multiple_invalid_usages(self): def test_unassign_material_layer_set_usage_from_element_with_multiple_invalid_usages(self):
element_type = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType") element_type = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType")
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
ifcopenshell.api.run("type.assign_type", self.file, related_objects=[element], relating_type=element_type) ifcopenshell.api.run("type.assign_type", self.file, related_objects=[element], relating_type=element_type)
ifcopenshell.api.run("type.assign_type", self.file, related_objects=[element2], relating_type=element_type) ifcopenshell.api.run("type.assign_type", self.file, related_objects=[element2], relating_type=element_type)
material = ifcopenshell.api.run("material.add_material", self.file, name="CON01")
ifcopenshell.api.run("material.assign_material", self.file, products=[element_type], type="IfcMaterialLayerSet") ifcopenshell.api.run("material.assign_material", self.file, products=[element_type], type="IfcMaterialLayerSet")
rel = ifcopenshell.api.run( rel = ifcopenshell.api.run(
"material.assign_material", self.file, products=[element], type="IfcMaterialLayerSetUsage" "material.assign_material", self.file, products=[element], type="IfcMaterialLayerSetUsage"
@@ -89,7 +114,7 @@ class TestUnassignMaterial(test.bootstrap.IFC4):
# In some invalid IFCs from Revit, they reuse usages. Let's recreate this invalid scenario # In some invalid IFCs from Revit, they reuse usages. Let's recreate this invalid scenario
rel.RelatedObjects = list(rel.RelatedObjects) + [element2] rel.RelatedObjects = list(rel.RelatedObjects) + [element2]
ifcopenshell.api.run("material.unassign_material", self.file, product=element) ifcopenshell.api.run("material.unassign_material", self.file, products=[element])
assert len(self.file.by_type("IfcRelAssociatesMaterial")) == 2 assert len(self.file.by_type("IfcRelAssociatesMaterial")) == 2
for rel in self.file.by_type("IfcRelAssociatesMaterial"): for rel in self.file.by_type("IfcRelAssociatesMaterial"):
@@ -102,46 +127,72 @@ class TestUnassignMaterial(test.bootstrap.IFC4):
assert ifcopenshell.util.element.get_material(element, should_inherit=False) is None assert ifcopenshell.util.element.get_material(element, should_inherit=False) is None
assert ifcopenshell.util.element.get_material(element2, should_inherit=False).is_a("IfcMaterialLayerSetUsage") assert ifcopenshell.util.element.get_material(element2, should_inherit=False).is_a("IfcMaterialLayerSetUsage")
def test_unassign_material_profile_set_from_type(self): def test_unassign_element_material_list(self):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType") element1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
material = ifcopenshell.api.run("material.add_material", self.file, name="CON01") element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
ifcopenshell.api.run("material.assign_material", self.file, products=[element], type="IfcMaterialProfileSet") material1 = ifcopenshell.api.run("material.add_material", self.file, name="CON01")
ifcopenshell.api.run("material.unassign_material", self.file, product=element) ifcopenshell.api.run(
"material.assign_material",
self.file,
products=[element1, element2],
type="IfcMaterialList",
material=material1,
)
element3 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
material3 = ifcopenshell.api.run("material.add_material", self.file, name="CON01")
ifcopenshell.api.run(
"material.assign_material", self.file, products=[element3], type="IfcMaterialList", material=material3
)
ifcopenshell.api.run("material.unassign_material", self.file, products=[element1, element2, element3])
assert len(self.file.by_type("IfcRelAssociatesMaterial")) == 0 assert len(self.file.by_type("IfcRelAssociatesMaterial")) == 0
assert len(self.file.by_type("IfcWallType")) == 1 assert len(self.file.by_type("IfcMaterialList")) == 2
assert len(self.file.by_type("IfcMaterialProfileSet")) == 1 assert len(self.file.by_type("IfcMaterial")) == 2
class TestUnassignMaterialIFC4(test.bootstrap.IFC4, TestUnassignMaterialIFC2X3):
def test_unassign_material_profile_set_from_type(self):
element1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType")
ifcopenshell.api.run("material.assign_material", self.file, products=[element1], type="IfcMaterialProfileSet")
element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType")
ifcopenshell.api.run("material.assign_material", self.file, products=[element2], type="IfcMaterialProfileSet")
ifcopenshell.api.run("material.unassign_material", self.file, products=[element1, element2])
assert len(self.file.by_type("IfcRelAssociatesMaterial")) == 0
assert len(self.file.by_type("IfcWallType")) == 2
assert len(self.file.by_type("IfcMaterialProfileSet")) == 2
def test_unassign_material_profile_set_usage_from_element(self): def test_unassign_material_profile_set_usage_from_element(self):
element_type = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType") element_type = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType")
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") element1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
ifcopenshell.api.run("type.assign_type", self.file, related_objects=[element], relating_type=element_type) element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
material = ifcopenshell.api.run("material.add_material", self.file, name="CON01") ifcopenshell.api.run(
ifcopenshell.api.run("material.assign_material", self.file, products=[element_type], type="IfcMaterialProfileSet") "type.assign_type", self.file, related_objects=[element1, element2], relating_type=element_type
ifcopenshell.api.run("material.assign_material", self.file, products=[element], type="IfcMaterialProfileSetUsage") )
ifcopenshell.api.run("material.unassign_material", self.file, product=element) ifcopenshell.api.run(
"material.assign_material", self.file, products=[element_type], type="IfcMaterialProfileSet"
)
ifcopenshell.api.run(
"material.assign_material", self.file, products=[element1, element2], type="IfcMaterialProfileSetUsage"
)
ifcopenshell.api.run("material.unassign_material", self.file, products=[element1, element2])
assert len(self.file.by_type("IfcRelAssociatesMaterial")) == 1 assert len(self.file.by_type("IfcRelAssociatesMaterial")) == 1
assert element_type.HasAssociations assert element_type.HasAssociations
assert len(self.file.by_type("IfcWallType")) == 1 assert len(self.file.by_type("IfcWallType")) == 1
assert len(self.file.by_type("IfcWall")) == 1 assert len(self.file.by_type("IfcWall")) == 2
assert len(self.file.by_type("IfcMaterialProfileSet")) == 1 assert len(self.file.by_type("IfcMaterialProfileSet")) == 1
assert len(self.file.by_type("IfcMaterialProfileSetUsage")) == 0 assert len(self.file.by_type("IfcMaterialProfileSetUsage")) == 0
def test_unassign_material_constituent_set_from_type(self): def test_unassign_material_constituent_set_from_type(self):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType") element1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType")
material = ifcopenshell.api.run("material.add_material", self.file, name="CON01") element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType")
ifcopenshell.api.run("material.assign_material", self.file, products=[element], type="IfcMaterialConstituentSet")
ifcopenshell.api.run("material.unassign_material", self.file, product=element)
assert len(self.file.by_type("IfcRelAssociatesMaterial")) == 0
assert len(self.file.by_type("IfcWallType")) == 1
assert len(self.file.by_type("IfcMaterialConstituentSet")) == 1
def test_unassign_element_material_list(self):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
material = ifcopenshell.api.run("material.add_material", self.file, name="CON01")
ifcopenshell.api.run( ifcopenshell.api.run(
"material.assign_material", self.file, products=[element], type="IfcMaterialList", material=material "material.assign_material", self.file, products=[element1, element2], type="IfcMaterialConstituentSet"
) )
ifcopenshell.api.run("material.unassign_material", self.file, product=element) element3 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWallType")
ifcopenshell.api.run(
"material.assign_material", self.file, products=[element3], type="IfcMaterialConstituentSet"
)
ifcopenshell.api.run("material.unassign_material", self.file, products=[element1, element2, element3])
assert len(self.file.by_type("IfcRelAssociatesMaterial")) == 0 assert len(self.file.by_type("IfcRelAssociatesMaterial")) == 0
assert len(self.file.by_type("IfcMaterialList")) == 1 assert len(self.file.by_type("IfcWallType")) == 3
assert len(self.file.by_type("IfcMaterial")) == 1 assert len(self.file.by_type("IfcMaterialConstituentSet")) == 2
@@ -174,3 +174,15 @@ class TestTemporarySupportForDeprecatedAPIArguments(test.bootstrap.IFC4):
) )
assert len(self.file.by_type("IfcRelAssociatesMaterial")) == 1 assert len(self.file.by_type("IfcRelAssociatesMaterial")) == 1
assert element.HasAssociations[0].RelatingMaterial == material assert element.HasAssociations[0].RelatingMaterial == material
@deprecation_check
def test_unassign_single_material(self):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
material = ifcopenshell.api.run("material.add_material", self.file, name="CON01")
ifcopenshell.api.run(
"material.assign_material", self.file, products=[element], type="IfcMaterial", material=material
)
ifcopenshell.api.run("material.unassign_material", self.file, product=element)
assert len(self.file.by_type("IfcRelAssociatesMaterial")) == 0
assert len(self.file.by_type("IfcWall")) == 1
assert len(self.file.by_type("IfcMaterial")) == 1