Generate functions for all API usecases for better static code features. See #2693.

This commit is contained in:
Dion Moult
2024-05-06 14:35:39 +10:00
parent 10f894e2ea
commit d11ec67129
330 changed files with 13283 additions and 13751 deletions
@@ -15,3 +15,28 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
from .add_constituent import add_constituent
from .add_layer import add_layer
from .add_list_item import add_list_item
from .add_material import add_material
from .add_material_set import add_material_set
from .add_profile import add_profile
from .assign_material import assign_material
from .assign_profile import assign_profile
from .copy_material import copy_material
from .edit_assigned_material import edit_assigned_material
from .edit_constituent import edit_constituent
from .edit_layer import edit_layer
from .edit_layer_usage import edit_layer_usage
from .edit_material import edit_material
from .edit_profile import edit_profile
from .edit_profile_usage import edit_profile_usage
from .remove_constituent import remove_constituent
from .remove_layer import remove_layer
from .remove_list_item import remove_list_item
from .remove_material import remove_material
from .remove_material_set import remove_material_set
from .remove_profile import remove_profile
from .reorder_set_item import reorder_set_item
from .unassign_material import unassign_material
@@ -17,75 +17,72 @@
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
class Usecase:
def __init__(self, file, constituent_set=None, material=None):
"""Adds a new constituent to a constituent set
def add_constituent(file, constituent_set=None, material=None) -> None:
"""Adds a new constituent to a constituent set
A constituent describes how a portion of an object is made out of a
material whereas other portions of the object is made out of other
materials. For example, a window might be made out of an aluminium frame
and a glass panel. The aluminium used for the frame is one constituent
of the material, and glass would be another constituent. Another example
might be concrete, where one constituent might be cement, and another
constituent might be binder. In the case of the window, the constituent
is represented explicitly by the geometry of the window frame and the
geometry of the window panel. In the case of a concrete slab, the
constituents might be represented in terms of percentages.
A constituent describes how a portion of an object is made out of a
material whereas other portions of the object is made out of other
materials. For example, a window might be made out of an aluminium frame
and a glass panel. The aluminium used for the frame is one constituent
of the material, and glass would be another constituent. Another example
might be concrete, where one constituent might be cement, and another
constituent might be binder. In the case of the window, the constituent
is represented explicitly by the geometry of the window frame and the
geometry of the window panel. In the case of a concrete slab, the
constituents might be represented in terms of percentages.
Constituents are not available in IFC2X3.
Constituents are not available in IFC2X3.
:param constituent_set: The IfcMaterialConstituentSet that the
constituent is part of. The constituent set represents a group of
constituents. See ifcopenshell.api.material.add_material_set for
information on how to add a constituent set.
:type constituent_set: ifcopenshell.entity_instance
:param material: The IfcMaterial that the constituent is made out of.
:type material: ifcopenshell.entity_instance
:return: The newly created IfcMaterialConstituent
:rtype: ifcopenshell.entity_instance
:param constituent_set: The IfcMaterialConstituentSet that the
constituent is part of. The constituent set represents a group of
constituents. See ifcopenshell.api.material.add_material_set for
information on how to add a constituent set.
:type constituent_set: ifcopenshell.entity_instance
:param material: The IfcMaterial that the constituent is made out of.
:type material: ifcopenshell.entity_instance
:return: The newly created IfcMaterialConstituent
:rtype: ifcopenshell.entity_instance
Example:
Example:
.. code:: python
.. code:: python
# Let's imagine we have a window type that has an aluminium frame
# and a glass glazing panel. Notice we are assigning to the type
# only, as all occurrences of that type will automatically inherit
# the material.
window_type = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWindowType")
# Let's imagine we have a window type that has an aluminium frame
# and a glass glazing panel. Notice we are assigning to the type
# only, as all occurrences of that type will automatically inherit
# the material.
window_type = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWindowType")
# First, let's create a constituent set. This will later be assigned
# to our window element.
material_set = ifcopenshell.api.run("material.add_material_set", model,
name="Window", set_type="IfcMaterialConstituentSet")
# First, let's create a constituent set. This will later be assigned
# to our window element.
material_set = ifcopenshell.api.run("material.add_material_set", model,
name="Window", set_type="IfcMaterialConstituentSet")
# Let's create a few materials, it's important to also give them
# categories. This makes it easy for model recipients to do things
# like "show me everything made out of aluminium / concrete / steel
# / glass / etc". The IFC specification states a list of categories
# you can use.
aluminium = ifcopenshell.api.run("material.add_material", model, name="AL01", category="aluminium")
glass = ifcopenshell.api.run("material.add_material", model, name="GLZ01", category="glass")
# Let's create a few materials, it's important to also give them
# categories. This makes it easy for model recipients to do things
# like "show me everything made out of aluminium / concrete / steel
# / glass / etc". The IFC specification states a list of categories
# you can use.
aluminium = ifcopenshell.api.run("material.add_material", model, name="AL01", category="aluminium")
glass = ifcopenshell.api.run("material.add_material", model, name="GLZ01", category="glass")
# Now let's use those materials as two constituents in our set.
ifcopenshell.api.run("material.add_constituent", model,
constituent_set=material_set, material=aluminium)
ifcopenshell.api.run("material.add_constituent", model,
constituent_set=material_set, material=glass)
# Now let's use those materials as two constituents in our set.
ifcopenshell.api.run("material.add_constituent", model,
constituent_set=material_set, material=aluminium)
ifcopenshell.api.run("material.add_constituent", model,
constituent_set=material_set, material=glass)
# Great! Let's assign our material set to our window type.
# We're technically not done here, we might want to add geometry to
# our window too, but to keep this example simple, geometry is
# optional and it is enough to say that this window is made out of
# aluminium and glass.
ifcopenshell.api.run("material.assign_material", model, products=[window_type], material=material_set)
"""
self.file = file
self.settings = {"constituent_set": constituent_set, "material": material}
# Great! Let's assign our material set to our window type.
# We're technically not done here, we might want to add geometry to
# our window too, but to keep this example simple, geometry is
# optional and it is enough to say that this window is made out of
# aluminium and glass.
ifcopenshell.api.run("material.assign_material", model, products=[window_type], material=material_set)
"""
settings = {"constituent_set": constituent_set, "material": material}
def execute(self):
constituents = list(self.settings["constituent_set"].MaterialConstituents or [])
constituent = self.file.create_entity("IfcMaterialConstituent", **{"Material": self.settings["material"]})
constituents.append(constituent)
self.settings["constituent_set"].MaterialConstituents = constituents
return constituent
constituents = list(settings["constituent_set"].MaterialConstituents or [])
constituent = file.create_entity("IfcMaterialConstituent", **{"Material": settings["material"]})
constituents.append(constituent)
settings["constituent_set"].MaterialConstituents = constituents
return constituent
@@ -17,75 +17,70 @@
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
class Usecase:
def __init__(self, file, layer_set=None, material=None):
"""Adds a new layer to a layer set
def add_layer(file, layer_set=None, material=None) -> None:
"""Adds a new layer to a layer set
A layer represents a portion of material within a layered build up,
defined by a thickness. Typical layered construction includes walls and
slabs, where a wall might include a layer of finish, a layer of
structure, a layer of insulation, and so on. It is recommended to define
layered construction this way where it is unnecessary to define the
exact geometry of how the wall or slab will be built, and it will
instead be determined on site by a trade.
A layer represents a portion of material within a layered build up,
defined by a thickness. Typical layered construction includes walls and
slabs, where a wall might include a layer of finish, a layer of
structure, a layer of insulation, and so on. It is recommended to define
layered construction this way where it is unnecessary to define the
exact geometry of how the wall or slab will be built, and it will
instead be determined on site by a trade.
Layers are defined in a particular order and thickness, so that it is
clear which layer comes next.
Layers are defined in a particular order and thickness, so that it is
clear which layer comes next.
:param layer_set: The IfcMaterialLayerSet that the layer is part of. The
layer set represents a group of layers. See
ifcopenshell.api.material.add_material_set for more information on
how to add a layer set.
:type layer_set: ifcopenshell.entity_instance
:param material: The IfcMaterial that the layer is made out of.
:type material: ifcopenshell.entity_instance
:return: The newly created IfcMaterialLayer
:rtype: ifcopenshell.entity_instance
:param layer_set: The IfcMaterialLayerSet that the layer is part of. The
layer set represents a group of layers. See
ifcopenshell.api.material.add_material_set for more information on
how to add a layer set.
:type layer_set: ifcopenshell.entity_instance
:param material: The IfcMaterial that the layer is made out of.
:type material: ifcopenshell.entity_instance
:return: The newly created IfcMaterialLayer
:rtype: ifcopenshell.entity_instance
Example:
Example:
.. code:: python
.. code:: python
# Let's imagine we have a wall type that has two layers of
# gypsum with steel studs inside. Notice we are assigning to
# the type only, as all occurrences of that type will automatically
# inherit the material.
wall_type = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWallType", name="WAL01")
# Let's imagine we have a wall type that has two layers of
# gypsum with steel studs inside. Notice we are assigning to
# the type only, as all occurrences of that type will automatically
# inherit the material.
wall_type = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWallType", name="WAL01")
# First, let's create a material set. This will later be assigned
# to our wall type element.
material_set = ifcopenshell.api.run("material.add_material_set", model,
name="GYP-ST-GYP", set_type="IfcMaterialLayerSet")
# First, let's create a material set. This will later be assigned
# to our wall type element.
material_set = ifcopenshell.api.run("material.add_material_set", model,
name="GYP-ST-GYP", set_type="IfcMaterialLayerSet")
# Let's create a few materials, it's important to also give them
# categories. This makes it easy for model recipients to do things
# like "show me everything made out of aluminium / concrete / steel
# / glass / etc". The IFC specification states a list of categories
# you can use.
gypsum = ifcopenshell.api.run("material.add_material", model, name="PB01", category="gypsum")
steel = ifcopenshell.api.run("material.add_material", model, name="ST01", category="steel")
# Let's create a few materials, it's important to also give them
# categories. This makes it easy for model recipients to do things
# like "show me everything made out of aluminium / concrete / steel
# / glass / etc". The IFC specification states a list of categories
# you can use.
gypsum = ifcopenshell.api.run("material.add_material", model, name="PB01", category="gypsum")
steel = ifcopenshell.api.run("material.add_material", model, name="ST01", category="steel")
# Now let's use those materials as three layers in our set, such
# that the steel studs are sandwiched by the gypsum. Let's imagine
# we're setting the layer thickness in millimeters.
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=gypsum)
ifcopenshell.api.run("material.edit_layer", model, layer=layer, attributes={"LayerThickness": 13})
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=steel)
ifcopenshell.api.run("material.edit_layer", model, layer=layer, attributes={"LayerThickness": 92})
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=gypsum)
ifcopenshell.api.run("material.edit_layer", model, layer=layer, attributes={"LayerThickness": 13})
# Now let's use those materials as three layers in our set, such
# that the steel studs are sandwiched by the gypsum. Let's imagine
# we're setting the layer thickness in millimeters.
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=gypsum)
ifcopenshell.api.run("material.edit_layer", model, layer=layer, attributes={"LayerThickness": 13})
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=steel)
ifcopenshell.api.run("material.edit_layer", model, layer=layer, attributes={"LayerThickness": 92})
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=gypsum)
ifcopenshell.api.run("material.edit_layer", model, layer=layer, attributes={"LayerThickness": 13})
# Great! Let's assign our material set to our wall type.
ifcopenshell.api.run("material.assign_material", model, products=[wall_type], material=material_set)
"""
self.file = file
self.settings = {"layer_set": layer_set, "material": material}
# Great! Let's assign our material set to our wall type.
ifcopenshell.api.run("material.assign_material", model, products=[wall_type], material=material_set)
"""
settings = {"layer_set": layer_set, "material": material}
def execute(self):
layers = list(self.settings["layer_set"].MaterialLayers or [])
layer = self.file.create_entity(
"IfcMaterialLayer", **{"Material": self.settings["material"], "LayerThickness": 1.0}
)
layers.append(layer)
self.settings["layer_set"].MaterialLayers = layers
return layer
layers = list(settings["layer_set"].MaterialLayers or [])
layer = file.create_entity("IfcMaterialLayer", **{"Material": settings["material"], "LayerThickness": 1.0})
layers.append(layer)
settings["layer_set"].MaterialLayers = layers
return layer
@@ -19,70 +19,67 @@
import ifcopenshell
class Usecase:
def __init__(self, file, material_list=None, material=None):
"""Adds a new material in a list of materials
def add_list_item(file, material_list=None, material=None) -> None:
"""Adds a new material in a list of materials
In IFC2X3, if you wanted an object to have multiple materials (i.e. a
composite material) you would assign the object to a material list,
which would contain a list of materials. For example, a window might
have a list of 2 materials, one being aluminium for the frame, and
another being glass for the panel.
In IFC2X3, if you wanted an object to have multiple materials (i.e. a
composite material) you would assign the object to a material list,
which would contain a list of materials. For example, a window might
have a list of 2 materials, one being aluminium for the frame, and
another being glass for the panel.
In IFC4 and above, this is deprecated and should not be used. Instead,
you should use constituent sets instead, which achieve the same thing
but are more powerful as they allow you to define the properties of the
constituents too.
In IFC4 and above, this is deprecated and should not be used. Instead,
you should use constituent sets instead, which achieve the same thing
but are more powerful as they allow you to define the properties of the
constituents too.
However if you're stuck on IFC2X3, you have my condolences as well as
this function.
However if you're stuck on IFC2X3, you have my condolences as well as
this function.
:param material_list: The IfcMaterialList the material should be added
to.
:type material_list: ifcopenshell.entity_instance
:param material: The IfcMaterial to add to the list
:type material: ifcopenshell.entity_instance
:return: None
:rtype: None
:param material_list: The IfcMaterialList the material should be added
to.
:type material_list: ifcopenshell.entity_instance
:param material: The IfcMaterial to add to the list
:type material: ifcopenshell.entity_instance
:return: None
:rtype: None
Example:
Example:
.. code:: python
.. code:: python
# Let's imagine we have a window type that has an aluminium frame
# and a glass glazing panel. Notice we are assigning to the type
# only, as all occurrences of that type will automatically inherit
# the material.
window_type = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWindowType")
# Let's imagine we have a window type that has an aluminium frame
# and a glass glazing panel. Notice we are assigning to the type
# only, as all occurrences of that type will automatically inherit
# the material.
window_type = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWindowType")
# First, let's create a list. This will later be assigned to our
# window element.
material_set = ifcopenshell.api.run("material.add_material_set", model,
name="Window", set_type="IfcMaterialList")
# First, let's create a list. This will later be assigned to our
# window element.
material_set = ifcopenshell.api.run("material.add_material_set", model,
name="Window", set_type="IfcMaterialList")
# Let's create a few materials, it's important to also give them
# categories. This makes it easy for model recipients to do things
# like "show me everything made out of aluminium / concrete / steel
# / glass / etc". The IFC specification states a list of categories
# you can use.
aluminium = ifcopenshell.api.run("material.add_material", model, name="AL01", category="aluminium")
glass = ifcopenshell.api.run("material.add_material", model, name="GLZ01", category="glass")
# Let's create a few materials, it's important to also give them
# categories. This makes it easy for model recipients to do things
# like "show me everything made out of aluminium / concrete / steel
# / glass / etc". The IFC specification states a list of categories
# you can use.
aluminium = ifcopenshell.api.run("material.add_material", model, name="AL01", category="aluminium")
glass = ifcopenshell.api.run("material.add_material", model, name="GLZ01", category="glass")
# Now let's use those materials as two items in our list.
ifcopenshell.api.run("material.add_list_item", model, material_list=material_set, material=aluminium)
ifcopenshell.api.run("material.add_list_item", model, material_list=material_set, material=glass)
# Now let's use those materials as two items in our list.
ifcopenshell.api.run("material.add_list_item", model, material_list=material_set, material=aluminium)
ifcopenshell.api.run("material.add_list_item", model, material_list=material_set, material=glass)
# Great! Let's assign our material set to our window type.
# We're technically not done here, we might want to add geometry to
# our window too, but to keep this example simple, geometry is
# optional and it is enough to say that this window is made out of
# aluminium and glass.
ifcopenshell.api.run("material.assign_material", model, products=[window_type], material=material_set)
"""
self.file = file
self.settings = {"material_list": material_list, "material": material}
# Great! Let's assign our material set to our window type.
# We're technically not done here, we might want to add geometry to
# our window too, but to keep this example simple, geometry is
# optional and it is enough to say that this window is made out of
# aluminium and glass.
ifcopenshell.api.run("material.assign_material", model, products=[window_type], material=material_set)
"""
settings = {"material_list": material_list, "material": material}
def execute(self):
materials = list(self.settings["material_list"].Materials or [])
materials.append(self.settings["material"])
self.settings["material_list"].Materials = materials
materials = list(settings["material_list"].Materials or [])
materials.append(settings["material"])
settings["material_list"].Materials = materials
@@ -17,64 +17,61 @@
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
class Usecase:
def __init__(self, file, name=None, category=None):
"""Adds a new material
def add_material(file, name=None, category=None) -> None:
"""Adds a new material
A material in IFC represents a physical material, such as timber, steel,
concrete, aluminium, etc. It may also contain physical properties used
for structural or lighting simulation. Note that unlike the computer
graphics industry, a material by itself does not define any colour or
lighting information. Colours in IFC are known as "styles", and an IFC
material may or may not have any style information associated with it.
See ifcopenshell.api.style for more information.
A material in IFC represents a physical material, such as timber, steel,
concrete, aluminium, etc. It may also contain physical properties used
for structural or lighting simulation. Note that unlike the computer
graphics industry, a material by itself does not define any colour or
lighting information. Colours in IFC are known as "styles", and an IFC
material may or may not have any style information associated with it.
See ifcopenshell.api.style for more information.
A material is typically given a code name which is used by architects in
elevations and details when tagging finishes. Materials are also useful
to structural engineers in specifying the exact types of concrete and
steel to be used in structural simulations.
A material is typically given a code name which is used by architects in
elevations and details when tagging finishes. Materials are also useful
to structural engineers in specifying the exact types of concrete and
steel to be used in structural simulations.
In addition, materials can belong to a category. Specifying this
category is critical to allow model recipients to make simple queries
like "show me all concrete / steel" elements in the model. Without
standardised category naming of all materials, this type of query
becomes a bespoke and inefficient task. A list of categories are:
'concrete', 'steel', 'aluminium', 'block', 'brick', 'stone', 'wood',
'glass', 'gypsum', 'plastic', and 'earth'. The user is allowed to
specify their own category instead if none of these categories are
appropriate.
In addition, materials can belong to a category. Specifying this
category is critical to allow model recipients to make simple queries
like "show me all concrete / steel" elements in the model. Without
standardised category naming of all materials, this type of query
becomes a bespoke and inefficient task. A list of categories are:
'concrete', 'steel', 'aluminium', 'block', 'brick', 'stone', 'wood',
'glass', 'gypsum', 'plastic', and 'earth'. The user is allowed to
specify their own category instead if none of these categories are
appropriate.
Note that categories are not available in IFC2X3. This shortcoming is
one of the big reasons projects should upgrade to IFC4.
Note that categories are not available in IFC2X3. This shortcoming is
one of the big reasons projects should upgrade to IFC4.
:param name: The name of the material, typically tagged in a finishes
drawing or schedule.
:type name: str
:param category: The category of the material.
:type category: str, optional
:return: The newly created IfcMaterial
:rtype: ifcopenshell.entity_instance
:param name: The name of the material, typically tagged in a finishes
drawing or schedule.
:type name: str
:param category: The category of the material.
:type category: str, optional
:return: The newly created IfcMaterial
:rtype: ifcopenshell.entity_instance
Example:
Example:
.. code:: python
.. code:: python
# Let's create two materials with their respective categories
concrete = ifcopenshell.api.run("material.add_material", model, name="CON01", category="concrete")
steel = ifcopenshell.api.run("material.add_material", model, name="ST01", category="steel")
# Let's create two materials with their respective categories
concrete = ifcopenshell.api.run("material.add_material", model, name="CON01", category="concrete")
steel = ifcopenshell.api.run("material.add_material", model, name="ST01", category="steel")
# Let's imagine an urban concrete bench which is purely made out of concrete
concrete_bench = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcFurnitureType")
# Let's imagine an urban concrete bench which is purely made out of concrete
concrete_bench = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcFurnitureType")
# Assign the concrete material to that bench. Note that no colour
# "Style" has been specified.
ifcopenshell.api.run("material.assign_material", model, products=[concrete_bench], material=concrete)
"""
self.file = file
self.settings = {"name": name or "Unnamed", "category": category}
# Assign the concrete material to that bench. Note that no colour
# "Style" has been specified.
ifcopenshell.api.run("material.assign_material", model, products=[concrete_bench], material=concrete)
"""
settings = {"name": name or "Unnamed", "category": category}
def execute(self):
material = self.file.create_entity("IfcMaterial", **{"Name": self.settings["name"] or "Unnamed"})
if self.settings["category"]:
material.Category = self.settings["category"]
return material
material = file.create_entity("IfcMaterial", **{"Name": settings["name"] or "Unnamed"})
if settings["category"]:
material.Category = settings["category"]
return material
@@ -17,97 +17,94 @@
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
class Usecase:
def __init__(self, file, name="Unnamed", set_type="IfcMaterialConstituentSet"):
"""Adds a new material set
def add_material_set(file, name="Unnamed", set_type="IfcMaterialConstituentSet") -> None:
"""Adds a new material set
IFC allows you to state that objects are made out of multiple materials.
These are known generically as material sets, but may also be called
layered materials, composite materials, or other names in software.
IFC allows you to state that objects are made out of multiple materials.
These are known generically as material sets, but may also be called
layered materials, composite materials, or other names in software.
There are three types of material sets:
There are three types of material sets:
- A layer set, used for layered construction such as walls, where the
element is parametrically made out of extruded layers, each layer
having a thickness defined. Even though this is known as a layer
"set" it is still recommended to use it for all standared layered
construction as it describes the intent of the element to be layered
construction and thus can be used for parametric editing.
- A profile set, used for profiled construction such as beams or
columns, where the element is parametrically made out of one or more
extruded profiles, where each profile may be parametric from a
standard section (e.g. standardised steel profile) or an arbitrary
shape (e.g. cold rolled sections, or skirtings, moldings, etc). Note
that even though this is called a profile "set", it should still be
used even if there is only a single profile. This is not available in
IFC2X3.
- A constituent set, used for arbitrary composite construction where
the object is made out of multiple materials. The constituents may be
explicitly defined via a shape, such as a window where the frame
geometry is made from one material and the panel geometry is made
from another material. Alternatively, the constituents may be
represented in terms of percentages, such as in mixtures like
concrete where there might be a percentage constituent of cement and
another percentage constituent of binder. This is not available in
IFC2X3.
- A layer set, used for layered construction such as walls, where the
element is parametrically made out of extruded layers, each layer
having a thickness defined. Even though this is known as a layer
"set" it is still recommended to use it for all standared layered
construction as it describes the intent of the element to be layered
construction and thus can be used for parametric editing.
- A profile set, used for profiled construction such as beams or
columns, where the element is parametrically made out of one or more
extruded profiles, where each profile may be parametric from a
standard section (e.g. standardised steel profile) or an arbitrary
shape (e.g. cold rolled sections, or skirtings, moldings, etc). Note
that even though this is called a profile "set", it should still be
used even if there is only a single profile. This is not available in
IFC2X3.
- A constituent set, used for arbitrary composite construction where
the object is made out of multiple materials. The constituents may be
explicitly defined via a shape, such as a window where the frame
geometry is made from one material and the panel geometry is made
from another material. Alternatively, the constituents may be
represented in terms of percentages, such as in mixtures like
concrete where there might be a percentage constituent of cement and
another percentage constituent of binder. This is not available in
IFC2X3.
There is also a fourth material set known as a material list, which is a
legacy type of set used by IFC2X3. It should not be used on IFC4 and
above, and constituent sets should be used instead.
There is also a fourth material set known as a material list, which is a
legacy type of set used by IFC2X3. It should not be used on IFC4 and
above, and constituent sets should be used instead.
:param name: The name of the material set, which may be purely
descriptive or annotated in drawings. Defaults to "Unnamed".
:type name: str, optional
:param set_type: What type of set you want to create, chosen from
IfcMaterialLayerSet, IfcMaterialProfileSet,
IfcMaterialConstituentSet, or IfcMaterialList. Defaults to
IfcMaterialConstituentSet.
:type set_type: str, optional
:return: The newly created material set element
:rtype: ifcopenshell.entity_instance
:param name: The name of the material set, which may be purely
descriptive or annotated in drawings. Defaults to "Unnamed".
:type name: str, optional
:param set_type: What type of set you want to create, chosen from
IfcMaterialLayerSet, IfcMaterialProfileSet,
IfcMaterialConstituentSet, or IfcMaterialList. Defaults to
IfcMaterialConstituentSet.
:type set_type: str, optional
:return: The newly created material set element
:rtype: ifcopenshell.entity_instance
Example:
Example:
.. code:: python
.. code:: python
# Let's imagine we have a wall type that has two layers of
# gypsum with steel studs inside. Notice we are assigning to
# the type only, as all occurrences of that type will automatically
# inherit the material.
wall_type = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWallType", name="WAL01")
# Let's imagine we have a wall type that has two layers of
# gypsum with steel studs inside. Notice we are assigning to
# the type only, as all occurrences of that type will automatically
# inherit the material.
wall_type = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWallType", name="WAL01")
# First, let's create a material set. This will later be assigned
# to our wall type element.
material_set = ifcopenshell.api.run("material.add_material_set", model,
name="GYP-ST-GYP", set_type="IfcMaterialLayerSet")
# First, let's create a material set. This will later be assigned
# to our wall type element.
material_set = ifcopenshell.api.run("material.add_material_set", model,
name="GYP-ST-GYP", set_type="IfcMaterialLayerSet")
# Let's create a few materials, it's important to also give them
# categories. This makes it easy for model recipients to do things
# like "show me everything made out of aluminium / concrete / steel
# / glass / etc". The IFC specification states a list of categories
# you can use.
gypsum = ifcopenshell.api.run("material.add_material", model, name="PB01", category="gypsum")
steel = ifcopenshell.api.run("material.add_material", model, name="ST01", category="steel")
# Let's create a few materials, it's important to also give them
# categories. This makes it easy for model recipients to do things
# like "show me everything made out of aluminium / concrete / steel
# / glass / etc". The IFC specification states a list of categories
# you can use.
gypsum = ifcopenshell.api.run("material.add_material", model, name="PB01", category="gypsum")
steel = ifcopenshell.api.run("material.add_material", model, name="ST01", category="steel")
# Now let's use those materials as three layers in our set, such
# that the steel studs are sandwiched by the gypsum. Let's imagine
# we're setting the layer thickness in millimeters.
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=gypsum)
ifcopenshell.api.run("material.edit_layer", model, layer=layer, attributes={"LayerThickness": 13})
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=steel)
ifcopenshell.api.run("material.edit_layer", model, layer=layer, attributes={"LayerThickness": 92})
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=gypsum)
ifcopenshell.api.run("material.edit_layer", model, layer=layer, attributes={"LayerThickness": 13})
# Now let's use those materials as three layers in our set, such
# that the steel studs are sandwiched by the gypsum. Let's imagine
# we're setting the layer thickness in millimeters.
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=gypsum)
ifcopenshell.api.run("material.edit_layer", model, layer=layer, attributes={"LayerThickness": 13})
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=steel)
ifcopenshell.api.run("material.edit_layer", model, layer=layer, attributes={"LayerThickness": 92})
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=gypsum)
ifcopenshell.api.run("material.edit_layer", model, layer=layer, attributes={"LayerThickness": 13})
# Great! Let's assign our material set to our wall type.
ifcopenshell.api.run("material.assign_material", model, products=[wall_type], material=material_set)
"""
self.file = file
self.settings = {"name": name or "Unnamed", "set_type": set_type or "IfcMaterialConstituentSet"}
# Great! Let's assign our material set to our wall type.
ifcopenshell.api.run("material.assign_material", model, products=[wall_type], material=material_set)
"""
settings = {"name": name or "Unnamed", "set_type": set_type or "IfcMaterialConstituentSet"}
def execute(self):
if self.settings["set_type"] == "IfcMaterialLayerSet":
return self.file.create_entity("IfcMaterialLayerSet", LayerSetName=self.settings["name"] or "Unnamed")
elif self.settings["set_type"] == "IfcMaterialList":
return self.file.create_entity("IfcMaterialList")
return self.file.create_entity(self.settings["set_type"], Name=self.settings["name"] or "Unnamed")
if settings["set_type"] == "IfcMaterialLayerSet":
return file.create_entity("IfcMaterialLayerSet", LayerSetName=settings["name"] or "Unnamed")
elif settings["set_type"] == "IfcMaterialList":
return file.create_entity("IfcMaterialList")
return file.create_entity(settings["set_type"], Name=settings["name"] or "Unnamed")
@@ -19,86 +19,82 @@ import ifcopenshell
from typing import Optional
class Usecase:
def __init__(
self,
file: ifcopenshell.file,
profile_set: ifcopenshell.entity_instance,
material: Optional[ifcopenshell.entity_instance] = None,
profile: Optional[ifcopenshell.entity_instance] = None,
):
"""Add a new profile item to a profile set
def add_profile(
file: ifcopenshell.file,
profile_set: ifcopenshell.entity_instance,
material: Optional[ifcopenshell.entity_instance] = None,
profile: Optional[ifcopenshell.entity_instance] = None,
) -> ifcopenshell.entity_instance:
"""Add a new profile item to a profile set
A profile item in a profile set represents an extruded 2D profile curve
that is extruded along the axis of the element. Most commonly there will
only be a single profile item in a profile set. For example, a beam will
have a material profile set containing a single profile item, which may
have a steel material and a I-beam shaped profile curve.
A profile item in a profile set represents an extruded 2D profile curve
that is extruded along the axis of the element. Most commonly there will
only be a single profile item in a profile set. For example, a beam will
have a material profile set containing a single profile item, which may
have a steel material and a I-beam shaped profile curve.
Note that the "profile item" represents a single extrusion in the
profile set, whereas the "profile curve" represents a 2D curve used by a
"profile item".
Note that the "profile item" represents a single extrusion in the
profile set, whereas the "profile curve" represents a 2D curve used by a
"profile item".
In some cases, a profiled element (i.e. beam, column) may be a composite
beam or column and include multiple extrusions. This is rare. The order
of the profiles does not matter.
In some cases, a profiled element (i.e. beam, column) may be a composite
beam or column and include multiple extrusions. This is rare. The order
of the profiles does not matter.
:param profile_set: The IfcMaterialProfileSet that the profile is part of. The
profile set represents a group of profile items. See
ifcopenshell.api.material.add_material_set for more information on
how to add a profile set.
:type profile_set: ifcopenshell.entity_instance
:param material: The IfcMaterial that the profile item is made out of.
:type material: ifcopenshell.entity_instance, optional
:param profile: The IfcProfileDef that represents the 2D cross section
of the the profile item.
:type profile: ifcopenshell.entity_instance, optional
:return: The newly created IfcMaterialProfile
:rtype: ifcopenshell.entity_instance
:param profile_set: The IfcMaterialProfileSet that the profile is part of. The
profile set represents a group of profile items. See
ifcopenshell.api.material.add_material_set for more information on
how to add a profile set.
:type profile_set: ifcopenshell.entity_instance
:param material: The IfcMaterial that the profile item is made out of.
:type material: ifcopenshell.entity_instance, optional
:param profile: The IfcProfileDef that represents the 2D cross section
of the the profile item.
:type profile: ifcopenshell.entity_instance, optional
:return: The newly created IfcMaterialProfile
:rtype: ifcopenshell.entity_instance
Example:
Example:
.. code:: python
.. code:: python
# Let's imagine we have a steel I-beam. Notice we are assigning to
# the type only, as all occurrences of that type will automatically
# inherit the material.
beam_type = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcBeamType", name="B1")
# Let's imagine we have a steel I-beam. Notice we are assigning to
# the type only, as all occurrences of that type will automatically
# inherit the material.
beam_type = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcBeamType", name="B1")
# First, let's create a material set. This will later be assigned
# to our beam type element.
material_set = ifcopenshell.api.run("material.add_profile_set", model,
name="B1", set_type="IfcMaterialProfileSet")
# First, let's create a material set. This will later be assigned
# to our beam type element.
material_set = ifcopenshell.api.run("material.add_profile_set", model,
name="B1", set_type="IfcMaterialProfileSet")
# Create a steel material.
steel = ifcopenshell.api.run("material.add_material", model, name="ST01", category="steel")
# Create a steel material.
steel = ifcopenshell.api.run("material.add_material", model, name="ST01", category="steel")
# Create an I-beam profile curve. Notice how we name our profiles
# based on standardised steel profile names.
hea100 = self.file.create_entity(
"IfcIShapeProfileDef", ProfileName="HEA100", ProfileType="AREA",
OverallWidth=100, OverallDepth=96, WebThickness=5, FlangeThickness=8, FilletRadius=12,
)
# Create an I-beam profile curve. Notice how we name our profiles
# based on standardised steel profile names.
hea100 = file.create_entity(
"IfcIShapeProfileDef", ProfileName="HEA100", ProfileType="AREA",
OverallWidth=100, OverallDepth=96, WebThickness=5, FlangeThickness=8, FilletRadius=12,
)
# Define that steel material and cross section as a single profile
# item. If this were a composite beam, we might add multiple profile
# items instead, but this is rarely the case in most construction.
ifcopenshell.api.run("material.add_profile", model,
profile_set=material_set, material=steel, profile=hea100)
# Define that steel material and cross section as a single profile
# item. If this were a composite beam, we might add multiple profile
# items instead, but this is rarely the case in most construction.
ifcopenshell.api.run("material.add_profile", model,
profile_set=material_set, material=steel, profile=hea100)
# Great! Let's assign our material set to our beam type.
ifcopenshell.api.run("material.assign_material", model, products=[beam_type], material=material_set)
"""
self.file = file
self.settings = {"profile_set": profile_set, "material": material, "profile": profile}
# Great! Let's assign our material set to our beam type.
ifcopenshell.api.run("material.assign_material", model, products=[beam_type], material=material_set)
"""
settings = {"profile_set": profile_set, "material": material, "profile": profile}
def execute(self) -> ifcopenshell.entity_instance:
profiles = list(self.settings["profile_set"].MaterialProfiles or [])
profile = self.file.create_entity("IfcMaterialProfile")
if self.settings["material"]:
profile.Material = self.settings["material"]
if self.settings["profile"]:
profile.Profile = self.settings["profile"]
profiles.append(profile)
self.settings["profile_set"].MaterialProfiles = profiles
return profile
profiles = list(settings["profile_set"].MaterialProfiles or [])
profile = file.create_entity("IfcMaterialProfile")
if settings["material"]:
profile.Material = settings["material"]
if settings["profile"]:
profile.Profile = settings["profile"]
profiles.append(profile)
settings["profile_set"].MaterialProfiles = profiles
return profile
@@ -23,133 +23,135 @@ import ifcopenshell.util.representation
from typing import Optional, Union
def assign_material(
file: ifcopenshell.file,
products: list[ifcopenshell.entity_instance],
type: str = "IfcMaterial",
material: Optional[ifcopenshell.entity_instance] = None,
) -> Union[ifcopenshell.entity_instance, list[ifcopenshell.entity_instance], None]:
"""Assigns a material to the list of products
Will unassign previously assigned material.
When a material is assigned to a product, it means that the product is
made out of that material. In its simplest form, a single material may
be assigned to a product, meaning that the entire product is made out of
that one material. Alternatively, a material set may be assigned to a
product, meaning that the product is made out of a set of materials.
There are three types of sets, including layered construction, profiled
materials, and arbitrary material constituents. See
ifcopenshell.api.material.add_material_set for details.
Materials are typically assigned to the element types rather than
individual occurrences of elements. Individual occurrences would then
inherit the material from the type.
If the type has a material set, then the geometry of the occurrences
must comply with the material set. For example, if the type has a
constituent set, then it is expected that all occurrences also inherit
the geometry of the type, which is made out of those constituents.
Alternatively, if the type has a layer set, then all occurrences must
have geometry that has a thickness equal to the sum of all layers. If a
type has a profile set, then all occurrences must has the same profile
extruded along its axis.
For layers and profiles assigned to types, the occurrences must be
assigned an IfcMaterialLayerSetUsage or an IfcMaterialProfileSetUsage.
This allows individual occurrences to override the layered or profiled
construction offset from a reference line.
:param products: The list of IfcProducts to assign the material or material set
to.
:type products: list[ifcopenshell.entity_instance]
:param type: Choose from "IfcMaterial", "IfcMaterialConstituentSet",
"IfcMaterialLayerSet", "IfcMaterialLayerSetUsage",
"IfcMaterialProfileSet", "IfcMaterialProfileSetUsage", or
"IfcMaterialList". Note that "Set Usages" may only be assigned to
occurrences, not types. Defaults to "IfcMaterial".
:type type: str
:param material: The IfcMaterial or material set you are assigning here.
If type is Usage then no need to provide `material`, it will be deduced
from the element type automatically.
:type material: ifcopenshell.entity_instance, optional
:return: IfcRelAssociatesMaterial entity
or a list of IfcRelAssociatesMaterial entities
(possible if `type` is Usage
and `products` require different Usages)
or `None` if `products` was empty list.
:rtype: Union[
ifcopenshell.entity_instance,
list[ifcopenshell.entity_instance], None]
Example:
.. code:: python
# Let's start with a simple concrete material
concrete = ifcopenshell.api.run("material.add_material", model, name="CON01", category="concrete")
# Let's imagine a concrete bench made out of a single concrete
# material. Let's assign it to the type.
bench_type = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcFurnitureType")
ifcopenshell.api.run("material.assign_material", model,
products=[bench_type], type="IfcMaterial", material=concrete)
# Let's imagine there are a two occurrences of this bench. It's not
# necessary to assign any material to these benches as they
# automatically inherit the material from the type.
bench1 = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcFurniture")
bench2 = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcFurniture")
ifcopenshell.api.run("type.assign_type", model, related_objects=[bench1], relating_type=bench_type)
ifcopenshell.api.run("type.assign_type", model, related_objects=[bench2], relating_type=bench_type)
# If we have a concrete wall, we should use a layer set. Again,
# let's start with a wall type, not occurrences.
wall_type = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWallType", name="WAL01")
# Even though there is only one layer in our layer set, we still use
# a layer set because it makes it clear that this is a layered
# construction. Let's say it's a 200mm thick concrete layer.
material_set = ifcopenshell.api.run("material.add_material_set", model,
name="CON200", set_type="IfcMaterialLayerSet")
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=steel)
ifcopenshell.api.run("material.edit_layer", model, layer=layer, attributes={"LayerThickness": 200})
# Our wall type now has the layer set assigned to it
ifcopenshell.api.run("material.assign_material", model,
products=[wall_type], type="IfcMaterialLayerSet", material=material_set)
# Let's imagine an occurrence of this wall type.
wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")
ifcopenshell.api.run("type.assign_type", model, related_objects=[wall], relating_type=wall_type)
# Our wall occurrence needs to have a "set usage" which describes
# how the layers relate to a reference line (typically a 2D line
# representing the extents of the wall). Usages are special since
# they automatically detect the inherited material set from the
# type. You'd write similar code for a profile set.
ifcopenshell.api.run("material.assign_material", model,
products=[wall], type="IfcMaterialLayerSetUsage")
# To be complete, let's create the wall's axis and body
# representation. Notice how the axis guides the walls "reference
# line" which determines where layers are extruded from, and the
# body has a thickness of 200mm, same as our total layer set
# thickness.
axis = ifcopenshell.api.run("geometry.add_axis_representation", model,
context=axis_context, axis=[(0.0, 0.0), (5000.0, 0.0)])
body = ifcopenshell.api.run("geometry.add_wall_representation", model,
context=body_context, length=5000, height=3000, thickness=200)
ifcopenshell.api.run("geometry.assign_representation", model, product=wall, representation=axis)
ifcopenshell.api.run("geometry.assign_representation", model, product=wall, representation=body)
ifcopenshell.api.run("geometry.edit_object_placement", model, product=wall)
"""
usecase = Usecase()
usecase.file = file
usecase.settings = {"products": products, "type": type, "material": material}
return usecase.execute()
class Usecase:
def __init__(
self,
file: ifcopenshell.file,
products: list[ifcopenshell.entity_instance],
type: str = "IfcMaterial",
material: Optional[ifcopenshell.entity_instance] = None,
):
"""Assigns a material to the list of products
Will unassign previously assigned material.
When a material is assigned to a product, it means that the product is
made out of that material. In its simplest form, a single material may
be assigned to a product, meaning that the entire product is made out of
that one material. Alternatively, a material set may be assigned to a
product, meaning that the product is made out of a set of materials.
There are three types of sets, including layered construction, profiled
materials, and arbitrary material constituents. See
ifcopenshell.api.material.add_material_set for details.
Materials are typically assigned to the element types rather than
individual occurrences of elements. Individual occurrences would then
inherit the material from the type.
If the type has a material set, then the geometry of the occurrences
must comply with the material set. For example, if the type has a
constituent set, then it is expected that all occurrences also inherit
the geometry of the type, which is made out of those constituents.
Alternatively, if the type has a layer set, then all occurrences must
have geometry that has a thickness equal to the sum of all layers. If a
type has a profile set, then all occurrences must has the same profile
extruded along its axis.
For layers and profiles assigned to types, the occurrences must be
assigned an IfcMaterialLayerSetUsage or an IfcMaterialProfileSetUsage.
This allows individual occurrences to override the layered or profiled
construction offset from a reference line.
:param products: The list of IfcProducts to assign the material or material set
to.
:type products: list[ifcopenshell.entity_instance]
:param type: Choose from "IfcMaterial", "IfcMaterialConstituentSet",
"IfcMaterialLayerSet", "IfcMaterialLayerSetUsage",
"IfcMaterialProfileSet", "IfcMaterialProfileSetUsage", or
"IfcMaterialList". Note that "Set Usages" may only be assigned to
occurrences, not types. Defaults to "IfcMaterial".
:type type: str
:param material: The IfcMaterial or material set you are assigning here.
If type is Usage then no need to provide `material`, it will be deduced
from the element type automatically.
:type material: ifcopenshell.entity_instance, optional
:return: IfcRelAssociatesMaterial entity
or a list of IfcRelAssociatesMaterial entities
(possible if `type` is Usage
and `products` require different Usages)
or `None` if `products` was empty list.
:rtype: Union[
ifcopenshell.entity_instance,
list[ifcopenshell.entity_instance], None]
Example:
.. code:: python
# Let's start with a simple concrete material
concrete = ifcopenshell.api.run("material.add_material", model, name="CON01", category="concrete")
# Let's imagine a concrete bench made out of a single concrete
# material. Let's assign it to the type.
bench_type = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcFurnitureType")
ifcopenshell.api.run("material.assign_material", model,
products=[bench_type], type="IfcMaterial", material=concrete)
# Let's imagine there are a two occurrences of this bench. It's not
# necessary to assign any material to these benches as they
# automatically inherit the material from the type.
bench1 = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcFurniture")
bench2 = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcFurniture")
ifcopenshell.api.run("type.assign_type", model, related_objects=[bench1], relating_type=bench_type)
ifcopenshell.api.run("type.assign_type", model, related_objects=[bench2], relating_type=bench_type)
# If we have a concrete wall, we should use a layer set. Again,
# let's start with a wall type, not occurrences.
wall_type = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWallType", name="WAL01")
# Even though there is only one layer in our layer set, we still use
# a layer set because it makes it clear that this is a layered
# construction. Let's say it's a 200mm thick concrete layer.
material_set = ifcopenshell.api.run("material.add_material_set", model,
name="CON200", set_type="IfcMaterialLayerSet")
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=steel)
ifcopenshell.api.run("material.edit_layer", model, layer=layer, attributes={"LayerThickness": 200})
# Our wall type now has the layer set assigned to it
ifcopenshell.api.run("material.assign_material", model,
products=[wall_type], type="IfcMaterialLayerSet", material=material_set)
# Let's imagine an occurrence of this wall type.
wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")
ifcopenshell.api.run("type.assign_type", model, related_objects=[wall], relating_type=wall_type)
# Our wall occurrence needs to have a "set usage" which describes
# how the layers relate to a reference line (typically a 2D line
# representing the extents of the wall). Usages are special since
# they automatically detect the inherited material set from the
# type. You'd write similar code for a profile set.
ifcopenshell.api.run("material.assign_material", model,
products=[wall], type="IfcMaterialLayerSetUsage")
# To be complete, let's create the wall's axis and body
# representation. Notice how the axis guides the walls "reference
# line" which determines where layers are extruded from, and the
# body has a thickness of 200mm, same as our total layer set
# thickness.
axis = ifcopenshell.api.run("geometry.add_axis_representation", model,
context=axis_context, axis=[(0.0, 0.0), (5000.0, 0.0)])
body = ifcopenshell.api.run("geometry.add_wall_representation", model,
context=body_context, length=5000, height=3000, thickness=200)
ifcopenshell.api.run("geometry.assign_representation", model, product=wall, representation=axis)
ifcopenshell.api.run("geometry.assign_representation", model, product=wall, representation=body)
ifcopenshell.api.run("geometry.edit_object_placement", model, product=wall)
"""
self.file = file
self.settings = {"products": products, "type": type, "material": material}
def execute(self) -> Union[ifcopenshell.entity_instance, list[ifcopenshell.entity_instance], None]:
def execute(self):
self.products: set[ifcopenshell.entity_instance] = set(self.settings["products"])
if not self.products:
return
@@ -19,78 +19,81 @@
import ifcopenshell.util.representation
def assign_profile(file, material_profile=None, profile=None) -> None:
"""Changes the profile curve of a material profile item in a profile set
In addition to changing the profile curve, it will also change the
profile curve used in any body representation extrusions.
:param material_profile: The IfcMaterialProfile to change the profile
curve of. See ifcopenshell.api.material.add_profile to see how to
create profiles.
:type material_profile: ifcopenshell.entity_instance
:param profile: The IfcProfileDef to set the profile item's curve to.
:type profile: ifcopenshell.entity_instance
:return: None
:rtype: None
Example:
.. code:: python
# Let's imagine we have a steel I-beam. Notice we are assigning to
# the type only, as all occurrences of that type will automatically
# inherit the material.
beam_type = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcBeamType", name="B1")
# First, let's create a material set. This will later be assigned
# to our beam type element.
material_set = ifcopenshell.api.run("material.add_profile_set", model,
name="B1", set_type="IfcMaterialProfileSet")
# Create a steel material.
steel = ifcopenshell.api.run("material.add_material", model, name="ST01", category="steel")
# Create an I-beam profile curve. Notice how we name our profiles
# based on standardised steel profile names.
hea100 = usecase.file.create_entity(
"IfcIShapeProfileDef", ProfileName="HEA100", ProfileType="AREA",
OverallWidth=100, OverallDepth=96, WebThickness=5, FlangeThickness=8, FilletRadius=12,
)
# Define that steel material and cross section as a single profile
# item. If this were a composite beam, we might add multiple profile
# items instead, but this is rarely the case in most construction.
profile_item = ifcopenshell.api.run("material.add_profile", model,
profile_set=material_set, material=steel, profile=hea100)
# Great! Let's assign our material set to our beam type.
ifcopenshell.api.run("material.assign_material", model, products=[beam_type], material=material_set)
# Let's create an occurrence of this beam.
beam = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcBeam", name="B1.01")
ifcopenshell.api.run("material.assign_material", model,
products=[beam], type="IfcMaterialProfileSetUsage")
# Let's give a 1000mm long beam body representation.
body = ifcopenshell.api.run("geometry.add_profile_representation",
context=body_context, profile=hea100, depth=1000)
ifcopenshell.api.run("geometry.assign_representation", model, product=beam, representation=body)
ifcopenshell.api.run("geometry.edit_object_placement", model, product=beam)
# Now let's change the profile to a HEA200 standard profile instead.
# This will automatically change the body representation that we
# just added as well to a HEA200 profile.
hea200 = usecase.file.create_entity(
"IfcIShapeProfileDef", ProfileName="HEA200", ProfileType="AREA",
OverallWidth=200, OverallDepth=190, WebThickness=6.5, FlangeThickness=10, FilletRadius=18,
)
ifcopenshell.api.run("material.assign_profile", model, material_profile=profile_item, profile=hea200)
"""
usecase = Usecase()
usecase.file = file
usecase.settings = {"material_profile": material_profile, "profile": profile}
return usecase.execute()
class Usecase:
def __init__(self, file, material_profile=None, profile=None):
"""Changes the profile curve of a material profile item in a profile set
In addition to changing the profile curve, it will also change the
profile curve used in any body representation extrusions.
:param material_profile: The IfcMaterialProfile to change the profile
curve of. See ifcopenshell.api.material.add_profile to see how to
create profiles.
:type material_profile: ifcopenshell.entity_instance
:param profile: The IfcProfileDef to set the profile item's curve to.
:type profile: ifcopenshell.entity_instance
:return: None
:rtype: None
Example:
.. code:: python
# Let's imagine we have a steel I-beam. Notice we are assigning to
# the type only, as all occurrences of that type will automatically
# inherit the material.
beam_type = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcBeamType", name="B1")
# First, let's create a material set. This will later be assigned
# to our beam type element.
material_set = ifcopenshell.api.run("material.add_profile_set", model,
name="B1", set_type="IfcMaterialProfileSet")
# Create a steel material.
steel = ifcopenshell.api.run("material.add_material", model, name="ST01", category="steel")
# Create an I-beam profile curve. Notice how we name our profiles
# based on standardised steel profile names.
hea100 = self.file.create_entity(
"IfcIShapeProfileDef", ProfileName="HEA100", ProfileType="AREA",
OverallWidth=100, OverallDepth=96, WebThickness=5, FlangeThickness=8, FilletRadius=12,
)
# Define that steel material and cross section as a single profile
# item. If this were a composite beam, we might add multiple profile
# items instead, but this is rarely the case in most construction.
profile_item = ifcopenshell.api.run("material.add_profile", model,
profile_set=material_set, material=steel, profile=hea100)
# Great! Let's assign our material set to our beam type.
ifcopenshell.api.run("material.assign_material", model, products=[beam_type], material=material_set)
# Let's create an occurrence of this beam.
beam = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcBeam", name="B1.01")
ifcopenshell.api.run("material.assign_material", model,
products=[beam], type="IfcMaterialProfileSetUsage")
# Let's give a 1000mm long beam body representation.
body = ifcopenshell.api.run("geometry.add_profile_representation",
context=body_context, profile=hea100, depth=1000)
ifcopenshell.api.run("geometry.assign_representation", model, product=beam, representation=body)
ifcopenshell.api.run("geometry.edit_object_placement", model, product=beam)
# Now let's change the profile to a HEA200 standard profile instead.
# This will automatically change the body representation that we
# just added as well to a HEA200 profile.
hea200 = self.file.create_entity(
"IfcIShapeProfileDef", ProfileName="HEA200", ProfileType="AREA",
OverallWidth=200, OverallDepth=190, WebThickness=6.5, FlangeThickness=10, FilletRadius=18,
)
ifcopenshell.api.run("material.assign_profile", model, material_profile=profile_item, profile=hea200)
"""
self.file = file
self.settings = {"material_profile": material_profile, "profile": profile}
def execute(self):
# TODO: handle composite profiles
old_profile = self.settings["material_profile"].Profile
@@ -20,45 +20,42 @@ import ifcopenshell
import ifcopenshell.util.element
class Usecase:
def __init__(self, file, material=None):
"""Copies a material
def copy_material(file, material=None) -> None:
"""Copies a material
All material psets and styles are copied. The copied material is not
associated to any elements.
All material psets and styles are copied. The copied material is not
associated to any elements.
:param material: The IfcMaterial to copy
:type material: ifcopenshell.entity_instance
:return: The new copy of the material
:rtype: ifcopenshell.entity_instance
:param material: The IfcMaterial to copy
:type material: ifcopenshell.entity_instance
:return: The new copy of the material
:rtype: ifcopenshell.entity_instance
Example:
Example:
.. code:: python
.. code:: python
concrete = ifcopenshell.api.run("material.add_material", model, name="CON01", category="concrete")
concrete = ifcopenshell.api.run("material.add_material", model, name="CON01", category="concrete")
# Let's duplicate the concrete material
concrete_copy = ifcopenshell.api.run("material.copy_material", model, material=concrete)
"""
self.file = file
self.settings = {"material": material}
# Let's duplicate the concrete material
concrete_copy = ifcopenshell.api.run("material.copy_material", model, material=concrete)
"""
settings = {"material": material}
def execute(self):
if self.settings["material"].is_a("IfcMaterial"):
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
if settings["material"].is_a("IfcMaterial"):
new = ifcopenshell.util.element.copy(file, settings["material"])
for inverse in file.get_inverse(settings["material"]):
if inverse.is_a("IfcMaterialProperties"):
# Properties must not be shared between objects for convenience of authoring
inverse = ifcopenshell.util.element.copy(file, inverse)
properties = []
for pset in inverse.Properties:
properties.append(ifcopenshell.util.element.copy_deep(file, pset))
inverse.Properties = properties
inverse.Material = new
elif inverse.is_a("IfcMaterialDefinitionRepresentation"):
inverse = ifcopenshell.util.element.copy_deep(
file, inverse, exclude=["IfcRepresentationContext", "IfcMaterial"]
)
inverse.RepresentedMaterial = new
return new
@@ -17,31 +17,28 @@
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
class Usecase:
def __init__(self, file, element=None, attributes=None):
"""Edits the attributes of an IfcMaterial
def edit_assigned_material(file, element=None, attributes=None) -> None:
"""Edits the attributes of an IfcMaterial
For more information about the attributes and data types of an
IfcMaterial, consult the IFC documentation.
For more information about the attributes and data types of an
IfcMaterial, consult the IFC documentation.
:param element: The IfcMaterial entity you want to edit
:type element: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
:type attributes: dict, optional
:return: None
:rtype: None
:param element: The IfcMaterial entity you want to edit
:type element: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
:type attributes: dict, optional
:return: None
:rtype: None
Example:
Example:
.. code:: python
.. code:: python
concrete = ifcopenshell.api.run("material.add_material", model, name="CON01", category="concrete")
ifcopenshell.api.run("material.edit_assigned_material", model,
element=concrete, attributes={"Description": "40MPA concrete with broom finish"})
"""
self.file = file
self.settings = {"element": element, "attributes": attributes or {}}
concrete = ifcopenshell.api.run("material.add_material", model, name="CON01", category="concrete")
ifcopenshell.api.run("material.edit_assigned_material", model,
element=concrete, attributes={"Description": "40MPA concrete with broom finish"})
"""
settings = {"element": element, "attributes": attributes or {}}
def execute(self):
for name, value in self.settings["attributes"].items():
setattr(self.settings["element"], name, value)
for name, value in settings["attributes"].items():
setattr(settings["element"], name, value)
@@ -17,52 +17,49 @@
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
class Usecase:
def __init__(self, file, constituent=None, attributes=None, material=None):
"""Edits the attributes of an IfcMaterialConstituent
def edit_constituent(file, constituent=None, attributes=None, material=None) -> None:
"""Edits the attributes of an IfcMaterialConstituent
For more information about the attributes and data types of an
IfcMaterialConstituent, consult the IFC documentation.
For more information about the attributes and data types of an
IfcMaterialConstituent, consult the IFC documentation.
:param constituent: The IfcMaterialConstituent entity you want to edit
:type constituent: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
:type attributes: dict, optional
:param material: The IfcMaterial entity you want to change the constituent to
:type material: ifcopenshell.entity_instance, optional
:return: None
:rtype: None
:param constituent: The IfcMaterialConstituent entity you want to edit
:type constituent: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
:type attributes: dict, optional
:param material: The IfcMaterial entity you want to change the constituent to
:type material: ifcopenshell.entity_instance, optional
:return: None
:rtype: None
Example:
Example:
.. code:: python
.. code:: python
# Let's add two materials
aluminium1 = ifcopenshell.api.run("material.add_material", model, name="AL01", category="aluminium")
aluminium2 = ifcopenshell.api.run("material.add_material", model, name="AL02", category="aluminium")
glass = ifcopenshell.api.run("material.add_material", model, name="GLZ01", category="glass")
# Let's add two materials
aluminium1 = ifcopenshell.api.run("material.add_material", model, name="AL01", category="aluminium")
aluminium2 = ifcopenshell.api.run("material.add_material", model, name="AL02", category="aluminium")
glass = ifcopenshell.api.run("material.add_material", model, name="GLZ01", category="glass")
material_set = ifcopenshell.api.run("material.add_material_set", model,
name="Window", set_type="IfcMaterialConstituentSet")
material_set = ifcopenshell.api.run("material.add_material_set", model,
name="Window", set_type="IfcMaterialConstituentSet")
# Set up two constituents, one for the frame and the other for the glazing.
framing = ifcopenshell.api.run("material.add_constituent", model,
constituent_set=material_set, material=aluminium1)
glazing = ifcopenshell.api.run("material.add_constituent", model,
constituent_set=material_set, material=glass)
# Set up two constituents, one for the frame and the other for the glazing.
framing = ifcopenshell.api.run("material.add_constituent", model,
constituent_set=material_set, material=aluminium1)
glazing = ifcopenshell.api.run("material.add_constituent", model,
constituent_set=material_set, material=glass)
# Let's make sure this constituent refers to the framing of the
# window and uses the second aluminium material instead.
ifcopenshell.api.run("material.edit_constituent", model,
constituent=framing, attributes={"Name": "Framing"}, material=aluminium2)
# Let's make sure this constituent refers to the framing of the
# window and uses the second aluminium material instead.
ifcopenshell.api.run("material.edit_constituent", model,
constituent=framing, attributes={"Name": "Framing"}, material=aluminium2)
ifcopenshell.api.run("material.edit_constituent", model,
constituent=constituent, attributes={"Name": "Glazing"})
"""
self.file = file
self.settings = {"constituent": constituent, "attributes": attributes or {}, "material": material}
ifcopenshell.api.run("material.edit_constituent", model,
constituent=constituent, attributes={"Name": "Glazing"})
"""
settings = {"constituent": constituent, "attributes": attributes or {}, "material": material}
def execute(self):
for name, value in self.settings["attributes"].items():
setattr(self.settings["constituent"], name, value)
self.settings["constituent"].Material = self.settings["material"]
for name, value in settings["attributes"].items():
setattr(settings["constituent"], name, value)
settings["constituent"].Material = settings["material"]
@@ -17,51 +17,48 @@
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
class Usecase:
def __init__(self, file, layer=None, attributes=None, material=None):
"""Edits the attributes of an IfcMaterialLayer
def edit_layer(file, layer=None, attributes=None, material=None) -> None:
"""Edits the attributes of an IfcMaterialLayer
For more information about the attributes and data types of an
IfcMaterialLayer, consult the IFC documentation.
For more information about the attributes and data types of an
IfcMaterialLayer, consult the IFC documentation.
:param layer: The IfcMaterialLayer entity you want to edit
:type layer: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
:type attributes: dict, optional
:param material: The IfcMaterial entity you want the layer to be made
from.
:type material: ifcopenshell.entity_instance, optional
:return: None
:rtype: None
:param layer: The IfcMaterialLayer entity you want to edit
:type layer: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
:type attributes: dict, optional
:param material: The IfcMaterial entity you want the layer to be made
from.
:type material: ifcopenshell.entity_instance, optional
:return: None
:rtype: None
Example:
Example:
.. code:: python
.. code:: python
# Let's create two materials typically used for steel stud partition
# walls with gypsum lining.
gypsum = ifcopenshell.api.run("material.add_material", model, name="PB01", category="gypsum")
steel = ifcopenshell.api.run("material.add_material", model, name="ST01", category="steel")
# Let's create two materials typically used for steel stud partition
# walls with gypsum lining.
gypsum = ifcopenshell.api.run("material.add_material", model, name="PB01", category="gypsum")
steel = ifcopenshell.api.run("material.add_material", model, name="ST01", category="steel")
# Create a material layer set to contain our layers.
material_set = ifcopenshell.api.run("material.add_material_set", model,
name="GYP-ST-GYP", set_type="IfcMaterialLayerSet")
# Create a material layer set to contain our layers.
material_set = ifcopenshell.api.run("material.add_material_set", model,
name="GYP-ST-GYP", set_type="IfcMaterialLayerSet")
# Now let's use those materials as three layers in our set, such
# that the steel studs are sandwiched by the gypsum. Let's imagine
# we're setting the layer thickness in millimeters.
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=gypsum)
ifcopenshell.api.run("material.edit_layer", model, layer=layer, attributes={"LayerThickness": 13})
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=steel)
ifcopenshell.api.run("material.edit_layer", model, layer=layer, attributes={"LayerThickness": 92})
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=gypsum)
ifcopenshell.api.run("material.edit_layer", model, layer=layer, attributes={"LayerThickness": 13})
"""
self.file = file
self.settings = {"layer": layer, "attributes": attributes or {}, "material": material}
# Now let's use those materials as three layers in our set, such
# that the steel studs are sandwiched by the gypsum. Let's imagine
# we're setting the layer thickness in millimeters.
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=gypsum)
ifcopenshell.api.run("material.edit_layer", model, layer=layer, attributes={"LayerThickness": 13})
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=steel)
ifcopenshell.api.run("material.edit_layer", model, layer=layer, attributes={"LayerThickness": 92})
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=gypsum)
ifcopenshell.api.run("material.edit_layer", model, layer=layer, attributes={"LayerThickness": 13})
"""
settings = {"layer": layer, "attributes": attributes or {}, "material": material}
def execute(self):
for name, value in self.settings["attributes"].items():
setattr(self.settings["layer"], name, value)
if self.settings["material"]:
self.settings["layer"].Material = self.settings["material"]
for name, value in settings["attributes"].items():
setattr(settings["layer"], name, value)
if settings["material"]:
settings["layer"].Material = settings["material"]
@@ -17,66 +17,63 @@
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
class Usecase:
def __init__(self, file, usage=None, attributes=None):
"""Edits the attributes of an IfcMaterialLayerSetUsage
def edit_layer_usage(file, usage=None, attributes=None) -> None:
"""Edits the attributes of an IfcMaterialLayerSetUsage
This is typically used to change the offset from the reference line to
the layers.
This is typically used to change the offset from the reference line to
the layers.
For more information about the attributes and data types of an
IfcMaterialLayerSetUsage, consult the IFC documentation.
For more information about the attributes and data types of an
IfcMaterialLayerSetUsage, consult the IFC documentation.
:param usage: The IfcMaterialLayerSetUsage entity you want to edit
:type usage: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
:type attributes: dict, optional
:return: None
:rtype: None
:param usage: The IfcMaterialLayerSetUsage entity you want to edit
:type usage: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
:type attributes: dict, optional
:return: None
:rtype: None
Example:
Example:
.. code:: python
.. code:: python
# Let's start with a simple concrete material
concrete = ifcopenshell.api.run("material.add_material", model, name="CON01", category="concrete")
# Let's start with a simple concrete material
concrete = ifcopenshell.api.run("material.add_material", model, name="CON01", category="concrete")
# If we have a concrete wall, we should use a layer set. Again,
# let's start with a wall type, not occurrences.
wall_type = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWallType", name="WAL01")
# If we have a concrete wall, we should use a layer set. Again,
# let's start with a wall type, not occurrences.
wall_type = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWallType", name="WAL01")
# Even though there is only one layer in our layer set, we still use
# a layer set because it makes it clear that this is a layered
# construction. Let's say it's a 200mm thick concrete layer.
material_set = ifcopenshell.api.run("material.add_material_set", model,
name="CON200", set_type="IfcMaterialLayerSet")
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=steel)
ifcopenshell.api.run("material.edit_layer", model, layer=layer, attributes={"LayerThickness": 200})
# Even though there is only one layer in our layer set, we still use
# a layer set because it makes it clear that this is a layered
# construction. Let's say it's a 200mm thick concrete layer.
material_set = ifcopenshell.api.run("material.add_material_set", model,
name="CON200", set_type="IfcMaterialLayerSet")
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=steel)
ifcopenshell.api.run("material.edit_layer", model, layer=layer, attributes={"LayerThickness": 200})
# Our wall type now has the layer set assigned to it
ifcopenshell.api.run("material.assign_material", model,
products=[wall_type], type="IfcMaterialLayerSet", material=material_set)
# Our wall type now has the layer set assigned to it
ifcopenshell.api.run("material.assign_material", model,
products=[wall_type], type="IfcMaterialLayerSet", material=material_set)
# Let's imagine an occurrence of this wall type.
wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")
ifcopenshell.api.run("type.assign_type", model, related_objects=[wall], relating_type=wall_type)
# Let's imagine an occurrence of this wall type.
wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")
ifcopenshell.api.run("type.assign_type", model, related_objects=[wall], relating_type=wall_type)
# Our wall occurrence needs to have a "set usage" which describes
# how the layers relate to a reference line (typically a 2D line
# representing the extents of the wall). Usages are special since
# they automatically detect the inherited material set from the
# type. You'd write similar code for a profile set.
rel = ifcopenshell.api.run("material.assign_material", model,
products=[wall], type="IfcMaterialLayerSetUsage")
# Our wall occurrence needs to have a "set usage" which describes
# how the layers relate to a reference line (typically a 2D line
# representing the extents of the wall). Usages are special since
# they automatically detect the inherited material set from the
# type. You'd write similar code for a profile set.
rel = ifcopenshell.api.run("material.assign_material", model,
products=[wall], type="IfcMaterialLayerSetUsage")
# Let's change the offset from the reference line to be 200mm
# instead of the default of 0mm.
ifcopenshell.api.run("material.edit_layer_usage", model,
usage=rel.RelatingMaterial, attributes={"OffsetFromReferenceLine": 200})
"""
self.file = file
self.settings = {"usage": usage, "attributes": attributes or {}}
# Let's change the offset from the reference line to be 200mm
# instead of the default of 0mm.
ifcopenshell.api.run("material.edit_layer_usage", model,
usage=rel.RelatingMaterial, attributes={"OffsetFromReferenceLine": 200})
"""
settings = {"usage": usage, "attributes": attributes or {}}
def execute(self):
for name, value in self.settings["attributes"].items():
setattr(self.settings["usage"], name, value)
for name, value in settings["attributes"].items():
setattr(settings["usage"], name, value)
@@ -17,13 +17,10 @@
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
class Usecase:
def __init__(self, file, material=None, attributes=None):
"""Edits the attributes of an IfcMaterial"""
self.file = file
self.settings = {"material": material, "attributes": attributes or {}}
def edit_material(file, material=None, attributes=None) -> None:
"""Edits the attributes of an IfcMaterial"""
def execute(self):
for name, value in self.settings["attributes"].items():
setattr(self.settings["material"], name, value)
settings = {"material": material, "attributes": attributes or {}}
for name, value in settings["attributes"].items():
setattr(settings["material"], name, value)
@@ -17,72 +17,69 @@
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
class Usecase:
def __init__(self, file, profile=None, attributes=None, profile_def=None, material=None):
"""Edits the attributes of an IfcMaterialProfile
def edit_profile(file, profile=None, attributes=None, profile_def=None, material=None) -> None:
"""Edits the attributes of an IfcMaterialProfile
For more information about the attributes and data types of an
IfcMaterialProfile, consult the IFC documentation.
For more information about the attributes and data types of an
IfcMaterialProfile, consult the IFC documentation.
:param profile: The IfcMaterialProfile entity you want to edit
:type profile: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
:type attributes: dict, optional
:param profile_def: The IfcProfileDef entity the profile curve should be
extruded from.
:type profile_def: ifcopenshell.entity_instance, optional
:param material: The IfcMaterial entity you want to change the profile
to be made from.
:type material: ifcopenshell.entity_instance, optional
:return: None
:rtype: None
:param profile: The IfcMaterialProfile entity you want to edit
:type profile: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
:type attributes: dict, optional
:param profile_def: The IfcProfileDef entity the profile curve should be
extruded from.
:type profile_def: ifcopenshell.entity_instance, optional
:param material: The IfcMaterial entity you want to change the profile
to be made from.
:type material: ifcopenshell.entity_instance, optional
:return: None
:rtype: None
Example:
Example:
.. code:: python
.. code:: python
# Let's create a material set to store our profiles.
material_set = ifcopenshell.api.run("material.add_profile_set", model,
name="B1", set_type="IfcMaterialProfileSet")
# Let's create a material set to store our profiles.
material_set = ifcopenshell.api.run("material.add_profile_set", model,
name="B1", set_type="IfcMaterialProfileSet")
# Create a couple steel materials.
steel1 = ifcopenshell.api.run("material.add_material", model, name="ST01", category="steel")
steel2 = ifcopenshell.api.run("material.add_material", model, name="ST01", category="steel")
# Create a couple steel materials.
steel1 = ifcopenshell.api.run("material.add_material", model, name="ST01", category="steel")
steel2 = ifcopenshell.api.run("material.add_material", model, name="ST01", category="steel")
# Create some I-shaped profiles. Notice how we name our profiles based
# on standardised steel profile names.
hea100 = self.file.create_entity(
"IfcIShapeProfileDef", ProfileName="HEA100", ProfileType="AREA",
OverallWidth=100, OverallDepth=96, WebThickness=5, FlangeThickness=8, FilletRadius=12,
)
hea200 = self.file.create_entity(
"IfcIShapeProfileDef", ProfileName="HEA200", ProfileType="AREA",
OverallWidth=200, OverallDepth=190, WebThickness=6.5, FlangeThickness=10, FilletRadius=18,
)
# Create some I-shaped profiles. Notice how we name our profiles based
# on standardised steel profile names.
hea100 = file.create_entity(
"IfcIShapeProfileDef", ProfileName="HEA100", ProfileType="AREA",
OverallWidth=100, OverallDepth=96, WebThickness=5, FlangeThickness=8, FilletRadius=12,
)
hea200 = file.create_entity(
"IfcIShapeProfileDef", ProfileName="HEA200", ProfileType="AREA",
OverallWidth=200, OverallDepth=190, WebThickness=6.5, FlangeThickness=10, FilletRadius=18,
)
# Define that steel material and cross section as a single profile
# item. If this were a composite beam, we might add multiple profile
# items instead, but this is rarely the case in most construction.
profile_item = ifcopenshell.api.run("material.add_profile", model,
profile_set=material_set, material=steel1, profile=hea100)
# Define that steel material and cross section as a single profile
# item. If this were a composite beam, we might add multiple profile
# items instead, but this is rarely the case in most construction.
profile_item = ifcopenshell.api.run("material.add_profile", model,
profile_set=material_set, material=steel1, profile=hea100)
# Edit our profile item to use a HEA200 profile instead made out of
# another type of steel.
ifcopenshell.api.run("material.edit_profile", model,
profile=profile_item, profile_def=hea200, material=steel2)
"""
self.file = file
self.settings = {
"profile": profile,
"attributes": attributes or {},
"profile_def": profile_def,
"material": material,
}
# Edit our profile item to use a HEA200 profile instead made out of
# another type of steel.
ifcopenshell.api.run("material.edit_profile", model,
profile=profile_item, profile_def=hea200, material=steel2)
"""
settings = {
"profile": profile,
"attributes": attributes or {},
"profile_def": profile_def,
"material": material,
}
def execute(self):
for name, value in self.settings["attributes"].items():
setattr(self.settings["profile"], name, value)
if self.settings["material"]:
self.settings["profile"].Material = self.settings["material"]
if self.settings["profile_def"]:
self.settings["profile"].Profile = self.settings["profile_def"]
for name, value in settings["attributes"].items():
setattr(settings["profile"], name, value)
if settings["material"]:
settings["profile"].Material = settings["material"]
if settings["profile_def"]:
settings["profile"].Profile = settings["profile_def"]
@@ -20,79 +20,82 @@ import ifcopenshell.geom
import ifcopenshell.util.representation
def edit_profile_usage(file, usage=None, attributes=None) -> None:
"""Edits the attributes of an IfcMaterialProfileSetUsage
This is typically used to change the cardinal point of the profile.
The cardinal point represents whether the profile is extruded along the
center of the axis line, at a corner, at a shear center, at the bottom,
top, etc.
For more information about the attributes and data types of an
IfcMaterialProfileSetUsage, consult the IFC documentation.
:param usage: The IfcMaterialProfileSetUsage entity you want to edit
:type usage: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
:type attributes: dict, optional
:return: None
:rtype: None
Example:
.. code:: python
# Let's imagine we have a steel I-beam. Notice we are assigning to
# the type only, as all occurrences of that type will automatically
# inherit the material.
beam_type = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcBeamType", name="B1")
# First, let's create a material set. This will later be assigned
# to our beam type element.
material_set = ifcopenshell.api.run("material.add_profile_set", model,
name="B1", set_type="IfcMaterialProfileSet")
# Create a steel material.
steel = ifcopenshell.api.run("material.add_material", model, name="ST01", category="steel")
# Create an I-beam profile curve. Notice how we name our profiles
# based on standardised steel profile names.
hea100 = usecase.file.create_entity(
"IfcIShapeProfileDef", ProfileName="HEA100", ProfileType="AREA",
OverallWidth=100, OverallDepth=96, WebThickness=5, FlangeThickness=8, FilletRadius=12,
)
# Define that steel material and cross section as a single profile
# item. If this were a composite beam, we might add multiple profile
# items instead, but this is rarely the case in most construction.
profile_item = ifcopenshell.api.run("material.add_profile", model,
profile_set=material_set, material=steel, profile=hea100)
# Great! Let's assign our material set to our beam type.
ifcopenshell.api.run("material.assign_material", model, products=[beam_type], material=material_set)
# Let's create an occurrence of this beam.
beam = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcBeam", name="B1.01")
rel = ifcopenshell.api.run("material.assign_material", model,
products=[beam], type="IfcMaterialProfileSetUsage")
# Let's give a 1000mm long beam body representation.
body = ifcopenshell.api.run("geometry.add_profile_representation",
context=body_context, profile=hea100, depth=1000)
ifcopenshell.api.run("geometry.assign_representation", model, product=beam, representation=body)
ifcopenshell.api.run("geometry.edit_object_placement", model, product=beam)
# Let's change the cardinal point to be the top center of the axis
# line. This is represented by the number "8". Consult the IFC
# documentation for all the numbers you can use.
ifcopenshell.api.run("material.edit_profile_usage", model,
usage=rel.RelatingMaterial, attributes={"CardinalPoint": 8})
"""
usecase = Usecase()
usecase.file = file
usecase.settings = {"usage": usage, "attributes": attributes or {}}
return usecase.execute()
class Usecase:
def __init__(self, file, usage=None, attributes=None):
"""Edits the attributes of an IfcMaterialProfileSetUsage
This is typically used to change the cardinal point of the profile.
The cardinal point represents whether the profile is extruded along the
center of the axis line, at a corner, at a shear center, at the bottom,
top, etc.
For more information about the attributes and data types of an
IfcMaterialProfileSetUsage, consult the IFC documentation.
:param usage: The IfcMaterialProfileSetUsage entity you want to edit
:type usage: ifcopenshell.entity_instance
:param attributes: a dictionary of attribute names and values.
:type attributes: dict, optional
:return: None
:rtype: None
Example:
.. code:: python
# Let's imagine we have a steel I-beam. Notice we are assigning to
# the type only, as all occurrences of that type will automatically
# inherit the material.
beam_type = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcBeamType", name="B1")
# First, let's create a material set. This will later be assigned
# to our beam type element.
material_set = ifcopenshell.api.run("material.add_profile_set", model,
name="B1", set_type="IfcMaterialProfileSet")
# Create a steel material.
steel = ifcopenshell.api.run("material.add_material", model, name="ST01", category="steel")
# Create an I-beam profile curve. Notice how we name our profiles
# based on standardised steel profile names.
hea100 = self.file.create_entity(
"IfcIShapeProfileDef", ProfileName="HEA100", ProfileType="AREA",
OverallWidth=100, OverallDepth=96, WebThickness=5, FlangeThickness=8, FilletRadius=12,
)
# Define that steel material and cross section as a single profile
# item. If this were a composite beam, we might add multiple profile
# items instead, but this is rarely the case in most construction.
profile_item = ifcopenshell.api.run("material.add_profile", model,
profile_set=material_set, material=steel, profile=hea100)
# Great! Let's assign our material set to our beam type.
ifcopenshell.api.run("material.assign_material", model, products=[beam_type], material=material_set)
# Let's create an occurrence of this beam.
beam = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcBeam", name="B1.01")
rel = ifcopenshell.api.run("material.assign_material", model,
products=[beam], type="IfcMaterialProfileSetUsage")
# Let's give a 1000mm long beam body representation.
body = ifcopenshell.api.run("geometry.add_profile_representation",
context=body_context, profile=hea100, depth=1000)
ifcopenshell.api.run("geometry.assign_representation", model, product=beam, representation=body)
ifcopenshell.api.run("geometry.edit_object_placement", model, product=beam)
# Let's change the cardinal point to be the top center of the axis
# line. This is represented by the number "8". Consult the IFC
# documentation for all the numbers you can use.
ifcopenshell.api.run("material.edit_profile_usage", model,
usage=rel.RelatingMaterial, attributes={"CardinalPoint": 8})
"""
self.file = file
self.settings = {"usage": usage, "attributes": attributes or {}}
def execute(self):
self.cardinal_point = self.settings["attributes"].get("CardinalPoint")
if self.cardinal_point and self.cardinal_point != self.settings["usage"].CardinalPoint:
@@ -17,42 +17,39 @@
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
class Usecase:
def __init__(self, file, constituent=None):
"""Removes a constituent from a constituent set
def remove_constituent(file, constituent=None) -> 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.
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 constituent: The IfcMaterialConstituent entity you want to remove
:type constituent: ifcopenshell.entity_instance
:return: None
:rtype: None
Example:
Example:
.. code:: python
.. code:: python
# Create a material set for windows made out of aluminium and glass.
material_set = ifcopenshell.api.run("material.add_material_set", model,
name="Window", set_type="IfcMaterialConstituentSet")
# Create a material set for windows made out of aluminium and glass.
material_set = ifcopenshell.api.run("material.add_material_set", model,
name="Window", set_type="IfcMaterialConstituentSet")
aluminium = ifcopenshell.api.run("material.add_material", model, name="AL01", category="aluminium")
glass = ifcopenshell.api.run("material.add_material", model, name="GLZ01", category="glass")
aluminium = ifcopenshell.api.run("material.add_material", model, name="AL01", category="aluminium")
glass = ifcopenshell.api.run("material.add_material", model, name="GLZ01", category="glass")
# Now let's use those materials as two constituents in our set.
framing = ifcopenshell.api.run("material.add_constituent", model,
constituent_set=material_set, material=aluminium)
glazing = ifcopenshell.api.run("material.add_constituent", model,
constituent_set=material_set, material=glass)
# Now let's use those materials as two constituents in our set.
framing = ifcopenshell.api.run("material.add_constituent", model,
constituent_set=material_set, material=aluminium)
glazing = ifcopenshell.api.run("material.add_constituent", model,
constituent_set=material_set, material=glass)
# Let's remove the glass constituent. Note that we should not remove
# the framing, at this would mean there are no constituents which is
# invalid.
ifcopenshell.api.run("material.remove_constituent", model, constituent=glazing)
"""
self.file = file
self.settings = {"constituent": constituent}
# Let's remove the glass constituent. Note that we should not remove
# the framing, at this would mean there are no constituents which is
# invalid.
ifcopenshell.api.run("material.remove_constituent", model, constituent=glazing)
"""
settings = {"constituent": constituent}
def execute(self):
self.file.remove(self.settings["constituent"])
file.remove(settings["constituent"])
@@ -17,45 +17,42 @@
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
class Usecase:
def __init__(self, file, layer=None):
"""Removes a layer from a layer set
def remove_layer(file, layer=None) -> 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.
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 layer: The IfcMaterialLayer entity you want to remove
:type layer: ifcopenshell.entity_instance
:return: None
:rtype: None
Example:
Example:
.. code:: python
.. code:: python
# Create a material set for steel stud partition walls.
material_set = ifcopenshell.api.run("material.add_material_set", model,
name="Window", set_type="IfcMaterialConstituentSet")
# Create a material set for steel stud partition walls.
material_set = ifcopenshell.api.run("material.add_material_set", model,
name="Window", set_type="IfcMaterialConstituentSet")
gypsum = ifcopenshell.api.run("material.add_material", model, name="PB01", category="gypsum")
steel = ifcopenshell.api.run("material.add_material", model, name="ST01", category="steel")
gypsum = ifcopenshell.api.run("material.add_material", model, name="PB01", category="gypsum")
steel = ifcopenshell.api.run("material.add_material", model, name="ST01", category="steel")
# Now let's use those materials as three layers in our set, such
# that the steel studs are sandwiched by the gypsum. Let's imagine
# we're setting the layer thickness in millimeters.
layer1 = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=gypsum)
ifcopenshell.api.run("material.edit_layer", model, layer=layer1, attributes={"LayerThickness": 13})
layer2 = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=steel)
ifcopenshell.api.run("material.edit_layer", model, layer=layer2, attributes={"LayerThickness": 92})
layer3 = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=gypsum)
ifcopenshell.api.run("material.edit_layer", model, layer=layer3, attributes={"LayerThickness": 13})
# Now let's use those materials as three layers in our set, such
# that the steel studs are sandwiched by the gypsum. Let's imagine
# we're setting the layer thickness in millimeters.
layer1 = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=gypsum)
ifcopenshell.api.run("material.edit_layer", model, layer=layer1, attributes={"LayerThickness": 13})
layer2 = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=steel)
ifcopenshell.api.run("material.edit_layer", model, layer=layer2, attributes={"LayerThickness": 92})
layer3 = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=gypsum)
ifcopenshell.api.run("material.edit_layer", model, layer=layer3, attributes={"LayerThickness": 13})
# Let's remove the last layer, such that the wall might be clad only
# one one side such as to line a services riser.
ifcopenshell.api.run("material.remove_layer", model, layer=layer3)
"""
self.file = file
self.settings = {"layer": layer}
# Let's remove the last layer, such that the wall might be clad only
# one one side such as to line a services riser.
ifcopenshell.api.run("material.remove_layer", model, layer=layer3)
"""
settings = {"layer": layer}
def execute(self):
self.file.remove(self.settings["layer"])
file.remove(settings["layer"])
@@ -19,44 +19,41 @@
import ifcopenshell
class Usecase:
def __init__(self, file, material_list=None, material_index=0):
"""Removes an item in an material list
def remove_list_item(file, material_list=None, material_index=0) -> None:
"""Removes an item in an material list
Note that it is invalid to have zero items in a list, so you should leave
at least one item to ensure a valid IFC dataset.
Note that it is invalid to have zero items in a list, so you should leave
at least one item to ensure a valid IFC dataset.
:param material_list: The IfcMaterialList entity you want to remove an
item from.
:type material_list: ifcopenshell.entity_instance
:param material_index: The index of the material you want to remove from
the list. Starts counting at 0. Defaults to 0.
:type material_index: int, optional
:return: None
:rtype: None
:param material_list: The IfcMaterialList entity you want to remove an
item from.
:type material_list: ifcopenshell.entity_instance
:param material_index: The index of the material you want to remove from
the list. Starts counting at 0. Defaults to 0.
:type material_index: int, optional
:return: None
:rtype: None
Example:
Example:
.. code:: python
.. code:: python
# Create a material list for aluminium windows.
material_set = ifcopenshell.api.run("material.add_material_set", model,
name="Window", set_type="IfcMaterialMaterialList")
# Create a material list for aluminium windows.
material_set = ifcopenshell.api.run("material.add_material_set", model,
name="Window", set_type="IfcMaterialMaterialList")
aluminium = ifcopenshell.api.run("material.add_material", model, name="AL01", category="aluminium")
glass = ifcopenshell.api.run("material.add_material", model, name="GLZ01", category="glass")
aluminium = ifcopenshell.api.run("material.add_material", model, name="AL01", category="aluminium")
glass = ifcopenshell.api.run("material.add_material", model, name="GLZ01", category="glass")
# Now let's use those materials as two items in our list.
ifcopenshell.api.run("material.add_list_item", model, material_list=material_set, material=aluminium)
ifcopenshell.api.run("material.add_list_item", model, material_list=material_set, material=glass)
# Now let's use those materials as two items in our list.
ifcopenshell.api.run("material.add_list_item", model, material_list=material_set, material=aluminium)
ifcopenshell.api.run("material.add_list_item", model, material_list=material_set, material=glass)
# Let's remove the glass
ifcopenshell.api.run("material.remove_list_item", model, material_list=material_set, material_index=1)
"""
self.file = file
self.settings = {"material_list": material_list, "material_index": material_index}
# Let's remove the glass
ifcopenshell.api.run("material.remove_list_item", model, material_list=material_set, material_index=1)
"""
settings = {"material_list": material_list, "material_index": material_index}
def execute(self):
materials = list(self.settings["material_list"].Materials)
materials.pop(self.settings["material_index"])
self.settings["material_list"].Materials = materials
materials = list(settings["material_list"].Materials)
materials.pop(settings["material_index"])
settings["material_list"].Materials = materials
@@ -20,57 +20,54 @@ import ifcopenshell
import ifcopenshell.util.element
class Usecase:
def __init__(self, file, material=None):
"""Removes a material
def remove_material(file, material=None) -> None:
"""Removes a material
If the material is used in a material set, the corresponding layer,
profile, or constituent is also removed. Note that this may result in a
material set with zero items in it, which is invalid, so the user must
take care of this situation themselves.
If the material is used in a material set, the corresponding layer,
profile, or constituent is also removed. Note that this may result in a
material set with zero items in it, which is invalid, so the user must
take care of this situation themselves.
:param material: The IfcMaterial entity you want to remove
:type material: ifcopenshell.entity_instance
:return: None
:rtype: None
:param material: The IfcMaterial entity you want to remove
:type material: ifcopenshell.entity_instance
:return: None
:rtype: None
Example:
Example:
.. code:: python
.. code:: python
# Create a material
aluminium = ifcopenshell.api.run("material.add_material", model, name="AL01", category="aluminium")
# Create a material
aluminium = ifcopenshell.api.run("material.add_material", model, name="AL01", category="aluminium")
# ... and remove it
ifcopenshell.api.run("material.remove_material", model, material=aluminium)
"""
self.file = file
self.settings = {"material": material}
# ... and remove it
ifcopenshell.api.run("material.remove_material", model, material=aluminium)
"""
settings = {"material": material}
def execute(self):
inverse_elements = self.file.get_inverse(self.settings["material"])
self.file.remove(self.settings["material"])
# TODO: Right now, we we choose only to delete set items (e.g. a layer) but not the material set
# This can lead to invalid material sets, but we assume the user will deal with it
for inverse in inverse_elements:
if inverse.is_a("IfcMaterialConstituent"):
self.file.remove(inverse)
elif inverse.is_a("IfcMaterialLayer"):
self.file.remove(inverse)
elif inverse.is_a("IfcMaterialProfile"):
self.file.remove(inverse)
elif inverse.is_a("IfcRelAssociatesMaterial"):
history = inverse.OwnerHistory
self.file.remove(inverse)
if history:
ifcopenshell.util.element.remove_deep2(self.file, history)
elif inverse.is_a("IfcMaterialProperties"):
for prop in inverse.Properties or []:
self.file.remove(prop)
self.file.remove(inverse)
elif inverse.is_a("IfcMaterialDefinitionRepresentation"):
for representation in inverse.Representations:
for item in representation.Items:
self.file.remove(item)
self.file.remove(representation)
self.file.remove(inverse)
inverse_elements = file.get_inverse(settings["material"])
file.remove(settings["material"])
# TODO: Right now, we we choose only to delete set items (e.g. a layer) but not the material set
# This can lead to invalid material sets, but we assume the user will deal with it
for inverse in inverse_elements:
if inverse.is_a("IfcMaterialConstituent"):
file.remove(inverse)
elif inverse.is_a("IfcMaterialLayer"):
file.remove(inverse)
elif inverse.is_a("IfcMaterialProfile"):
file.remove(inverse)
elif inverse.is_a("IfcRelAssociatesMaterial"):
history = inverse.OwnerHistory
file.remove(inverse)
if history:
ifcopenshell.util.element.remove_deep2(file, history)
elif inverse.is_a("IfcMaterialProperties"):
for prop in inverse.Properties or []:
file.remove(prop)
file.remove(inverse)
elif inverse.is_a("IfcMaterialDefinitionRepresentation"):
for representation in inverse.Representations:
for item in representation.Items:
file.remove(item)
file.remove(representation)
file.remove(inverse)
@@ -20,65 +20,62 @@ import ifcopenshell
import ifcopenshell.util.element
class Usecase:
def __init__(self, file, material=None):
"""Removes a material set
def remove_material_set(file, material=None) -> None:
"""Removes a material set
All set items, such as layers, profiles, or constituents will also be
removed. However, the materials and profile curves used by the layers,
profiles and constituents will not be removed.
All set items, such as layers, profiles, or constituents will also be
removed. However, the materials and profile curves used by the layers,
profiles and constituents will not be removed.
:param material: The IfcMaterialLayerSet, IfcMaterialConstituentSet,
IfcMaterialProfileSet entity you want to remove.
:type material: ifcopenshell.entity_instance
:return: None
:rtype: None
:param material: The IfcMaterialLayerSet, IfcMaterialConstituentSet,
IfcMaterialProfileSet entity you want to remove.
:type material: ifcopenshell.entity_instance
:return: None
:rtype: None
Example:
Example:
.. code:: python
.. code:: python
# Create a material set
material_set = ifcopenshell.api.run("material.add_material_set", model,
name="GYP-ST-GYP", set_type="IfcMaterialLayerSet")
# Create a material set
material_set = ifcopenshell.api.run("material.add_material_set", model,
name="GYP-ST-GYP", set_type="IfcMaterialLayerSet")
# Create some materials
gypsum = ifcopenshell.api.run("material.add_material", model, name="PB01", category="gypsum")
steel = ifcopenshell.api.run("material.add_material", model, name="ST01", category="steel")
# Create some materials
gypsum = ifcopenshell.api.run("material.add_material", model, name="PB01", category="gypsum")
steel = ifcopenshell.api.run("material.add_material", model, name="ST01", category="steel")
# Add some layers
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=gypsum)
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=steel)
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=gypsum)
# Add some layers
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=gypsum)
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=steel)
layer = ifcopenshell.api.run("material.add_layer", model, layer_set=material_set, material=gypsum)
# Completely delete the set and all layers. The gypsum and steel
# material still exist, though.
ifcopenshell.api.run("material.remove_material_set", model, material=material_set)
"""
# Completely delete the set and all layers. The gypsum and steel
# material still exist, though.
ifcopenshell.api.run("material.remove_material_set", model, material=material_set)
"""
self.file = file
self.settings = {"material": material}
settings = {"material": material}
def execute(self):
inverse_elements = self.file.get_inverse(self.settings["material"])
if self.settings["material"].is_a("IfcMaterialLayerSet"):
set_items = self.settings["material"].MaterialLayers or []
elif self.settings["material"].is_a("IfcMaterialProfileSet"):
set_items = self.settings["material"].MaterialProfiles or []
elif self.settings["material"].is_a("IfcMaterialConstituentSet"):
set_items = self.settings["material"].MaterialConstituents or []
elif self.settings["material"].is_a("IfcMaterialList"):
set_items = []
for set_item in set_items:
self.file.remove(set_item)
self.file.remove(self.settings["material"])
for inverse in inverse_elements:
if inverse.is_a("IfcRelAssociatesMaterial"):
history = inverse.OwnerHistory
self.file.remove(inverse)
if history:
ifcopenshell.util.element.remove_deep2(self.file, history)
elif inverse.is_a("IfcMaterialProperties"):
for prop in inverse.Properties or []:
self.file.remove(prop)
self.file.remove(inverse)
inverse_elements = file.get_inverse(settings["material"])
if settings["material"].is_a("IfcMaterialLayerSet"):
set_items = settings["material"].MaterialLayers or []
elif settings["material"].is_a("IfcMaterialProfileSet"):
set_items = settings["material"].MaterialProfiles or []
elif settings["material"].is_a("IfcMaterialConstituentSet"):
set_items = settings["material"].MaterialConstituents or []
elif settings["material"].is_a("IfcMaterialList"):
set_items = []
for set_item in set_items:
file.remove(set_item)
file.remove(settings["material"])
for inverse in inverse_elements:
if inverse.is_a("IfcRelAssociatesMaterial"):
history = inverse.OwnerHistory
file.remove(inverse)
if history:
ifcopenshell.util.element.remove_deep2(file, history)
elif inverse.is_a("IfcMaterialProperties"):
for prop in inverse.Properties or []:
file.remove(prop)
file.remove(inverse)
@@ -21,58 +21,55 @@ import ifcopenshell
import ifcopenshell.util.element
class Usecase:
def __init__(self, file, profile=None):
"""Removes a profile item from a profile set
def remove_profile(file, profile=None) -> 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.
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 profile: The IfcMaterialProfile entity you want to remove
:type profile: ifcopenshell.entity_instance
:return: None
:rtype: None
Example:
Example:
.. code:: python
.. code:: python
# First, let's create a material set.
material_set = ifcopenshell.api.run("material.add_profile_set", model,
name="B1", set_type="IfcMaterialProfileSet")
# First, let's create a material set.
material_set = ifcopenshell.api.run("material.add_profile_set", model,
name="B1", set_type="IfcMaterialProfileSet")
# Create a steel material.
steel = ifcopenshell.api.run("material.add_material", model, name="ST01", category="steel")
# Create a steel material.
steel = ifcopenshell.api.run("material.add_material", model, name="ST01", category="steel")
# Create an I-beam profile curve. Notice how we name our profiles
# based on standardised steel profile names.
hea100 = self.file.create_entity(
"IfcIShapeProfileDef", ProfileName="HEA100", ProfileType="AREA",
OverallWidth=100, OverallDepth=96, WebThickness=5, FlangeThickness=8, FilletRadius=12,
)
# Create an I-beam profile curve. Notice how we name our profiles
# based on standardised steel profile names.
hea100 = file.create_entity(
"IfcIShapeProfileDef", ProfileName="HEA100", ProfileType="AREA",
OverallWidth=100, OverallDepth=96, WebThickness=5, FlangeThickness=8, FilletRadius=12,
)
# Define that steel material and cross section as a single profile item.
ifcopenshell.api.run("material.add_profile", model,
profile_set=material_set, material=steel, profile=hea100)
# Define that steel material and cross section as a single profile item.
ifcopenshell.api.run("material.add_profile", model,
profile_set=material_set, material=steel, profile=hea100)
# Imagine a welded square along the length of the profile.
welded_square = ifcopenshell.api.run("profile.add_arbitrary_profile", model,
profile=[(.0025, .0025), (.0325, .0025), (.0325, -.0025), (.0025, -.0025), (.0025, .0025)])
weld_profile = ifcopenshell.api.run("material.add_profile", model,
profile_set=material_set, material=steel, profile=welded_square)
# Imagine a welded square along the length of the profile.
welded_square = ifcopenshell.api.run("profile.add_arbitrary_profile", model,
profile=[(.0025, .0025), (.0325, .0025), (.0325, -.0025), (.0025, -.0025), (.0025, .0025)])
weld_profile = ifcopenshell.api.run("material.add_profile", model,
profile_set=material_set, material=steel, profile=welded_square)
# Let's remove our welded square.
ifcopenshell.api.run("material.remove_profile", model, profile=weld_profile)
"""
# Let's remove our welded square.
ifcopenshell.api.run("material.remove_profile", model, profile=weld_profile)
"""
self.file = file
self.settings = {"profile": profile}
settings = {"profile": profile}
def execute(self):
subelements = set()
for attribute in self.settings["profile"]:
if isinstance(attribute, ifcopenshell.entity_instance):
subelements.add(attribute)
self.file.remove(self.settings["profile"])
for subelement in subelements:
ifcopenshell.util.element.remove_deep2(self.file, subelement)
subelements = set()
for attribute in settings["profile"]:
if isinstance(attribute, ifcopenshell.entity_instance):
subelements.add(attribute)
file.remove(settings["profile"])
for subelement in subelements:
ifcopenshell.util.element.remove_deep2(file, subelement)
@@ -17,56 +17,53 @@
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
class Usecase:
def __init__(self, file, material_set=None, old_index=0, new_index=0):
"""Reorders an item in a material set
def reorder_set_item(file, material_set=None, old_index=0, new_index=0) -> None:
"""Reorders an item in a material set
In some material sets, the order have meaning, like in a layer set. In
other cases, it is purely for human convenience.
In some material sets, the order have meaning, like in a layer set. In
other cases, it is purely for human convenience.
:param material_set: The IfcMaterialSet which you want to reorder an
item in.
:type material_set: ifcopenshell.entity_instance
:param old_index: The index of the item you want to move. This starts
counting from 0.
:type old_index: int
:param new_index: The index of the new position the item will move to.
This starts counting from 0.
:type new_index: int
:return: None
:rtype: None
:param material_set: The IfcMaterialSet which you want to reorder an
item in.
:type material_set: ifcopenshell.entity_instance
:param old_index: The index of the item you want to move. This starts
counting from 0.
:type old_index: int
:param new_index: The index of the new position the item will move to.
This starts counting from 0.
:type new_index: int
:return: None
:rtype: None
Example:
Example:
.. code:: python
.. code:: python
material_set = ifcopenshell.api.run("material.add_material_set", model,
name="Window", set_type="IfcMaterialList")
material_set = ifcopenshell.api.run("material.add_material_set", model,
name="Window", set_type="IfcMaterialList")
aluminium = ifcopenshell.api.run("material.add_material", model, name="AL01", category="aluminium")
glass = ifcopenshell.api.run("material.add_material", model, name="GLZ01", category="glass")
aluminium = ifcopenshell.api.run("material.add_material", model, name="AL01", category="aluminium")
glass = ifcopenshell.api.run("material.add_material", model, name="GLZ01", category="glass")
# Now let's use those materials as two items in our list.
ifcopenshell.api.run("material.add_list_item", model, material_list=material_set, material=aluminium)
ifcopenshell.api.run("material.add_list_item", model, material_list=material_set, material=glass)
# Now let's use those materials as two items in our list.
ifcopenshell.api.run("material.add_list_item", model, material_list=material_set, material=aluminium)
ifcopenshell.api.run("material.add_list_item", model, material_list=material_set, material=glass)
# Switch the order around, this has no meaning for a list, so this
# is just for fun.
ifcopenshell.api.run("material.reorder_set_item", model,
material_set=material_set, old_index=0, new_index=1)
"""
self.file = file
self.settings = {"material_set": material_set, "old_index": old_index, "new_index": new_index}
# Switch the order around, this has no meaning for a list, so this
# is just for fun.
ifcopenshell.api.run("material.reorder_set_item", model,
material_set=material_set, old_index=0, new_index=1)
"""
settings = {"material_set": material_set, "old_index": old_index, "new_index": new_index}
def execute(self):
if self.settings["material_set"].is_a("IfcMaterialConstituentSet"):
set_name = "MaterialConstituents"
elif self.settings["material_set"].is_a("IfcMaterialLayerSet"):
set_name = "MaterialLayers"
elif self.settings["material_set"].is_a("IfcMaterialProfileSet"):
set_name = "MaterialProfiles"
elif self.settings["material_set"].is_a("IfcMaterialList"):
set_name = "Materials"
items = list(getattr(self.settings["material_set"], set_name) or [])
items.insert(self.settings["new_index"], items.pop(self.settings["old_index"]))
setattr(self.settings["material_set"], set_name, items)
if settings["material_set"].is_a("IfcMaterialConstituentSet"):
set_name = "MaterialConstituents"
elif settings["material_set"].is_a("IfcMaterialLayerSet"):
set_name = "MaterialLayers"
elif settings["material_set"].is_a("IfcMaterialProfileSet"):
set_name = "MaterialProfiles"
elif settings["material_set"].is_a("IfcMaterialList"):
set_name = "Materials"
items = list(getattr(settings["material_set"], set_name) or [])
items.insert(settings["new_index"], items.pop(settings["old_index"]))
setattr(settings["material_set"], set_name, items)
@@ -21,41 +21,44 @@ import ifcopenshell.api
import ifcopenshell.util.element
def unassign_material(file: ifcopenshell.file, products: list[ifcopenshell.entity_instance]) -> None:
"""Removes any material relationship with the list of products
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
removed, only the relationship is removed.
If the product does not have a material, nothing happens.
:param products: The list IfcProducts that may or may not have a material
:type product: list[ifcopenshell.entity_instance]
:return: None
:rtype: None
Example:
.. code:: python
concrete = ifcopenshell.api.run("material.add_material", model, name="CON01", category="concrete")
# Let's imagine a concrete bench made out of concrete.
bench_type = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcFurnitureType")
ifcopenshell.api.run("material.assign_material", model,
products=[bench_type], type="IfcMaterial", material=concrete)
# Let's change our mind and remove the concrete assignment. The
# concrete material still exists, but the bench is no longer made
# out of concrete now.
ifcopenshell.api.run("material.unassign_material", model, products=[bench_type])
"""
usecase = Usecase()
usecase.file = file
usecase.settings = {"products": products}
return usecase.execute()
class Usecase:
def __init__(self, file: ifcopenshell.file, products: list[ifcopenshell.entity_instance]):
"""Removes any material relationship with the list of products
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
removed, only the relationship is removed.
If the product does not have a material, nothing happens.
:param products: The list IfcProducts that may or may not have a material
:type product: list[ifcopenshell.entity_instance]
:return: None
:rtype: None
Example:
.. code:: python
concrete = ifcopenshell.api.run("material.add_material", model, name="CON01", category="concrete")
# Let's imagine a concrete bench made out of concrete.
bench_type = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcFurnitureType")
ifcopenshell.api.run("material.assign_material", model,
products=[bench_type], type="IfcMaterial", material=concrete)
# Let's change our mind and remove the concrete assignment. The
# concrete material still exists, but the bench is no longer made
# out of concrete now.
ifcopenshell.api.run("material.unassign_material", model, products=[bench_type])
"""
self.file = file
self.settings = {"products": products}
def execute(self) -> None:
def execute(self):
self.products = set(self.settings["products"])
if not self.products:
return