mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-20 15:08:51 +00:00
Add feature to get parent of a particular IFC class
This commit is contained in:
@@ -1234,7 +1234,9 @@ def get_controls(element: ifcopenshell.entity_instance) -> Generator[ifcopenshel
|
|||||||
yield rel.RelatingControl
|
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
|
"""Get the parent in the spatial heirarchy
|
||||||
|
|
||||||
IFC features a spatial hierarchy tree of all objects. Each spatial element
|
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
|
- 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 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.
|
:return: Its parent. This must exist for any valid file, or None if we've reached the IfcProject.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
@@ -1260,7 +1264,7 @@ def get_parent(element: ifcopenshell.entity_instance) -> Union[ifcopenshell.enti
|
|||||||
element = file.by_type("IfcWall")[0]
|
element = file.by_type("IfcWall")[0]
|
||||||
parent = ifcopenshell.util.element.get_parent(element)
|
parent = ifcopenshell.util.element.get_parent(element)
|
||||||
"""
|
"""
|
||||||
return (
|
parent = (
|
||||||
get_container(element, should_get_direct=True)
|
get_container(element, should_get_direct=True)
|
||||||
or get_aggregate(element)
|
or get_aggregate(element)
|
||||||
or get_nest(element)
|
or get_nest(element)
|
||||||
@@ -1268,6 +1272,16 @@ def get_parent(element: ifcopenshell.entity_instance) -> Union[ifcopenshell.enti
|
|||||||
or get_voided_element(element)
|
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]:
|
def get_filled_void(element: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]:
|
||||||
"""If the element is filling a void, get the void
|
"""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":
|
elif key == "container":
|
||||||
value = ifcopenshell.util.element.get_container(value)
|
value = ifcopenshell.util.element.get_container(value)
|
||||||
elif key == "space":
|
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":
|
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":
|
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":
|
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":
|
elif key == "parent":
|
||||||
value = ifcopenshell.util.element.get_parent(value)
|
value = ifcopenshell.util.element.get_parent(value)
|
||||||
elif key in ("types", "occurrences"):
|
elif key in ("types", "occurrences"):
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import ifcopenshell.api.sequence
|
|||||||
import ifcopenshell.api.spatial
|
import ifcopenshell.api.spatial
|
||||||
import ifcopenshell.api.style
|
import ifcopenshell.api.style
|
||||||
import ifcopenshell.api.type
|
import ifcopenshell.api.type
|
||||||
|
import ifcopenshell.api.feature
|
||||||
import ifcopenshell.guid
|
import ifcopenshell.guid
|
||||||
import ifcopenshell.util.element as subject
|
import ifcopenshell.util.element as subject
|
||||||
import test.bootstrap
|
import test.bootstrap
|
||||||
@@ -891,6 +892,35 @@ class TestGetlayers(test.bootstrap.IFC4, TestGetlayersIFC2X3):
|
|||||||
assert subject.get_layers(self.file, element) == [layer]
|
assert subject.get_layers(self.file, element) == [layer]
|
||||||
|
|
||||||
|
|
||||||
|
class TestGetParentIFC4(test.bootstrap.IFC4):
|
||||||
|
def test_getting_the_parent_of_an_element(self):
|
||||||
|
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
||||||
|
building = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcBuilding")
|
||||||
|
ifcopenshell.api.spatial.assign_container(self.file, products=[element], relating_structure=building)
|
||||||
|
assert subject.get_parent(element) == building
|
||||||
|
|
||||||
|
def test_getting_the_specific_parent_of_an_element(self):
|
||||||
|
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
||||||
|
building = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcBuilding")
|
||||||
|
storey = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcBuildingStorey")
|
||||||
|
ifcopenshell.api.aggregate.assign_object(self.file, products=[storey], relating_object=building)
|
||||||
|
ifcopenshell.api.spatial.assign_container(self.file, products=[element], relating_structure=storey)
|
||||||
|
assert subject.get_parent(element, ifc_class="IfcBuilding") == building
|
||||||
|
assert subject.get_parent(element, ifc_class="IfcSite") == None
|
||||||
|
|
||||||
|
def test_getting_the_specific_parent_of_an_element_via_voiding(self):
|
||||||
|
wall = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
||||||
|
building = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcBuilding")
|
||||||
|
ifcopenshell.api.spatial.assign_container(self.file, products=[wall], relating_structure=building)
|
||||||
|
opening = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcOpeningElement")
|
||||||
|
ifcopenshell.api.feature.add_feature(self.file, feature=opening, element=wall)
|
||||||
|
window = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWindow")
|
||||||
|
ifcopenshell.api.feature.add_filling(self.file, opening=opening, element=window)
|
||||||
|
assert subject.get_parent(window, ifc_class="IfcWall") == wall
|
||||||
|
assert subject.get_parent(window, ifc_class="IfcBuilding") == building
|
||||||
|
assert subject.get_parent(window, ifc_class="IfcSite") == None
|
||||||
|
|
||||||
|
|
||||||
class TestGetContainerIFC4(test.bootstrap.IFC4):
|
class TestGetContainerIFC4(test.bootstrap.IFC4):
|
||||||
def test_getting_the_spatial_container_of_an_element(self):
|
def test_getting_the_spatial_container_of_an_element(self):
|
||||||
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
element = ifcopenshell.api.root.create_entity(self.file, ifc_class="IfcWall")
|
||||||
|
|||||||
Reference in New Issue
Block a user