Fix #3948. Bug where IfcTester PartOf facet didn't correctly read entity XML.

This commit is contained in:
Dion Moult
2023-11-02 12:28:53 +11:00
parent 611f7518d0
commit f40281e979
2 changed files with 50 additions and 48 deletions
+21 -21
View File
@@ -354,23 +354,23 @@ class Classification(Facet):
class PartOf(Facet): class PartOf(Facet):
def __init__( def __init__(
self, self,
entity="IFCWALL", name="IFCWALL",
predefinedType=None, predefinedType=None,
relation=None, relation=None,
minOccurs=None, minOccurs=None,
maxOccurs="unbounded", maxOccurs="unbounded",
instructions=None, instructions=None,
): ):
self.parameters = ["entity", "predefinedType", "@relation", "@minOccurs", "@maxOccurs", "@instructions"] self.parameters = ["name", "predefinedType", "@relation", "@minOccurs", "@maxOccurs", "@instructions"]
self.applicability_templates = [ self.applicability_templates = [
"An element with an {relation} relationship with an {entity}", "An element with an {relation} relationship with an {name}",
"An element with an {relation} relationship", "An element with an {relation} relationship",
] ]
self.requirement_templates = [ self.requirement_templates = [
"An element must have an {relation} relationship with an {entity}", "An element must have an {relation} relationship with an {name}",
"An element must have an {relation} relationship", "An element must have an {relation} relationship",
] ]
super().__init__(entity, predefinedType, relation, minOccurs, maxOccurs, instructions) super().__init__(name, predefinedType, relation, minOccurs, maxOccurs, instructions)
def filter(self, ifc_file, elements): def filter(self, ifc_file, elements):
if isinstance(elements, list): if isinstance(elements, list):
@@ -380,9 +380,9 @@ class PartOf(Facet):
def asdict(self): def asdict(self):
results = super().asdict() results = super().asdict()
entity = {} entity = {}
if "entity" in results: if "name" in results:
entity["name"] = results["entity"] entity["name"] = results["name"]
del results["entity"] del results["name"]
if "predefinedType" in results: if "predefinedType" in results:
entity["predefinedType"] = results["predefinedType"] entity["predefinedType"] = results["predefinedType"]
del results["predefinedType"] del results["predefinedType"]
@@ -407,7 +407,7 @@ class PartOf(Facet):
parent = self.get_parent(inst) parent = self.get_parent(inst)
while parent: while parent:
ancestors.append(parent.is_a()) ancestors.append(parent.is_a())
if parent.is_a().upper() == self.entity: if parent.is_a().upper() == self.name:
if self.predefinedType: if self.predefinedType:
if ifcopenshell.util.element.get_predefined_type(parent) == self.predefinedType: if ifcopenshell.util.element.get_predefined_type(parent) == self.predefinedType:
is_pass = True is_pass = True
@@ -422,12 +422,12 @@ class PartOf(Facet):
is_pass = aggregate is not None is_pass = aggregate is not None
if not is_pass: if not is_pass:
reason = {"type": "NOVALUE"} reason = {"type": "NOVALUE"}
if is_pass and self.entity: if is_pass and self.name:
is_pass = False is_pass = False
ancestors = [] ancestors = []
while aggregate is not None: while aggregate is not None:
ancestors.append(aggregate.is_a()) ancestors.append(aggregate.is_a())
if aggregate.is_a().upper() == self.entity: if aggregate.is_a().upper() == self.name:
if self.predefinedType: if self.predefinedType:
if ifcopenshell.util.element.get_predefined_type(aggregate) == self.predefinedType: if ifcopenshell.util.element.get_predefined_type(aggregate) == self.predefinedType:
is_pass = True is_pass = True
@@ -446,8 +446,8 @@ class PartOf(Facet):
is_pass = group is not None is_pass = group is not None
if not is_pass: if not is_pass:
reason = {"type": "NOVALUE"} reason = {"type": "NOVALUE"}
if is_pass and self.entity: if is_pass and self.name:
if group.is_a().upper() != self.entity: if group.is_a().upper() != self.name:
is_pass = False is_pass = False
reason = {"type": "ENTITY", "actual": group.is_a().upper()} reason = {"type": "ENTITY", "actual": group.is_a().upper()}
if self.predefinedType: if self.predefinedType:
@@ -460,8 +460,8 @@ class PartOf(Facet):
is_pass = container is not None is_pass = container is not None
if not is_pass: if not is_pass:
reason = {"type": "NOVALUE"} reason = {"type": "NOVALUE"}
if is_pass and self.entity: if is_pass and self.name:
if container.is_a().upper() != self.entity: if container.is_a().upper() != self.name:
is_pass = False is_pass = False
reason = {"type": "ENTITY", "actual": container.is_a().upper()} reason = {"type": "ENTITY", "actual": container.is_a().upper()}
if self.predefinedType: if self.predefinedType:
@@ -474,12 +474,12 @@ class PartOf(Facet):
is_pass = nest is not None is_pass = nest is not None
if not is_pass: if not is_pass:
reason = {"type": "NOVALUE"} reason = {"type": "NOVALUE"}
if is_pass and self.entity: if is_pass and self.name:
is_pass = False is_pass = False
ancestors = [] ancestors = []
while nest is not None: while nest is not None:
ancestors.append(nest.is_a()) ancestors.append(nest.is_a())
if nest.is_a().upper() == self.entity: if nest.is_a().upper() == self.name:
if self.predefinedType: if self.predefinedType:
if ifcopenshell.util.element.get_predefined_type(nest) == self.predefinedType: if ifcopenshell.util.element.get_predefined_type(nest) == self.predefinedType:
is_pass = True is_pass = True
@@ -494,9 +494,9 @@ class PartOf(Facet):
is_pass = building_element is not None is_pass = building_element is not None
if not is_pass: if not is_pass:
reason = {"type": "NOVALUE"} reason = {"type": "NOVALUE"}
if is_pass and self.entity: if is_pass and self.name:
is_pass = False is_pass = False
if building_element.is_a().upper() == self.entity: if building_element.is_a().upper() == self.name:
if self.predefinedType: if self.predefinedType:
if ifcopenshell.util.element.get_predefined_type(building_element) == self.predefinedType: if ifcopenshell.util.element.get_predefined_type(building_element) == self.predefinedType:
is_pass = True is_pass = True
@@ -509,9 +509,9 @@ class PartOf(Facet):
is_pass = opening is not None is_pass = opening is not None
if not is_pass: if not is_pass:
reason = {"type": "NOVALUE"} reason = {"type": "NOVALUE"}
if is_pass and self.entity: if is_pass and self.name:
is_pass = False is_pass = False
if opening.is_a().upper() == self.entity: if opening.is_a().upper() == self.name:
if self.predefinedType: if self.predefinedType:
if ifcopenshell.util.element.get_predefined_type(opening) == self.predefinedType: if ifcopenshell.util.element.get_predefined_type(opening) == self.predefinedType:
is_pass = True is_pass = True
+29 -27
View File
@@ -20,6 +20,7 @@
import uuid import uuid
import ifcopenshell import ifcopenshell
import ifcopenshell.api import ifcopenshell.api
import ifctester.facet
from ifctester.facet import Entity, Attribute, Classification, Property, PartOf, Material, Restriction from ifctester.facet import Entity, Attribute, Classification, Property, PartOf, Material, Restriction
@@ -28,6 +29,8 @@ def set_facet(facet):
def run(name, *, facet, inst, expected): def run(name, *, facet, inst, expected):
ifctester.facet.get_pset.cache_clear()
ifctester.facet.get_psets.cache_clear()
assert bool(facet(inst)) is expected assert bool(facet(inst)) is expected
@@ -76,7 +79,6 @@ class TestEntity:
expected=False, expected=False,
) )
# TODO But in that case why are the enumerations for things like partOf using the IFC capitalisation?
facet = Entity(name="IfcWall") facet = Entity(name="IfcWall")
ifc = ifcopenshell.file() ifc = ifcopenshell.file()
run( run(
@@ -1406,7 +1408,7 @@ class TestPartOf:
facet = PartOf() facet = PartOf()
assert facet.asdict() == {"entity": {"name": {"simpleValue": "IFCWALL"}}, "@maxOccurs": "unbounded" } assert facet.asdict() == {"entity": {"name": {"simpleValue": "IFCWALL"}}, "@maxOccurs": "unbounded" }
facet = PartOf( facet = PartOf(
entity="IFCGROUP", name="IFCGROUP",
predefinedType="predefinedType", predefinedType="predefinedType",
relation="IFCRELASSIGNSTOGROUP", relation="IFCRELASSIGNSTOGROUP",
minOccurs="0", minOccurs="0",
@@ -1431,16 +1433,16 @@ class TestPartOf:
element = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcElementAssembly") element = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcElementAssembly")
subelement = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcWall") subelement = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcWall")
facet = PartOf(entity="IFCELEMENTASSEMBLY", relation="IFCRELAGGREGATES") facet = PartOf(name="IFCELEMENTASSEMBLY", relation="IFCRELAGGREGATES")
run("A non aggregated element fails an aggregate relationship", facet=facet, inst=subelement, expected=False) run("A non aggregated element fails an aggregate relationship", facet=facet, inst=subelement, expected=False)
ifcopenshell.api.run("aggregate.assign_object", ifc, product=subelement, relating_object=element) ifcopenshell.api.run("aggregate.assign_object", ifc, product=subelement, relating_object=element)
run("The aggregated whole fails an aggregate relationship", facet=facet, inst=element, expected=False) run("The aggregated whole fails an aggregate relationship", facet=facet, inst=element, expected=False)
run("The aggregated part passes an aggregate relationship", facet=facet, inst=subelement, expected=True) run("The aggregated part passes an aggregate relationship", facet=facet, inst=subelement, expected=True)
run("A required facet checks all parameters as normal", facet=facet, inst=subelement, expected=True) run("A required facet checks all parameters as normal", facet=facet, inst=subelement, expected=True)
facet = PartOf(entity="IFCELEMENTASSEMBLY", relation="IFCRELAGGREGATES", minOccurs=0, maxOccurs=0) facet = PartOf(name="IFCELEMENTASSEMBLY", relation="IFCRELAGGREGATES", minOccurs=0, maxOccurs=0)
run("A prohibited facet returns the opposite of a required facet", facet=facet, inst=subelement, expected=False) run("A prohibited facet returns the opposite of a required facet", facet=facet, inst=subelement, expected=False)
facet = PartOf(entity="IFCELEMENTASSEMBLY", relation="IFCRELAGGREGATES", minOccurs=0) facet = PartOf(name="IFCELEMENTASSEMBLY", relation="IFCRELAGGREGATES", minOccurs=0)
run("An optional facet always passes regardless of outcome 1/2", facet=facet, inst=element, expected=True) run("An optional facet always passes regardless of outcome 1/2", facet=facet, inst=element, expected=True)
run("An optional facet always passes regardless of outcome 2/2", facet=facet, inst=subelement, expected=True) run("An optional facet always passes regardless of outcome 2/2", facet=facet, inst=subelement, expected=True)
@@ -1448,17 +1450,17 @@ class TestPartOf:
element = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcSlab") element = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcSlab")
subelement = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcBeam") subelement = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcBeam")
ifcopenshell.api.run("aggregate.assign_object", ifc, product=subelement, relating_object=element) ifcopenshell.api.run("aggregate.assign_object", ifc, product=subelement, relating_object=element)
facet = PartOf(entity="IFCSLAB", relation="IFCRELAGGREGATES") facet = PartOf(name="IFCSLAB", relation="IFCRELAGGREGATES")
run("An aggregate may specify the entity of the whole 1/2", facet=facet, inst=subelement, expected=True) run("An aggregate may specify the entity of the whole 1/2", facet=facet, inst=subelement, expected=True)
facet = PartOf(entity="IFCWALL", relation="IFCRELAGGREGATES") facet = PartOf(name="IFCWALL", relation="IFCRELAGGREGATES")
run("An aggregate may specify the entity of the whole 2/2", facet=facet, inst=subelement, expected=False) run("An aggregate may specify the entity of the whole 2/2", facet=facet, inst=subelement, expected=False)
element.PredefinedType = "BASESLAB" element.PredefinedType = "BASESLAB"
facet = PartOf(entity="IFCSLAB", predefinedType="BASESLAB", relation="IFCRELAGGREGATES") facet = PartOf(name="IFCSLAB", predefinedType="BASESLAB", relation="IFCRELAGGREGATES")
run( run(
"An aggregate may specify the predefined type of the whole 1/2", facet=facet, inst=subelement, expected=True "An aggregate may specify the predefined type of the whole 1/2", facet=facet, inst=subelement, expected=True
) )
facet = PartOf(entity="IFCSLAB", predefinedType="SLABRADOR", relation="IFCRELAGGREGATES") facet = PartOf(name="IFCSLAB", predefinedType="SLABRADOR", relation="IFCRELAGGREGATES")
run( run(
"An aggregate may specify the predefined type of the whole 2/2", "An aggregate may specify the predefined type of the whole 2/2",
facet=facet, facet=facet,
@@ -1472,13 +1474,13 @@ class TestPartOf:
subsubelement = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcBeam") subsubelement = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcBeam")
ifcopenshell.api.run("aggregate.assign_object", ifc, product=subelement, relating_object=element) ifcopenshell.api.run("aggregate.assign_object", ifc, product=subelement, relating_object=element)
ifcopenshell.api.run("aggregate.assign_object", ifc, product=subsubelement, relating_object=subelement) ifcopenshell.api.run("aggregate.assign_object", ifc, product=subsubelement, relating_object=subelement)
facet = PartOf(entity="IFCELEMENTASSEMBLY", relation="IFCRELAGGREGATES") facet = PartOf(name="IFCELEMENTASSEMBLY", relation="IFCRELAGGREGATES")
run("An aggregate entity may pass any ancestral whole passes", facet=facet, inst=subsubelement, expected=True) run("An aggregate entity may pass any ancestral whole passes", facet=facet, inst=subsubelement, expected=True)
ifc = ifcopenshell.file() ifc = ifcopenshell.file()
element = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcElementAssembly") element = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcElementAssembly")
group = ifcopenshell.api.run("group.add_group", ifc) group = ifcopenshell.api.run("group.add_group", ifc)
facet = PartOf(entity="IFCGROUP", relation="IFCRELASSIGNSTOGROUP") facet = PartOf(name="IFCGROUP", relation="IFCRELASSIGNSTOGROUP")
run("A non grouped element fails a group relationship", facet=facet, inst=element, expected=False) run("A non grouped element fails a group relationship", facet=facet, inst=element, expected=False)
ifcopenshell.api.run("group.assign_group", ifc, products=[element], group=group) ifcopenshell.api.run("group.assign_group", ifc, products=[element], group=group)
run("A grouped element passes a group relationship", facet=facet, inst=element, expected=True) run("A grouped element passes a group relationship", facet=facet, inst=element, expected=True)
@@ -1486,22 +1488,22 @@ class TestPartOf:
ifc = ifcopenshell.file() ifc = ifcopenshell.file()
element = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcElementAssembly") element = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcElementAssembly")
group = ifc.createIfcInventory() group = ifc.createIfcInventory()
facet = PartOf(entity="IFCGROUP", relation="IFCRELASSIGNSTOGROUP") facet = PartOf(name="IFCGROUP", relation="IFCRELASSIGNSTOGROUP")
ifcopenshell.api.run("group.assign_group", ifc, products=[element], group=group) ifcopenshell.api.run("group.assign_group", ifc, products=[element], group=group)
run("A group entity must match exactly 1/2", facet=facet, inst=element, expected=False) run("A group entity must match exactly 1/2", facet=facet, inst=element, expected=False)
facet = PartOf(entity="IFCINVENTORY", relation="IFCRELASSIGNSTOGROUP") facet = PartOf(name="IFCINVENTORY", relation="IFCRELASSIGNSTOGROUP")
run("A group entity must match exactly 2/2", facet=facet, inst=element, expected=True) run("A group entity must match exactly 2/2", facet=facet, inst=element, expected=True)
group.ObjectType = "BUNNY" group.ObjectType = "BUNNY"
facet = PartOf(entity="IFCINVENTORY", predefinedType="BUNNARY", relation="IFCRELASSIGNSTOGROUP") facet = PartOf(name="IFCINVENTORY", predefinedType="BUNNARY", relation="IFCRELASSIGNSTOGROUP")
run("A group predefined type must match exactly 2/2", facet=facet, inst=element, expected=False) run("A group predefined type must match exactly 2/2", facet=facet, inst=element, expected=False)
facet = PartOf(entity="IFCINVENTORY", predefinedType="BUNNY", relation="IFCRELASSIGNSTOGROUP") facet = PartOf(name="IFCINVENTORY", predefinedType="BUNNY", relation="IFCRELASSIGNSTOGROUP")
run("A group predefined type must match exactly 2/2", facet=facet, inst=element, expected=True) run("A group predefined type must match exactly 2/2", facet=facet, inst=element, expected=True)
ifc = ifcopenshell.file() ifc = ifcopenshell.file()
element = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcElementAssembly") element = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcElementAssembly")
container = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcSpace") container = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcSpace")
facet = PartOf(entity="IFCSPACE", relation="IFCRELCONTAINEDINSPATIALSTRUCTURE") facet = PartOf(name="IFCSPACE", relation="IFCRELCONTAINEDINSPATIALSTRUCTURE")
run("Any contained element passes a containment relationship 1/2", facet=facet, inst=element, expected=False) run("Any contained element passes a containment relationship 1/2", facet=facet, inst=element, expected=False)
ifcopenshell.api.run("spatial.assign_container", ifc, product=element, relating_structure=container) ifcopenshell.api.run("spatial.assign_container", ifc, product=element, relating_structure=container)
run("Any contained element passes a containment relationship 2/2", facet=facet, inst=element, expected=True) run("Any contained element passes a containment relationship 2/2", facet=facet, inst=element, expected=True)
@@ -1511,15 +1513,15 @@ class TestPartOf:
element = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcElementAssembly") element = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcElementAssembly")
container = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcSpace") container = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcSpace")
ifcopenshell.api.run("spatial.assign_container", ifc, product=element, relating_structure=container) ifcopenshell.api.run("spatial.assign_container", ifc, product=element, relating_structure=container)
facet = PartOf(relation="IFCRELCONTAINEDINSPATIALSTRUCTURE", entity="IFCSITE") facet = PartOf(relation="IFCRELCONTAINEDINSPATIALSTRUCTURE", name="IFCSITE")
run("The container entity must match exactly 1/2", facet=facet, inst=element, expected=False) run("The container entity must match exactly 1/2", facet=facet, inst=element, expected=False)
facet = PartOf(relation="IFCRELCONTAINEDINSPATIALSTRUCTURE", entity="IFCSPACE") facet = PartOf(relation="IFCRELCONTAINEDINSPATIALSTRUCTURE", name="IFCSPACE")
run("The container entity must match exactly 2/2", facet=facet, inst=element, expected=True) run("The container entity must match exactly 2/2", facet=facet, inst=element, expected=True)
container.ObjectType = "BURROW" container.ObjectType = "BURROW"
facet = PartOf(relation="IFCRELCONTAINEDINSPATIALSTRUCTURE", entity="IFCSPACE", predefinedType="WARREN") facet = PartOf(relation="IFCRELCONTAINEDINSPATIALSTRUCTURE", name="IFCSPACE", predefinedType="WARREN")
run("The container predefined type must match exactly 1/2", facet=facet, inst=element, expected=False) run("The container predefined type must match exactly 1/2", facet=facet, inst=element, expected=False)
facet = PartOf(relation="IFCRELCONTAINEDINSPATIALSTRUCTURE", entity="IFCSPACE", predefinedType="BURROW") facet = PartOf(relation="IFCRELCONTAINEDINSPATIALSTRUCTURE", name="IFCSPACE", predefinedType="BURROW")
run("The container predefined type must match exactly 2/2", facet=facet, inst=element, expected=True) run("The container predefined type must match exactly 2/2", facet=facet, inst=element, expected=True)
ifc = ifcopenshell.file() ifc = ifcopenshell.file()
@@ -1528,14 +1530,14 @@ class TestPartOf:
ifcopenshell.api.run("aggregate.assign_object", ifc, product=subelement, relating_object=element) ifcopenshell.api.run("aggregate.assign_object", ifc, product=subelement, relating_object=element)
container = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcSpace") container = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcSpace")
ifcopenshell.api.run("spatial.assign_container", ifc, product=element, relating_structure=container) ifcopenshell.api.run("spatial.assign_container", ifc, product=element, relating_structure=container)
facet = PartOf(relation="IFCRELCONTAINEDINSPATIALSTRUCTURE", entity="IFCSPACE") facet = PartOf(relation="IFCRELCONTAINEDINSPATIALSTRUCTURE", name="IFCSPACE")
run("The container may be indirect", facet=facet, inst=subelement, expected=True) run("The container may be indirect", facet=facet, inst=subelement, expected=True)
ifc = ifcopenshell.file() ifc = ifcopenshell.file()
element = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcFurniture") element = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcFurniture")
subelement = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcDiscreteAccessory") subelement = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcDiscreteAccessory")
ifcopenshell.api.run("nest.assign_object", ifc, related_object=subelement, relating_object=element) ifcopenshell.api.run("nest.assign_object", ifc, related_object=subelement, relating_object=element)
facet = PartOf(entity="IFCFURNITURE", relation="IFCRELNESTS") facet = PartOf(name="IFCFURNITURE", relation="IFCRELNESTS")
run("Any nested part passes a nest relationship", facet=facet, inst=subelement, expected=True) run("Any nested part passes a nest relationship", facet=facet, inst=subelement, expected=True)
run("Any nested whole fails a nest relationship", facet=facet, inst=element, expected=False) run("Any nested whole fails a nest relationship", facet=facet, inst=element, expected=False)
@@ -1543,16 +1545,16 @@ class TestPartOf:
element = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcFurniture") element = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcFurniture")
subelement = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcDiscreteAccessory") subelement = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcDiscreteAccessory")
ifcopenshell.api.run("nest.assign_object", ifc, related_object=subelement, relating_object=element) ifcopenshell.api.run("nest.assign_object", ifc, related_object=subelement, relating_object=element)
facet = PartOf(relation="IFCRELNESTS", entity="IFCBEAM") facet = PartOf(relation="IFCRELNESTS", name="IFCBEAM")
run("The nest entity must match exactly 1/2", facet=facet, inst=subelement, expected=False) run("The nest entity must match exactly 1/2", facet=facet, inst=subelement, expected=False)
facet = PartOf(relation="IFCRELNESTS", entity="IFCFURNITURE") facet = PartOf(relation="IFCRELNESTS", name="IFCFURNITURE")
run("The nest entity must match exactly 2/2", facet=facet, inst=subelement, expected=True) run("The nest entity must match exactly 2/2", facet=facet, inst=subelement, expected=True)
element.PredefinedType = "USERDEFINED" element.PredefinedType = "USERDEFINED"
element.ObjectType = "WATERBOTTLE" element.ObjectType = "WATERBOTTLE"
facet = PartOf(relation="IFCRELNESTS", entity="IFCFURNITURE", predefinedType="LITTERBOX") facet = PartOf(relation="IFCRELNESTS", name="IFCFURNITURE", predefinedType="LITTERBOX")
run("The nest predefined type must match exactly 1/2", facet=facet, inst=subelement, expected=False) run("The nest predefined type must match exactly 1/2", facet=facet, inst=subelement, expected=False)
facet = PartOf(relation="IFCRELNESTS", entity="IFCFURNITURE", predefinedType="WATERBOTTLE") facet = PartOf(relation="IFCRELNESTS", name="IFCFURNITURE", predefinedType="WATERBOTTLE")
run("The nest predefined type must match exactly 2/2", facet=facet, inst=subelement, expected=True) run("The nest predefined type must match exactly 2/2", facet=facet, inst=subelement, expected=True)
ifc = ifcopenshell.file() ifc = ifcopenshell.file()
@@ -1561,7 +1563,7 @@ class TestPartOf:
subsubelement = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcMechanicalFastener") subsubelement = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcMechanicalFastener")
ifcopenshell.api.run("nest.assign_object", ifc, related_object=subelement, relating_object=element) ifcopenshell.api.run("nest.assign_object", ifc, related_object=subelement, relating_object=element)
ifcopenshell.api.run("nest.assign_object", ifc, related_object=subsubelement, relating_object=subelement) ifcopenshell.api.run("nest.assign_object", ifc, related_object=subsubelement, relating_object=subelement)
facet = PartOf(relation="IFCRELNESTS", entity="IFCFURNITURE") facet = PartOf(relation="IFCRELNESTS", name="IFCFURNITURE")
run("Nesting may be indirect", facet=facet, inst=subsubelement, expected=True) run("Nesting may be indirect", facet=facet, inst=subsubelement, expected=True)