Fix #2898. You can now copy materials from the materials tab.

This commit is contained in:
Dion Moult
2023-03-26 19:04:32 +11:00
parent fb3e4016ec
commit e9a3630595
4 changed files with 104 additions and 77 deletions
@@ -21,65 +21,44 @@ import ifcopenshell.util.element
class Usecase:
def __init__(self, file, material=None, element=None):
"""Copies a material to an element
def __init__(self, file, material=None):
"""Copies a material
This convenience function exists to allow you to easily unassign any
existing material an element has, and assign a new material to it.
Essentially, it is a form a copy / pasting a material from one element
to another.
All material psets and styles are copied. The copied material is not
associated to any elements.
It's a bit out of place, and will likely be redesigned or removed in the
future. It's not recommended to use this function, and
ifcopenshell.api.material.assign_material should be used instead.
:param material: The IfcMaterial to assign to the element.
:param material: The IfcMaterial to copy
:type material: ifcopenshell.entity_instance.entity_instance
:param element: The IfcElement or IfcElementType to remove all previous
materials from and assign the new material to.
:type element: ifcopenshell.entity_instance.entity_instance
:return: None
:rtype: None
:return: The new copy of the material
:rtype: ifcopenshell.entity_instance.entity_instance
Example:
.. code:: python
concrete = ifcopenshell.api.run("material.add_material", model, name="CON01", category="concrete")
wood = ifcopenshell.api.run("material.add_material", model, name="TIM01", category="wood")
# Let's imagine a concrete bench made out of concrete.
bench = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcFurniture")
ifcopenshell.api.run("material.assign_material", model,
product=bench, type="IfcMaterial", material=concrete)
# And some street furniture made from wood.
street_furniture = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcFurniture")
ifcopenshell.api.run("material.assign_material", model,
product=street_furniture, type="IfcMaterial", material=wood)
# Let's copy the concrete over to the street furniture.
ifcopenshell.api.run("material.copy_material", model, material=wood, element=street_furniture)
# Let's duplicate the concrete material
concrete_copy = ifcopenshell.api.run("material.copy_material", model, material=concrete)
"""
self.file = file
self.settings = {"material": material, "element": element}
self.settings = {"material": material}
def execute(self):
ifcopenshell.api.run("material.unassign_material", self.file, product=self.settings["element"])
if self.settings["material"].is_a("IfcMaterial"):
ifcopenshell.api.run(
"material.assign_material",
self.file,
product=self.settings["element"],
type="IfcMaterial",
material=self.settings["material"],
)
# No other material type can be copied right now.
# 1. Material lists and constituents may have shape aspects and I
# haven't implemented it yet.
# 2. Material layer and profile sets implicitly define parametric
# geometry and we have no way of guaranteeing that this constraint is
# satisfied.
# 3. Material set usages follow an unofficial constraint that all
# instances must have a usage of their type's material set. We cannot
# guarantee that constraint.
new = ifcopenshell.util.element.copy(self.file, self.settings["material"])
for inverse in self.file.get_inverse(self.settings["material"]):
if inverse.is_a("IfcMaterialProperties"):
# Properties must not be shared between objects for convenience of authoring
inverse = ifcopenshell.util.element.copy(self.file, inverse)
properties = []
for pset in inverse.Properties:
properties.append(ifcopenshell.util.element.copy_deep(self.file, pset))
inverse.Properties = properties
inverse.Material = new
elif inverse.is_a("IfcMaterialDefinitionRepresentation"):
inverse = ifcopenshell.util.element.copy_deep(
self.file, inverse, exclude=["IfcRepresentationContext", "IfcMaterial"]
)
inverse.RepresentedMaterial = new
return new