Write docs for void API module

This commit is contained in:
Dion Moult
2023-01-04 16:09:46 +11:00
parent fd8774718e
commit 82ac895bbb
4 changed files with 208 additions and 16 deletions
@@ -20,11 +20,85 @@ import ifcopenshell
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, opening=None, element=None):
"""Fill an opening with an element
Physical elements may have openings in them. For example, a wall might
have an opening for a door. That opening is then filled by the door.
This indicates that when the door moves, the opening will move with it.
Or if the door is removed, then the opening may remain and need to be
filled.
:param opening: The IfcOpeningElement to fill with the element.
:type opening: ifcopenshell.entity_instance.entity_instance
:param element: The IfcElement to be inserted into the opening.
:type element: ifcopenshell.entity_instance.entity_instance
:return: The new IfcRelFillsElement relationship
:rtype: ifcopenshell.entity_instance.entity_instance
Example::
# A bit of preparation, let's create some geometric contexts since
# we want to create some geometry for our wall and opening.
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)
# Create a wall
wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")
# Let's use the "3D Body" representation we created earlier to add a
# new wall-like body geometry, 5 meters long, 3 meters high, and
# 200mm thick
representation = ifcopenshell.api.run("geometry.add_wall_representation", model,
context=body, length=5, height=3, thickness=0.2)
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)
# Create an opening, such as for a service penetration with fire and
# acoustic requirements.
opening = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcOpeningElement")
# Let's create an opening representation of a 950mm x 2100mm door.
# Notice how the thickness is greater than the wall thickness, this
# helps resolve floating point resolution errors in 3D.
representation = ifcopenshell.api.run("geometry.add_wall_representation", model,
context=body, length=.95, height=2.1, thickness=0.4)
ifcopenshell.api.run("geometry.assign_representation", model,
product=opening, representation=representation)
# Let's shift our door 1 meter along the wall and 100mm along the
# wall, to create a nice overlap for the opening boolean.
matrix = np.identity(4)
matrix[:,3] = [1, -.1, 0, 0]
ifcopenshell.api.run("geometry.edit_object_placement", model, product=opening, matrix=matrix)
# The opening will now void the wall.
ifcopenshell.api.run("void.add_opening", model, opening=opening, element=wall)
# Create a door
door = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcDoor")
# Let's create a door representation of a 950mm x 2100mm door.
representation = ifcopenshell.api.run("geometry.add_wall_representation", model,
context=body, length=.95, height=2.1, thickness=0.05)
ifcopenshell.api.run("geometry.assign_representation", model,
product=door, representation=representation)
# Let's shift our door 1 meter along the wall and 100mm along the
# wall, which lines up with our opening.
matrix = np.identity(4)
matrix[:,3] = [1, .05, 0, 0]
ifcopenshell.api.run("geometry.edit_object_placement", model, product=door, matrix=matrix)
# The door will now fill the opening.
ifcopenshell.api.run("void.add_filling", model, opening=opening, element=door)
"""
self.file = file
self.settings = {"opening": None, "element": None}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"opening": opening, "element": element}
def execute(self):
fills_voids = self.settings["element"].FillsVoids
@@ -22,11 +22,83 @@ import ifcopenshell.util.placement
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, opening=None, element=None):
"""Create an opening in an element
It is often necessary to cut out openings in elements like walls and
slabs to make space to insert doors, windows, and other services that go
through these penetrations.
Whereas it is possible to simply draw the wall as a rectangle with a
hole in it for the opening, often these openings have specific meanings.
For example, an opening might be filled with a window, and so when the
window moves, the opening should move with it. Alternatively, the
opening itself might have fire or acoustic requirements, such that any
service or equipment passing through that space must also comply with
those requirements. For these types of semantic openings, you should
have a distinct opening element which voids your regular element. For
example, your wall will still be a rectangular prism with no hole in it,
and a separate opening element will have a box representing the extents
of the opening for a window. The opening element will automatically
perform a geometric boolean operation to cut out the wall's geometry.
Whenever you have an opening in you project, you should determine
whether or not the opening is semantic (i.e. should be represented by a
distinct opening object) or non-semantic (i.e. should simply be
booleaned or be part of the shape of the object).
:param opening: The IfcOpeningElement to cut out the element.
:type opening: ifcopenshell.entity_instance.entity_instance
:param element: The IfcElement to insert the opening into.
:type element: ifcopenshell.entity_instance.entity_instance
:return: The new IfcRelVoidsElement relationship
:rtype: ifcopenshell.entity_instance.entity_instance
Example::
# A bit of preparation, let's create some geometric contexts since
# we want to create some geometry for our wall and opening.
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)
# Create a wall
wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")
# Let's use the "3D Body" representation we created earlier to add a
# new wall-like body geometry, 5 meters long, 3 meters high, and
# 200mm thick
representation = ifcopenshell.api.run("geometry.add_wall_representation", model,
context=body, length=5, height=3, thickness=0.2)
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)
# Create an opening, such as for a service penetration with fire and
# acoustic requirements.
opening = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcOpeningElement")
# Let's create an opening representation of a 950mm x 2100mm door.
# Notice how the thickness is greater than the wall thickness, this
# helps resolve floating point resolution errors in 3D.
representation = ifcopenshell.api.run("geometry.add_wall_representation", model,
context=body, length=.95, height=2.1, thickness=0.4)
ifcopenshell.api.run("geometry.assign_representation", model,
product=opening, representation=representation)
# Let's shift our door 1 meter along the wall and 100mm along the
# wall, to create a nice overlap for the opening boolean.
matrix = np.identity(4)
matrix[:,3] = [1, -.1, 0, 0]
ifcopenshell.api.run("geometry.edit_object_placement", model, product=opening, matrix=matrix)
# The opening will now void the wall.
ifcopenshell.api.run("void.add_opening", model, opening=opening, element=wall)
"""
self.file = file
self.settings = {"opening": None, "element": None}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"opening": opening, "element": element}
def execute(self):
voids_elements = self.settings["opening"].VoidsElements
@@ -18,11 +18,38 @@
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, element=None):
"""Remove a filling relationship
If an element is filling an opening, this removes the relationship such
that the opening and element both still exist, but the element no longer
fills the opening.
:param element: The element filling an opening.
:type element: ifcopenshell.entity_instance.entity_instance
:return: None
:rtype: None
Example::
# Create a wall
wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")
# Create an opening, such as for a service penetration with fire and
# acoustic requirements.
opening = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcOpeningElement")
# Create a door
door = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcDoor")
# The door will now fill the opening.
ifcopenshell.api.run("void.add_filling", model, opening=opening, element=door)
# Not anymore!
ifcopenshell.api.run("void.remove_filling", model, element=door)
"""
self.file = file
self.settings = {"element": None}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"element": element}
def execute(self):
for rel in self.file.by_type("IfcRelFillsElement"):
@@ -20,11 +20,30 @@ import ifcopenshell.api
class Usecase:
def __init__(self, file, **settings):
def __init__(self, file, opening=None):
"""Remove an opening
Fillings are retained as orphans. Voided elements remain. Openings
cannot exist by themselves, so not only is the opening relationship
removed, the opening is also removed.
:param opening: The IfcOpeningElement to remove.
:type opening: ifcopenshell.entity_instance.entity_instance
:return: None
:rtype: None
Example::
# Create an oprhaned opening. Note that an orphaned opening is
# invalid, as an opening can only exist when voiding another
# element.
opening = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcOpeningElement")
# Remove it. This brings us back to a valid model.
ifcopenshell.api.run("void.remove_opening", model, opening=opening)
"""
self.file = file
self.settings = {"opening": None}
for key, value in settings.items():
self.settings[key] = value
self.settings = {"opening": opening}
def execute(self):
for rel in self.settings["opening"].VoidsElements: