Write docs for type API module

This commit is contained in:
Dion Moult
2023-01-04 16:09:32 +11:00
parent 92623b98e2
commit 90d4d5afda
4 changed files with 238 additions and 19 deletions
@@ -22,14 +22,147 @@ import ifcopenshell.util.element
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, related_object=None, relating_type=None):
"""Assigns a type to an occurrence of an object
IFC supports the concept of occurrences and types. An occurrence is an
actual physical product in the real world: like a wall, a chair, a door,
a column, a pump, and so on.
Most occurrences have a corresponding type. A type describes either a
common shape and set of properties of a particular model of equipment,
or a construction typology. An occurrence may only have zero or one
type.
For example, architects would typically have a door schedule for
individual occurrences of doors and a door types schedule for a handful
of door types, described by the door hardware, frame, and panel. Other
examples might be window types or wall types. Structural engineers would
have a list of column types, beam types, slab types, etc, such as a 400
diameter column, a 500 diameter column, and so on. Services consultant
might nominate a particular type of sprinkler which have many
occurrences, or light fixture types, and so on.
Types are critical as they communicate to the procurement team what
types of equipment and products need to be procured. The individual
occurrences of that type tell them how many to procure. Types are also
critical in construction as they indicate succinctly how to manufacture
or construct something. For example, a wall type is enough information
for a builder to understand the build up and construction of a wall.
Types are used to help break down cost plans, or isolate portions of an
assembly process for construction scheduling. Types are also used in
facility maintenance, as occurrences sharing the same type can be
repaired in the same way or by replacing the same parts.
An occurrence of a type inherits all the properties and materials of the
type. For example, a 2HR fire rated wall type implies that all
wall occurrences of that wall type will also be 2HR fire rated.
A type may or may not have a geometric representation. If a type does
not have any representation, then the occurrences are free to have any
representation of their own. However, if a type has a representation,
all occurrences must have the same representation. For example, if a
light fixture downlight type has a representation of a cylinder, then
all occurrences must have exactly the same cylinder as its
representation. If you change the cylinder's shape of the type, then all
occurrence representations will also change.
If a type does not have any geometric representation, they may have a
parametric material representation. This may be either a parametric
layered material or parametric cross-sectional profile material. If this
is the case, the occurrence must be constructed out of the parametric
material. For example, if a wall type uses a list of parametric layers
indicating a thickness of 13mm plasterboard and 90mm stud, then the
thickness of every wall occurrence representation must be 103mm. The
length of each wall, however, may vary. Similarly, if a beam type has a
parametric profile material of an I-beam, then all beam occurrences must
also be this I-beam shape, though the length may vary.
It is highly recommended for every occurence to have a type. There are
some exceptions to the rule, such as in heritage architecture or
as-built or dilapidation models, where existing conditions are
ambiguous, unknown or are so bespoke as to have no logical type.
:param related_object: The IfcElement occurrence.
:type related_object: ifcopenshell.entity_instance.entity_instance
:param relating_type: The IfcElementType type.
:type relating_type: ifcopenshell.entity_instance.entity_instance
:return: The IfcRelDefinesByType relationship
:rtype: ifcopenshell.entity_instance.entity_instance
Example::
# A furniture type. This would correlate to a particular model in a
# manufacturer's catalogue. Like an Ikea sofa :)
furniture_type = ifcopenshell.api.run("root.create_entity", model,
ifc_class="IfcFurnitureType", name="FUN01")
# An individual occurrence of a that sofa.
furniture = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcFurniture")
# Assign the furniture to the furniture type. If the furniture_type
# had a representation, the furniture occurrence will also now have
# the exact same representation. This is highly efficient as you
# don't need to define the representation for every occurrence.
ifcopenshell.api.run("type.assign_type", model, related_object=furniture, relating_type=furniture_type)
# Let's imagine a parametric material layer set
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")
# 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": .013})
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": .092})
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": .013})
# Great! Let's assign our material set to our wall type.
ifcopenshell.api.run("material.assign_material", model, product=wall_type, material=material_set)
# Now, let's create a wall.
wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")
# The wall is a WAL01 wall type.
ifcopenshell.api.run("type.assign_type", model, related_object=wall, relating_type=wall_type)
# A bit of preparation, let's create some geometric contexts since
# we want to create some geometry for our wall.
model3d = ifcopenshell.api.run("context.add_context", model, context_type="Model")
body = ifcopenshell.api.run("context.add_context", model,
context_type="Model", context_identifier="Body", target_view="MODEL_VIEW", parent=model3d)
# Notice how our thickness of 0.118 must equal .013 + .092 + .013 from our type
representation = ifcopenshell.api.run("geometry.add_wall_representation", model,
context=body, length=5, height=3, thickness=0.118)
# Assign our new body geometry back to our wall
ifcopenshell.api.run("geometry.assign_representation", model,
product=wall, representation=representation)
# Place our wall at the origin
ifcopenshell.api.run("geometry.edit_object_placement", model, product=wall)
"""
self.file = file
self.settings = {
"related_object": None,
"relating_type": None,
"related_object": related_object,
"relating_type": relating_type,
}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
if self.file.schema == "IFC2X3":
@@ -20,14 +20,25 @@ import ifcopenshell
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, related_object=None, relating_type=None):
"""Gets all the related occurrences of a type
Do not use this function. It will be removed. Use
ifcopenshell.util.element.get_type or
ifcopenshell.util.element.get_types instead.
:param related_object: The IfcElement occurrence.
:type related_object: ifcopenshell.entity_instance.entity_instance
:param relating_type: The IfcElementType type.
:type relating_type: ifcopenshell.entity_instance.entity_instance
:return: A list of occurrences of the type.
:rtype: list[ifcopenshell.entity_instance.entity_instance]
"""
self.file = file
self.settings = {
"related_object": None,
"relating_type": None,
"related_object": related_object,
"relating_type": relating_type,
}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
if self.settings["related_object"]:
@@ -22,14 +22,68 @@ import ifcopenshell.util.element
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, related_object=None, relating_type=None):
"""Ensures that all occurrences has the same representation as the type
If a type has a representation, all occurrences must have the same
representation. If the type's representation changes, this function may
be used to ensure consistency of the occurrence's representations.
:param related_object: The IfcElement occurrence.
:type related_object: ifcopenshell.entity_instance.entity_instance
:param relating_type: The IfcElementType type.
:type relating_type: ifcopenshell.entity_instance.entity_instance
:return: None
:rtype: None
Example::
# A furniture type. This would correlate to a particular model in a
# manufacturer's catalogue. Like an Ikea sofa :)
furniture_type = ifcopenshell.api.run("root.create_entity", model,
ifc_class="IfcFurnitureType", name="FUN01")
# An individual occurrence of a that sofa.
furniture = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcFurniture")
# Place our furniture at the origin
ifcopenshell.api.run("geometry.edit_object_placement", model, product=furniture)
# Assign the furniture to the furniture type. Right now, the
# furniture type has no representation, so the furniture may also
# have no representation, or any arbitrary representation that may
# vary from occurrence to occurrence.
ifcopenshell.api.run("type.assign_type", model, related_object=furniture, relating_type=furniture_type)
# A bit of preparation, let's create some geometric contexts since
# we want to create some geometry for our furniture type.
model3d = ifcopenshell.api.run("context.add_context", model, context_type="Model")
body = ifcopenshell.api.run("context.add_context", model,
context_type="Model", context_identifier="Body", target_view="MODEL_VIEW", parent=model3d)
# Let's create a mesh representation of an arbitrary 2m cube.
representation = ifcopenshell.api.run("geometry.add_sverchok_representation", model, context=body,
vertices=[[(-1.0, -1.0, 0.0), (-1.0, -1.0, 2.0), (-1.0, 1.0, 0.0), (-1.0, 1.0, 2.0),
(1.0, -1.0, 0.0), (1.0, -1.0, 2.0), (1.0, 1.0, 0.0), (1.0, 1.0, 2.0)]],
faces=[[[0, 1, 3, 2], [2, 3, 7, 6], [6, 7, 5, 4], [4, 5, 1, 0], [2, 6, 4, 0], [7, 3, 1, 5]]])
# Assign our new body geometry back to our furniture type. In this
# case, since we use the API, all occurrences automatically get the
# representation mapped, so there is nothing more we need to do.
ifcopenshell.api.run("geometry.assign_representation", model,
product=furniture_type, representation=representation)
# However, if you were doing some sort of manual IFC patching, like
# assigning furniture_type.RepresentationMaps directly, then you
# might make this call:
# ifcopenshell.api.run("type.map_type_representations", model,
# related_object=furniture, relating_type=furniture_type)
"""
self.file = file
self.settings = {
"related_object": None,
"relating_type": None,
"related_object": related_object,
"relating_type": relating_type,
}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
if not self.settings["relating_type"].RepresentationMaps:
@@ -21,11 +21,32 @@ import ifcopenshell.api
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, related_object=None):
"""Unassigns a type of an occurrence
:param related_object: The IfcElement occurrence.
:type related_object: ifcopenshell.entity_instance.entity_instance
:return: None
:rtype: None
Example::
# A furniture type. This would correlate to a particular model in a
# manufacturer's catalogue. Like an Ikea sofa :)
furniture_type = ifcopenshell.api.run("root.create_entity", model,
ifc_class="IfcFurnitureType", name="FUN01")
# An individual occurrence of a that sofa.
furniture = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcFurniture")
# Assign the furniture to the furniture type.
ifcopenshell.api.run("type.assign_type", model, related_object=furniture, relating_type=furniture_type)
# Change our mind. Maybe it's a different type?
ifcopenshell.api.run("type.unassign_type", model, related_object=furniture)
"""
self.file = file
self.settings = {"related_object": None}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"related_object": related_object}
def execute(self):
if self.file.schema == "IFC2X3":