diff --git a/src/bonsai/bonsai/bim/module/material/operator.py b/src/bonsai/bonsai/bim/module/material/operator.py
index 4cf66d9177..c6b92145b5 100644
--- a/src/bonsai/bonsai/bim/module/material/operator.py
+++ b/src/bonsai/bonsai/bim/module/material/operator.py
@@ -314,7 +314,7 @@ class RemoveConstituent(bpy.types.Operator, tool.Ifc.Operator):
if len(material_set.MaterialConstituents) == 1:
self.report({"ERROR"}, "At least one constituent must exist")
return {"CANCELLED"}
- ifcopenshell.api.run("material.remove_constituent", tool.Ifc.get(), constituent=constituent)
+ ifcopenshell.api.material.remove_constituent(tool.Ifc.get(), constituent=constituent)
class AddProfile(bpy.types.Operator, tool.Ifc.Operator):
@@ -349,7 +349,7 @@ class RemoveProfile(bpy.types.Operator, tool.Ifc.Operator):
if len(material_set.MaterialProfiles) == 1:
self.report({"ERROR"}, "At least one profile must exist")
return {"CANCELLED"}
- ifcopenshell.api.run("material.remove_profile", tool.Ifc.get(), profile=profile)
+ ifcopenshell.api.material.remove_profile(tool.Ifc.get(), profile=profile)
class AddLayer(bpy.types.Operator, tool.Ifc.Operator):
@@ -410,7 +410,7 @@ class RemoveLayer(bpy.types.Operator, tool.Ifc.Operator):
if len(material_set.MaterialLayers) == 1:
self.report({"ERROR"}, "At least one layer must exist")
return {"CANCELLED"}
- ifcopenshell.api.run("material.remove_layer", tool.Ifc.get(), layer=layer)
+ ifcopenshell.api.material.remove_layer(tool.Ifc.get(), layer=layer)
for material_set in material_sets:
slab.DumbSlabPlaner().regenerate_from_layer_set(material_set)
wall.DumbWallPlaner().regenerate_from_layer_set(material_set)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/material/remove_constituent.py b/src/ifcopenshell-python/ifcopenshell/api/material/remove_constituent.py
index 7f6bd4d6a9..7521c48a15 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/material/remove_constituent.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/material/remove_constituent.py
@@ -18,16 +18,16 @@
import ifcopenshell
-def remove_constituent(file: ifcopenshell.file, constituent: ifcopenshell.entity_instance) -> None:
+def remove_constituent(
+ file: ifcopenshell.file, constituent: ifcopenshell.entity_instance, should_remove_material: bool = False
+) -> None:
"""Removes a constituent from a constituent set
Note that it is invalid to have zero items in a set, so you should leave
at least one constituent to ensure a valid IFC dataset.
:param constituent: The IfcMaterialConstituent entity you want to remove
- :type constituent: ifcopenshell.entity_instance
- :return: None
- :rtype: None
+ :param should_remove_material: If true, materials with no users will be removed
Example:
@@ -51,6 +51,7 @@ def remove_constituent(file: ifcopenshell.file, constituent: ifcopenshell.entity
# invalid.
ifcopenshell.api.material.remove_constituent(model, constituent=glazing)
"""
- settings = {"constituent": constituent}
-
- file.remove(settings["constituent"])
+ material = layer.Material
+ file.remove(constituent)
+ if material and should_remove_material:
+ ifcopenshell.util.element.remove_deep2(file, subelement)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/material/remove_layer.py b/src/ifcopenshell-python/ifcopenshell/api/material/remove_layer.py
index 8f3a0f9450..7055beaf26 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/material/remove_layer.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/material/remove_layer.py
@@ -15,19 +15,19 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with IfcOpenShell. If not, see .
-import ifcopenshell
+import ifcopenshell.util.element
-def remove_layer(file: ifcopenshell.file, layer: ifcopenshell.entity_instance) -> None:
+def remove_layer(
+ file: ifcopenshell.file, layer: ifcopenshell.entity_instance, should_remove_material: bool = False
+) -> None:
"""Removes a layer from a layer set
Note that it is invalid to have zero items in a set, so you should leave
at least one layer to ensure a valid IFC dataset.
:param layer: The IfcMaterialLayer entity you want to remove
- :type layer: ifcopenshell.entity_instance
- :return: None
- :rtype: None
+ :param should_remove_material: If true, materials with no users will be removed
Example:
@@ -54,6 +54,7 @@ def remove_layer(file: ifcopenshell.file, layer: ifcopenshell.entity_instance) -
# one one side such as to line a services riser.
ifcopenshell.api.material.remove_layer(model, layer=layer3)
"""
- settings = {"layer": layer}
-
- file.remove(settings["layer"])
+ material = layer.Material
+ file.remove(layer)
+ if material and should_remove_material:
+ ifcopenshell.util.element.remove_deep2(file, subelement)
diff --git a/src/ifcopenshell-python/ifcopenshell/api/material/remove_profile.py b/src/ifcopenshell-python/ifcopenshell/api/material/remove_profile.py
index 61c696d465..2883f21e41 100644
--- a/src/ifcopenshell-python/ifcopenshell/api/material/remove_profile.py
+++ b/src/ifcopenshell-python/ifcopenshell/api/material/remove_profile.py
@@ -17,20 +17,23 @@
# along with IfcOpenShell. If not, see .
-import ifcopenshell
import ifcopenshell.util.element
-def remove_profile(file: ifcopenshell.file, profile: ifcopenshell.entity_instance) -> None:
+def remove_profile(
+ file: ifcopenshell.file,
+ profile: ifcopenshell.entity_instance,
+ should_remove_profile_def: bool = False,
+ should_remove_material: bool = False,
+) -> None:
"""Removes a profile item from a profile set
Note that it is invalid to have zero items in a set, so you should leave
at least one profile to ensure a valid IFC dataset.
:param profile: The IfcMaterialProfile entity you want to remove
- :type profile: ifcopenshell.entity_instance
- :return: None
- :rtype: None
+ :param should_remove_profile_def: If true, profile defs with no users will be removed
+ :param should_remove_material: If true, materials with no users will be removed
Example:
@@ -64,12 +67,14 @@ def remove_profile(file: ifcopenshell.file, profile: ifcopenshell.entity_instanc
ifcopenshell.api.material.remove_profile(model, profile=weld_profile)
"""
- settings = {"profile": profile}
-
subelements = set()
- for attribute in settings["profile"]:
+ for attribute in profile:
if isinstance(attribute, ifcopenshell.entity_instance):
subelements.add(attribute)
- file.remove(settings["profile"])
+ file.remove(profile)
for subelement in subelements:
+ if subelement.is_a("IfcMaterial") and not should_remove_material:
+ continue
+ elif subelement.is_a("IfcProfileDef") and not should_remove_profile_def:
+ continue
ifcopenshell.util.element.remove_deep2(file, subelement)