Add feature to get parent of a particular IFC class

This commit is contained in:
Dion Moult
2026-03-20 23:10:00 +11:00
parent 7b6e82a9cc
commit d0f20371bd
3 changed files with 50 additions and 6 deletions
@@ -1234,7 +1234,9 @@ def get_controls(element: ifcopenshell.entity_instance) -> Generator[ifcopenshel
yield rel.RelatingControl
def get_parent(element: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]:
def get_parent(
element: ifcopenshell.entity_instance, ifc_class: Optional[str] = None
) -> Union[ifcopenshell.entity_instance, None]:
"""Get the parent in the spatial heirarchy
IFC features a spatial hierarchy tree of all objects. Each spatial element
@@ -1251,6 +1253,8 @@ def get_parent(element: ifcopenshell.entity_instance) -> Union[ifcopenshell.enti
- Voiding: the opening voids another physical element, such as a hole in a wall
:param element: Any physical or spatial element in the tree
:param ifc_class: Optionally filter the type of parent you're after. For
example, you may be after the storey, not a space.
:return: Its parent. This must exist for any valid file, or None if we've reached the IfcProject.
Example:
@@ -1260,7 +1264,7 @@ def get_parent(element: ifcopenshell.entity_instance) -> Union[ifcopenshell.enti
element = file.by_type("IfcWall")[0]
parent = ifcopenshell.util.element.get_parent(element)
"""
return (
parent = (
get_container(element, should_get_direct=True)
or get_aggregate(element)
or get_nest(element)
@@ -1268,6 +1272,16 @@ def get_parent(element: ifcopenshell.entity_instance) -> Union[ifcopenshell.enti
or get_voided_element(element)
)
if not ifc_class:
return parent
while parent:
if parent.is_a(ifc_class):
return parent
parent = get_parent(parent)
return None
def get_filled_void(element: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]:
"""If the element is filling a void, get the void
@@ -440,13 +440,13 @@ def _get_element_value(element: ifcopenshell.entity_instance, keys: list[str]) -
elif key == "container":
value = ifcopenshell.util.element.get_container(value)
elif key == "space":
value = ifcopenshell.util.element.get_container(value, ifc_class="IfcSpace")
value = ifcopenshell.util.element.get_parent(value, ifc_class="IfcSpace")
elif key == "storey":
value = ifcopenshell.util.element.get_container(value, ifc_class="IfcBuildingStorey")
value = ifcopenshell.util.element.get_parent(value, ifc_class="IfcBuildingStorey")
elif key == "building":
value = ifcopenshell.util.element.get_container(value, ifc_class="IfcBuilding")
value = ifcopenshell.util.element.get_parent(value, ifc_class="IfcBuilding")
elif key == "site":
value = ifcopenshell.util.element.get_container(value, ifc_class="IfcSite")
value = ifcopenshell.util.element.get_parent(value, ifc_class="IfcSite")
elif key == "parent":
value = ifcopenshell.util.element.get_parent(value)
elif key in ("types", "occurrences"):