You can now get specific container types via util.element or util.selector. E.g. if you wanted to know what building an object is in or what storey an object is on.

This commit is contained in:
Dion Moult
2023-08-21 23:06:49 +10:00
parent 2d3295ec54
commit 57173c7740
2 changed files with 32 additions and 3 deletions
@@ -625,7 +625,7 @@ def get_layers(ifc_file, element):
return layers
def get_container(element, should_get_direct=False):
def get_container(element, should_get_direct=False, ifc_class=None):
"""
Retrieves the spatial structure container of an element.
@@ -637,6 +637,9 @@ def get_container(element, should_get_direct=False):
part of an aggregate, and then if that aggregate is contained in a
spatial structure element.
:type should_get_direct: bool
:param ifc_class: Optionally filter the type of container you're after. For
example, you may be after the storey, not a space.
:type ifc_class: str
:return: The direct or indirect container of the element or None.
Example:
@@ -648,13 +651,23 @@ def get_container(element, should_get_direct=False):
"""
if should_get_direct:
if hasattr(element, "ContainedInStructure") and element.ContainedInStructure:
return element.ContainedInStructure[0].RelatingStructure
container = element.ContainedInStructure[0].RelatingStructure
if not ifc_class:
return container
if container.is_a(ifc_class):
return container
else:
aggregate = get_aggregate(element)
if aggregate:
return get_container(aggregate, should_get_direct)
if hasattr(element, "ContainedInStructure") and element.ContainedInStructure:
return element.ContainedInStructure[0].RelatingStructure
container = element.ContainedInStructure[0].RelatingStructure
if not ifc_class:
return container
while container:
if container.is_a(ifc_class):
return container
container = get_aggregate(container)
def get_referenced_structures(element):
@@ -151,6 +151,14 @@ def set_element_value(ifc_file, element, query, value):
element = element.MaterialConstituents
elif key == "container":
element = ifcopenshell.util.element.get_container(element)
elif key == "space":
element = ifcopenshell.util.element.get_container(element, ifc_class="IfcSpace")
elif key == "storey":
element = ifcopenshell.util.element.get_container(element, ifc_class="IfcBuildingStorey")
elif key == "building":
element = ifcopenshell.util.element.get_container(element, ifc_class="IfcBuilding")
elif key == "site":
element = ifcopenshell.util.element.get_container(element, ifc_class="IfcSite")
elif key == "class":
if element.is_a() != value:
return ifcopenshell.util.schema.reassign_class(ifc_file, element, value)
@@ -637,6 +645,14 @@ class Selector:
value = value.MaterialConstituents
elif key == "container":
value = ifcopenshell.util.element.get_container(value)
elif key == "space":
element = ifcopenshell.util.element.get_container(element, ifc_class="IfcSpace")
elif key == "storey":
element = ifcopenshell.util.element.get_container(element, ifc_class="IfcBuildingStorey")
elif key == "building":
element = ifcopenshell.util.element.get_container(element, ifc_class="IfcBuilding")
elif key == "site":
element = ifcopenshell.util.element.get_container(element, ifc_class="IfcSite")
elif key == "class":
value = value.is_a()
elif key == "id":