spatial.assign_container - support batching #4474

This commit is contained in:
Andrej730
2024-04-05 14:57:11 +05:00
parent 78abca16e6
commit 109787d869
32 changed files with 157 additions and 119 deletions
+1 -1
View File
@@ -47,7 +47,7 @@ def unassign_object(ifc, aggregate, collector, relating_obj=None, related_obj=No
if relating_obj: if relating_obj:
ifc.run("aggregate.unassign_object", product=related_element) ifc.run("aggregate.unassign_object", product=related_element)
if container: if container:
ifc.run("spatial.assign_container", product=related_element, relating_structure=container) ifc.run("spatial.assign_container", products=[related_element], relating_structure=container)
collector.assign(relating_obj) collector.assign(relating_obj)
collector.assign(related_obj) collector.assign(related_obj)
+1 -1
View File
@@ -47,7 +47,7 @@ def unassign_object(ifc, nest, collector, relating_obj=None, related_obj=None):
if relating_obj: if relating_obj:
ifc.run("nest.unassign_object", related_object=related_element) ifc.run("nest.unassign_object", related_object=related_element)
if container: if container:
ifc.run("spatial.assign_container", product=related_element, relating_structure=container) ifc.run("spatial.assign_container", products=[related_element], relating_structure=container)
collector.assign(relating_obj) collector.assign(relating_obj)
collector.assign(related_obj) collector.assign(related_obj)
+1 -1
View File
@@ -56,7 +56,7 @@ def assign_container(
return return
rel = ifc.run( rel = ifc.run(
"spatial.assign_container", "spatial.assign_container",
product=ifc.get_entity(element_obj), products=[ifc.get_entity(element_obj)],
relating_structure=ifc.get_entity(structure_obj), relating_structure=ifc.get_entity(structure_obj),
) )
spatial.disable_editing(element_obj) spatial.disable_editing(element_obj)
+3 -1
View File
@@ -85,7 +85,9 @@ class Obj2Ifc:
Name=mesh.label() or self.basename, Name=mesh.label() or self.basename,
Representation=representation, Representation=representation,
) )
ifcopenshell.api.run("spatial.assign_container", self.file, product=product, relating_structure=self.storey) ifcopenshell.api.run(
"spatial.assign_container", self.file, products=[product], relating_structure=self.storey
)
product.ObjectPlacement = self.placement product.ObjectPlacement = self.placement
self.file.write(self.outfile) self.file.write(self.outfile)
+3 -1
View File
@@ -79,7 +79,9 @@ class Obj2Ifc:
Name=mesh.name or self.basename, Name=mesh.name or self.basename,
Representation=representation, Representation=representation,
) )
ifcopenshell.api.run("spatial.assign_container", self.file, product=product, relating_structure=self.storey) ifcopenshell.api.run(
"spatial.assign_container", self.file, products=[product], relating_structure=self.storey
)
product.ObjectPlacement = self.placement product.ObjectPlacement = self.placement
self.file.write(self.outfile) self.file.write(self.outfile)
+1 -1
View File
@@ -53,7 +53,7 @@ class TestUnassignObject:
def test_run(self, ifc, aggregate, collector): def test_run(self, ifc, aggregate, collector):
ifc.get_entity("related_obj").should_be_called().will_return("element") ifc.get_entity("related_obj").should_be_called().will_return("element")
aggregate.get_container("element").should_be_called().will_return("container") aggregate.get_container("element").should_be_called().will_return("container")
ifc.run("spatial.assign_container", product="element", relating_structure="container").should_be_called() ifc.run("spatial.assign_container", products=["element"], relating_structure="container").should_be_called()
ifc.run("aggregate.unassign_object", product="element").should_be_called().will_return("rel") ifc.run("aggregate.unassign_object", product="element").should_be_called().will_return("rel")
collector.assign("relating_obj").should_be_called() collector.assign("relating_obj").should_be_called()
collector.assign("related_obj").should_be_called() collector.assign("related_obj").should_be_called()
+1 -1
View File
@@ -52,7 +52,7 @@ class TestUnassignObject:
def test_run(self, ifc, nest, collector): def test_run(self, ifc, nest, collector):
ifc.get_entity("related_obj").should_be_called().will_return("element") ifc.get_entity("related_obj").should_be_called().will_return("element")
nest.get_container("element").should_be_called().will_return("container") nest.get_container("element").should_be_called().will_return("container")
ifc.run("spatial.assign_container", product="element", relating_structure="container").should_be_called() ifc.run("spatial.assign_container", products=["element"], relating_structure="container").should_be_called()
ifc.run("nest.unassign_object", related_object="element").should_be_called().will_return("rel") ifc.run("nest.unassign_object", related_object="element").should_be_called().will_return("rel")
collector.assign("relating_obj").should_be_called() collector.assign("relating_obj").should_be_called()
collector.assign("related_obj").should_be_called() collector.assign("related_obj").should_be_called()
+1 -1
View File
@@ -40,7 +40,7 @@ class TestAssignContainer:
ifc.get_entity("structure_obj").should_be_called().will_return("structure") ifc.get_entity("structure_obj").should_be_called().will_return("structure")
ifc.get_entity("element_obj").should_be_called().will_return("element") ifc.get_entity("element_obj").should_be_called().will_return("element")
ifc.run( ifc.run(
"spatial.assign_container", product="element", relating_structure="structure" "spatial.assign_container", products=["element"], relating_structure="structure"
).should_be_called().will_return("rel") ).should_be_called().will_return("rel")
spatial.disable_editing("element_obj").should_be_called() spatial.disable_editing("element_obj").should_be_called()
collector.assign("element_obj").should_be_called() collector.assign("element_obj").should_be_called()
+1 -1
View File
@@ -125,5 +125,5 @@ class TestGetContainer(NewFile):
tool.Ifc.set(ifc) tool.Ifc.set(ifc)
element = ifc.createIfcWall() element = ifc.createIfcWall()
container = ifc.createIfcBuildingStorey() container = ifc.createIfcBuildingStorey()
ifcopenshell.api.run("spatial.assign_container", ifc, product=element, relating_structure=container) ifcopenshell.api.run("spatial.assign_container", ifc, products=[element], relating_structure=container)
assert subject.get_container(element) == container assert subject.get_container(element) == container
+4 -4
View File
@@ -41,7 +41,7 @@ class TestAssign(NewFile):
ifcopenshell.api.run( ifcopenshell.api.run(
"spatial.assign_container", "spatial.assign_container",
tool.Ifc.get(), tool.Ifc.get(),
product=wall_element, products=[wall_element],
relating_structure=tool.Ifc.get().by_type("IfcSite")[0], relating_structure=tool.Ifc.get().by_type("IfcSite")[0],
) )
subject.assign(wall_obj) subject.assign(wall_obj)
@@ -196,7 +196,7 @@ class TestAssign(NewFile):
ifcopenshell.api.run( ifcopenshell.api.run(
"spatial.assign_container", "spatial.assign_container",
tool.Ifc.get(), tool.Ifc.get(),
product=element, products=[element],
relating_structure=tool.Ifc.get().by_type("IfcSite")[0], relating_structure=tool.Ifc.get().by_type("IfcSite")[0],
) )
ifcopenshell.api.run( ifcopenshell.api.run(
@@ -236,7 +236,7 @@ class TestAssign(NewFile):
ifcopenshell.api.run( ifcopenshell.api.run(
"spatial.assign_container", "spatial.assign_container",
tool.Ifc.get(), tool.Ifc.get(),
product=element, products=[element],
relating_structure=tool.Ifc.get().by_type("IfcSite")[0], relating_structure=tool.Ifc.get().by_type("IfcSite")[0],
) )
bpy.context.scene.collection.objects.link(element_obj) bpy.context.scene.collection.objects.link(element_obj)
@@ -255,7 +255,7 @@ class TestAssign(NewFile):
ifcopenshell.api.run( ifcopenshell.api.run(
"spatial.assign_container", "spatial.assign_container",
tool.Ifc.get(), tool.Ifc.get(),
product=element, products=[element],
relating_structure=tool.Ifc.get().by_type("IfcSite")[0], relating_structure=tool.Ifc.get().by_type("IfcSite")[0],
) )
bpy.context.scene.collection.objects.link(element_obj) bpy.context.scene.collection.objects.link(element_obj)
+2 -2
View File
@@ -40,7 +40,7 @@ class TestGetObjectStorey(test.bim.bootstrap.NewFile):
wall = ifc.createIfcWall() wall = ifc.createIfcWall()
tool.Ifc.link(wall, obj) tool.Ifc.link(wall, obj)
storey = ifc.createIfcBuildingStorey() storey = ifc.createIfcBuildingStorey()
ifcopenshell.api.run("spatial.assign_container", ifc, product=wall, relating_structure=storey) ifcopenshell.api.run("spatial.assign_container", ifc, products=[wall], relating_structure=storey)
assert subject.get_object_storey(obj) == storey assert subject.get_object_storey(obj) == storey
def test_only_returning_a_building_storey(self): def test_only_returning_a_building_storey(self):
@@ -50,7 +50,7 @@ class TestGetObjectStorey(test.bim.bootstrap.NewFile):
wall = ifc.createIfcWall() wall = ifc.createIfcWall()
tool.Ifc.link(wall, obj) tool.Ifc.link(wall, obj)
building = ifc.createIfcBuilding() building = ifc.createIfcBuilding()
ifcopenshell.api.run("spatial.assign_container", ifc, product=wall, relating_structure=building) ifcopenshell.api.run("spatial.assign_container", ifc, products=[wall], relating_structure=building)
assert subject.get_object_storey(obj) is None assert subject.get_object_storey(obj) is None
def test_returning_nothing_if_uncontained(self): def test_returning_nothing_if_uncontained(self):
+1 -1
View File
@@ -70,5 +70,5 @@ class TestGetContainer(NewFile):
tool.Ifc.set(ifc) tool.Ifc.set(ifc)
element = ifc.createIfcWall() element = ifc.createIfcWall()
container = ifc.createIfcBuildingStorey() container = ifc.createIfcBuildingStorey()
ifcopenshell.api.run("spatial.assign_container", ifc, product=element, relating_structure=container) ifcopenshell.api.run("spatial.assign_container", ifc, products=[element], relating_structure=container)
assert subject.get_container(element) == container assert subject.get_container(element) == container
+3 -3
View File
@@ -154,7 +154,7 @@ class TestGetContainer(NewFile):
ifc = ifcopenshell.file() ifc = ifcopenshell.file()
site = ifc.createIfcSite() site = ifc.createIfcSite()
wall = ifc.createIfcWall() wall = ifc.createIfcWall()
ifcopenshell.api.run("spatial.assign_container", ifc, product=wall, relating_structure=site) ifcopenshell.api.run("spatial.assign_container", ifc, products=[wall], relating_structure=site)
assert subject.get_container(wall) == site assert subject.get_container(wall) == site
@@ -163,7 +163,7 @@ class TestGetDecomposedElements(NewFile):
ifc = ifcopenshell.file() ifc = ifcopenshell.file()
site = ifc.createIfcSite() site = ifc.createIfcSite()
wall = ifc.createIfcWall() wall = ifc.createIfcWall()
ifcopenshell.api.run("spatial.assign_container", ifc, product=wall, relating_structure=site) ifcopenshell.api.run("spatial.assign_container", ifc, products=[wall], relating_structure=site)
assert subject.get_decomposed_elements(site) == [wall] assert subject.get_decomposed_elements(site) == [wall]
@@ -268,4 +268,4 @@ class TestSelectProducts(NewFile):
bpy.context.scene.collection.objects.link(obj) bpy.context.scene.collection.objects.link(obj)
tool.Ifc.link(product, obj) tool.Ifc.link(product, obj)
subject.select_products([product]) subject.select_products([product])
assert obj in bpy.context.selected_objects assert obj in bpy.context.selected_objects
@@ -20,11 +20,17 @@ import ifcopenshell
import ifcopenshell.api import ifcopenshell.api
import ifcopenshell.util.element import ifcopenshell.util.element
import ifcopenshell.util.placement import ifcopenshell.util.placement
from typing import Union
class Usecase: class Usecase:
def __init__(self, file, product=None, relating_structure=None): def __init__(
"""Assigns a product to be contained hierarchically in a space self,
file: ifcopenshell.file,
products: list[ifcopenshell.entity_instance],
relating_structure: ifcopenshell.entity_instance,
):
"""Assigns products to be contained hierarchically in a space
All physical IFC model elements must be part of a hierarchical tree All physical IFC model elements must be part of a hierarchical tree
called the "spatial decomposition", where large things are made up of called the "spatial decomposition", where large things are made up of
@@ -61,13 +67,14 @@ class Usecase:
decomposition" tree, assigning an aggregate relationship will remove any decomposition" tree, assigning an aggregate relationship will remove any
previous aggregation, containment, or nesting relationships it may have. previous aggregation, containment, or nesting relationships it may have.
:param product: The physical IfcElement that exists in the space. :param products: A list of physical IfcElements existing in the space.
:type product: ifcopenshell.entity_instance.entity_instance :type products: list[ifcopenshell.entity_instance.entity_instance]
:param relating_structure: The IfcSpatialStructureElement element, such :param relating_structure: The IfcSpatialStructureElement element, such
as IfcBuilding, IfcBuildingStorey, or IfcSpace that the element as IfcBuilding, IfcBuildingStorey, or IfcSpace that the element
exists in. exists in.
:return: The IfcRelContainedInSpatialStructure relationship instance :return: The IfcRelContainedInSpatialStructure relationship instance
:rtype: ifcopenshell.entity_instance.entity_instance or `None` if nothing was changed.
:rtype: Union[ifcopenshell.entity_instance.entity_instance, None]
Example: Example:
@@ -80,76 +87,98 @@ class Usecase:
space = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcSpace") space = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcSpace")
# The project contains a site (note that project aggregation is a special case in IFC) # The project contains a site (note that project aggregation is a special case in IFC)
ifcopenshell.api.run("aggregate.assign_object", model, product=site, relating_object=project) ifcopenshell.api.run("aggregate.assign_object", model, products=[site], relating_object=project)
# The site has a building, the building has a storey, and the storey has a space # The site has a building, the building has a storey, and the storey has a space
ifcopenshell.api.run("aggregate.assign_object", model, product=building, relating_object=site) ifcopenshell.api.run("aggregate.assign_object", model, products=[building], relating_object=site)
ifcopenshell.api.run("aggregate.assign_object", model, product=storey, relating_object=building) ifcopenshell.api.run("aggregate.assign_object", model, products=[storey], relating_object=building)
ifcopenshell.api.run("aggregate.assign_object", model, product=space, relating_object=storey) ifcopenshell.api.run("aggregate.assign_object", model, products=[space], relating_object=storey)
# Create a wall and furniture # Create a wall and furniture
wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall") wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")
furniture = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcFurniture") furniture = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcFurniture")
# The wall is in the storey, and the furniture is in the space # The wall is in the storey, and the furniture is in the space
ifcopenshell.api.run("spatial.assign_container", model, product=wall, relating_structure=storey) ifcopenshell.api.run("spatial.assign_container", model, products=[wall], relating_structure=storey)
ifcopenshell.api.run("spatial.assign_container", model, product=furniture, relating_structure=space) ifcopenshell.api.run("spatial.assign_container", model, products=[furniture], relating_structure=space)
""" """
self.file = file self.file = file
self.settings = { self.settings = {
"product": product, "products": products,
"relating_structure": relating_structure, "relating_structure": relating_structure,
} }
def execute(self): def execute(self) -> Union[ifcopenshell.entity_instance, None]:
contained_in_structure = self.settings["product"].ContainedInStructure if not self.settings["products"]:
contains_elements = self.settings["relating_structure"].ContainsElements
if contains_elements and contained_in_structure and contained_in_structure[0] == contains_elements[0]:
return return
aggregate = ifcopenshell.util.element.get_aggregate(self.settings["product"]) products = set(self.settings["products"])
if aggregate: relating_structure = self.settings["relating_structure"]
ifcopenshell.api.run( structure_rel = next(iter(relating_structure.ContainsElements), None)
"aggregate.unassign_object", self.file, product=self.settings["product"]
)
if contained_in_structure: previous_containers_rels: set[ifcopenshell.entity_instance] = set()
related_elements = list(contained_in_structure[0].RelatedElements) products_without_containers: list[ifcopenshell.entity_instance] = []
related_elements.remove(self.settings["product"]) products_with_containers: list[ifcopenshell.entity_instance] = []
# check if there is anything to change
for product in products:
product_rel = next(iter(product.ContainedInStructure), None)
if product_rel is None:
products_without_containers.append(product)
continue
if product_rel != structure_rel:
previous_containers_rels.add(product_rel)
products_with_containers.append(product)
# nothing to change
if not products_without_containers and not products_with_containers:
return
# can be either only aggregated or only contained at the same time
for product in products_without_containers:
aggregate = ifcopenshell.util.element.get_aggregate(product)
if aggregate:
ifcopenshell.api.run("aggregate.unassign_object", self.file, product=product)
# unassign elements from previous container
for rel in previous_containers_rels:
related_elements = set(rel.RelatedElements) - products
if related_elements: if related_elements:
contained_in_structure[0].RelatedElements = related_elements rel.RelatedElements = list(related_elements)
ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": contained_in_structure[0]}) ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": rel})
else: else:
history = contained_in_structure[0].OwnerHistory history = rel.OwnerHistory
self.file.remove(contained_in_structure[0]) self.file.remove(rel)
if history: if history:
ifcopenshell.util.element.remove_deep2(self.file, history) ifcopenshell.util.element.remove_deep2(self.file, history)
if contains_elements: # assign elements to a new container
related_elements = list(contains_elements[0].RelatedElements) if structure_rel:
related_elements.append(self.settings["product"]) structure_rel.RelatedElements = list(set(structure_rel.RelatedElements) | products)
contains_elements[0].RelatedElements = related_elements ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": structure_rel})
ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": contains_elements[0]})
else: else:
contains_elements = self.file.create_entity( structure_rel = self.file.create_entity(
"IfcRelContainedInSpatialStructure", "IfcRelContainedInSpatialStructure",
**{ **{
"GlobalId": ifcopenshell.guid.new(), "GlobalId": ifcopenshell.guid.new(),
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file), "OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file),
"RelatedElements": [self.settings["product"]], "RelatedElements": list(products),
"RelatingStructure": self.settings["relating_structure"], "RelatingStructure": self.settings["relating_structure"],
} }
) )
placement = getattr(self.settings["product"], "ObjectPlacement", None) # localize placement relative to a new container for affected products
if placement and placement.is_a("IfcLocalPlacement"): for product in products_without_containers + products_with_containers:
ifcopenshell.api.run( placement = getattr(product, "ObjectPlacement", None)
"geometry.edit_object_placement", if placement and placement.is_a("IfcLocalPlacement"):
self.file, ifcopenshell.api.run(
product=self.settings["product"], "geometry.edit_object_placement",
matrix=ifcopenshell.util.placement.get_local_placement(self.settings["product"].ObjectPlacement), self.file,
is_si=False, product=product,
) matrix=ifcopenshell.util.placement.get_local_placement(product.ObjectPlacement),
is_si=False,
)
return contains_elements return structure_rel
@@ -56,7 +56,7 @@ class Usecase:
column = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall") column = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")
# The column is contained in the lowermost storey # The column is contained in the lowermost storey
ifcopenshell.api.run("spatial.assign_container", model, product=column, relating_structure=storey1) ifcopenshell.api.run("spatial.assign_container", model, products=[column], relating_structure=storey1)
# And referenced in the others # And referenced in the others
ifcopenshell.api.run("spatial.reference_structure", model, product=column, relating_structure=storey2) ifcopenshell.api.run("spatial.reference_structure", model, product=column, relating_structure=storey2)
@@ -70,7 +70,7 @@ class Usecase:
column = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall") column = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")
# The column is contained in the lowermost storey # The column is contained in the lowermost storey
ifcopenshell.api.run("spatial.assign_container", model, product=column, relating_structure=storey1) ifcopenshell.api.run("spatial.assign_container", model, products=[column], relating_structure=storey1)
# And referenced in the others # And referenced in the others
ifcopenshell.api.run("spatial.reference_structure", model, product=column, relating_structure=storey2) ifcopenshell.api.run("spatial.reference_structure", model, product=column, relating_structure=storey2)
@@ -52,7 +52,7 @@ class Usecase:
wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall") wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")
# The wall is in the storey # The wall is in the storey
ifcopenshell.api.run("spatial.assign_container", model, product=wall, relating_structure=storey) ifcopenshell.api.run("spatial.assign_container", model, products=[wall], relating_structure=storey)
# Not anymore! # Not anymore!
ifcopenshell.api.run("spatial.remove_container", model, product=wall) ifcopenshell.api.run("spatial.remove_container", model, product=wall)
@@ -114,6 +114,6 @@ class TestAssignObject(test.bootstrap.IFC4):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcElementAssembly") element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcElementAssembly")
container = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuildingStorey") container = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuildingStorey")
subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement, relating_structure=container) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement], relating_structure=container)
ifcopenshell.api.run("aggregate.assign_object", self.file, product=subelement, relating_object=element) ifcopenshell.api.run("aggregate.assign_object", self.file, product=subelement, relating_object=element)
assert not ifcopenshell.util.element.get_container(subelement, should_get_direct=True) assert not ifcopenshell.util.element.get_container(subelement, should_get_direct=True)
@@ -172,7 +172,7 @@ class TestEditObjectPlacement(test.bootstrap.IFC4):
ifcopenshell.api.run("unit.assign_unit", self.file) ifcopenshell.api.run("unit.assign_unit", self.file)
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding")
subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement, relating_structure=element) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement], relating_structure=element)
matrix1 = numpy.array( matrix1 = numpy.array(
( (
(1.0, 0.0, 0.0, 1.0), (1.0, 0.0, 0.0, 1.0),
@@ -221,7 +221,7 @@ class TestEditObjectPlacement(test.bootstrap.IFC4):
(0.0, 0.0, 0.0, 1.0), (0.0, 0.0, 0.0, 1.0),
) )
) )
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement, relating_structure=element) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement], relating_structure=element)
ifcopenshell.api.run( ifcopenshell.api.run(
"geometry.edit_object_placement", self.file, product=element, matrix=matrix.copy(), is_si=False "geometry.edit_object_placement", self.file, product=element, matrix=matrix.copy(), is_si=False
) )
@@ -301,7 +301,7 @@ class TestEditObjectPlacement(test.bootstrap.IFC4):
site = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcSite") site = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcSite")
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcOpeningElement") subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcOpeningElement")
ifcopenshell.api.run("spatial.assign_container", self.file, product=element, relating_structure=site) ifcopenshell.api.run("spatial.assign_container", self.file, products=[element], relating_structure=site)
matrix = numpy.array( matrix = numpy.array(
( (
(1.0, 0.0, 0.0, 1.0), (1.0, 0.0, 0.0, 1.0),
@@ -336,8 +336,8 @@ class TestEditObjectPlacement(test.bootstrap.IFC4):
wall = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") wall = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcOpeningElement") element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcOpeningElement")
subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcDoor") subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcDoor")
ifcopenshell.api.run("spatial.assign_container", self.file, product=wall, relating_structure=site) ifcopenshell.api.run("spatial.assign_container", self.file, products=[wall], relating_structure=site)
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement, relating_structure=site) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement], relating_structure=site)
matrix = numpy.array( matrix = numpy.array(
( (
(1.0, 0.0, 0.0, 1.0), (1.0, 0.0, 0.0, 1.0),
@@ -435,7 +435,7 @@ class TestEditObjectPlacement(test.bootstrap.IFC4):
(0.0, 0.0, 0.0, 1.0), (0.0, 0.0, 0.0, 1.0),
) )
) )
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement, relating_structure=element) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement], relating_structure=element)
ifcopenshell.api.run( ifcopenshell.api.run(
"geometry.edit_object_placement", self.file, product=element, matrix=matrix.copy(), is_si=False "geometry.edit_object_placement", self.file, product=element, matrix=matrix.copy(), is_si=False
) )
@@ -478,7 +478,7 @@ class TestEditObjectPlacement(test.bootstrap.IFC4):
(0.0, 0.0, 0.0, 1.0), (0.0, 0.0, 0.0, 1.0),
) )
) )
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement, relating_structure=element) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement], relating_structure=element)
ifcopenshell.api.run( ifcopenshell.api.run(
"geometry.edit_object_placement", self.file, product=element, matrix=matrix.copy(), is_si=False "geometry.edit_object_placement", self.file, product=element, matrix=matrix.copy(), is_si=False
) )
@@ -528,7 +528,7 @@ class TestEditObjectPlacement(test.bootstrap.IFC4):
(0.0, 0.0, 0.0, 1.0), (0.0, 0.0, 0.0, 1.0),
) )
) )
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement, relating_structure=element) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement], relating_structure=element)
ifcopenshell.api.run( ifcopenshell.api.run(
"geometry.edit_object_placement", self.file, product=element, matrix=matrix.copy(), is_si=False "geometry.edit_object_placement", self.file, product=element, matrix=matrix.copy(), is_si=False
) )
@@ -631,7 +631,7 @@ class TestEditObjectPlacement(test.bootstrap.IFC4):
storey = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuildingStorey") storey = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuildingStorey")
ifcopenshell.api.run("aggregate.assign_object", self.file, product=storey, relating_object=building) ifcopenshell.api.run("aggregate.assign_object", self.file, product=storey, relating_object=building)
wall = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") wall = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
ifcopenshell.api.run("spatial.assign_container", self.file, product=wall, relating_structure=storey) ifcopenshell.api.run("spatial.assign_container", self.file, products=[wall], relating_structure=storey)
matrix = np_matrix_translation((1, 1, 1)) matrix = np_matrix_translation((1, 1, 1))
submatrix = np_matrix_translation((1, 2, 3)) submatrix = np_matrix_translation((1, 2, 3))
@@ -34,7 +34,7 @@ class TestCopyClass(test.bootstrap.IFC4):
ifcopenshell.api.run("unit.assign_unit", self.file) ifcopenshell.api.run("unit.assign_unit", self.file)
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding")
subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement, relating_structure=element) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement], relating_structure=element)
matrix = numpy.identity(4) matrix = numpy.identity(4)
ifcopenshell.api.run("geometry.edit_object_placement", self.file, product=element, matrix=matrix.copy()) ifcopenshell.api.run("geometry.edit_object_placement", self.file, product=element, matrix=matrix.copy())
ifcopenshell.api.run("geometry.edit_object_placement", self.file, product=subelement, matrix=matrix.copy()) ifcopenshell.api.run("geometry.edit_object_placement", self.file, product=subelement, matrix=matrix.copy())
@@ -74,7 +74,7 @@ class TestCopyClass(test.bootstrap.IFC4):
def test_copying_a_container_only_and_not_its_contents(self): def test_copying_a_container_only_and_not_its_contents(self):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding")
subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement, relating_structure=element) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement], relating_structure=element)
new = ifcopenshell.api.run("root.copy_class", self.file, product=element) new = ifcopenshell.api.run("root.copy_class", self.file, product=element)
assert element.ContainsElements assert element.ContainsElements
assert not new.ContainsElements assert not new.ContainsElements
@@ -82,7 +82,7 @@ class TestCopyClass(test.bootstrap.IFC4):
def test_copying_contents_of_a_container_and_maintaining_the_containment_relationship(self): def test_copying_contents_of_a_container_and_maintaining_the_containment_relationship(self):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding")
subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement, relating_structure=element) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement], relating_structure=element)
new = ifcopenshell.api.run("root.copy_class", self.file, product=subelement) new = ifcopenshell.api.run("root.copy_class", self.file, product=subelement)
assert new.ContainedInStructure[0].RelatingStructure == element assert new.ContainedInStructure[0].RelatingStructure == element
@@ -234,7 +234,7 @@ class TestRemoveProduct(test.bootstrap.IFC4):
def test_removing_all_containment_relationships_of_a_container(self): def test_removing_all_containment_relationships_of_a_container(self):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcSpace") element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcSpace")
subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement, relating_structure=element) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement], relating_structure=element)
total_entities = len(list(self.file)) total_entities = len(list(self.file))
ifcopenshell.api.run("root.remove_product", self.file, product=element) ifcopenshell.api.run("root.remove_product", self.file, product=element)
assert len(list(self.file)) == total_entities - 2 assert len(list(self.file)) == total_entities - 2
@@ -245,7 +245,7 @@ class TestRemoveProduct(test.bootstrap.IFC4):
def test_removing_all_containment_relationships_of_an_element(self): def test_removing_all_containment_relationships_of_an_element(self):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcSpace") element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcSpace")
subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement, relating_structure=element) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement], relating_structure=element)
total_entities = len(list(self.file)) total_entities = len(list(self.file))
ifcopenshell.api.run("root.remove_product", self.file, product=subelement) ifcopenshell.api.run("root.remove_product", self.file, product=subelement)
assert len(list(self.file)) == total_entities - 2 assert len(list(self.file)) == total_entities - 2
@@ -28,18 +28,20 @@ class TestAssignContainer(test.bootstrap.IFC4):
def test_assigning_a_container(self): def test_assigning_a_container(self):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding")
subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
subelement2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
rel = ifcopenshell.api.run( rel = ifcopenshell.api.run(
"spatial.assign_container", self.file, product=subelement, relating_structure=element "spatial.assign_container", self.file, products=[subelement, subelement2], relating_structure=element
) )
assert ifcopenshell.util.element.get_container(subelement) == element assert ifcopenshell.util.element.get_container(subelement) == element
assert ifcopenshell.util.element.get_container(subelement2) == element
assert rel.is_a("IfcRelContainedInSpatialStructure") assert rel.is_a("IfcRelContainedInSpatialStructure")
def test_doing_nothing_if_the_container_is_already_assigned(self): def test_doing_nothing_if_the_container_is_already_assigned(self):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding")
subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement, relating_structure=element) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement], relating_structure=element)
total_elements = len([e for e in self.file]) total_elements = len([e for e in self.file])
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement, relating_structure=element) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement], relating_structure=element)
assert len([e for e in self.file]) == total_elements assert len([e for e in self.file]) == total_elements
def test_that_old_containment_relationships_are_updated_if_they_still_contain_elements(self): def test_that_old_containment_relationships_are_updated_if_they_still_contain_elements(self):
@@ -47,20 +49,20 @@ class TestAssignContainer(test.bootstrap.IFC4):
element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding")
subelement1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") subelement1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
subelement2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") subelement2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement1, relating_structure=element1) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement1], relating_structure=element1)
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement2, relating_structure=element1) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement2], relating_structure=element1)
rel = subelement1.ContainedInStructure[0] rel = subelement1.ContainedInStructure[0]
assert len(rel.RelatedElements) == 2 assert len(rel.RelatedElements) == 2
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement1, relating_structure=element2) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement1], relating_structure=element2)
assert len(rel.RelatedElements) == 1 assert len(rel.RelatedElements) == 1
def test_that_old_containment_relationships_are_purged_if_no_more_elements_are_contained(self): def test_that_old_containment_relationships_are_purged_if_no_more_elements_are_contained(self):
element1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") element1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding")
element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding")
subelement1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") subelement1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement1, relating_structure=element1) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement1], relating_structure=element1)
rel_id = subelement1.ContainedInStructure[0].id() rel_id = subelement1.ContainedInStructure[0].id()
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement1, relating_structure=element2) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement1], relating_structure=element2)
with pytest.raises(RuntimeError): with pytest.raises(RuntimeError):
self.file.by_id(rel_id) self.file.by_id(rel_id)
@@ -70,7 +72,7 @@ class TestAssignContainer(test.bootstrap.IFC4):
element1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") element1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding")
element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding")
subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement, relating_structure=element1) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement], relating_structure=element1)
matrix1 = numpy.array( matrix1 = numpy.array(
( (
(1.0, 0.0, 0.0, 1.0), (1.0, 0.0, 0.0, 1.0),
@@ -96,7 +98,7 @@ class TestAssignContainer(test.bootstrap.IFC4):
ifcopenshell.api.run( ifcopenshell.api.run(
"geometry.edit_object_placement", self.file, product=subelement, matrix=matrix1.copy(), is_si=False "geometry.edit_object_placement", self.file, product=subelement, matrix=matrix1.copy(), is_si=False
) )
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement, relating_structure=element2) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement], relating_structure=element2)
assert subelement.ObjectPlacement.PlacementRelTo.PlacesObject[0] == element2 assert subelement.ObjectPlacement.PlacementRelTo.PlacesObject[0] == element2
assert numpy.array_equal(ifcopenshell.util.placement.get_local_placement(subelement.ObjectPlacement), matrix1) assert numpy.array_equal(ifcopenshell.util.placement.get_local_placement(subelement.ObjectPlacement), matrix1)
@@ -107,7 +109,7 @@ class TestAssignContainer(test.bootstrap.IFC4):
subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
placement = self.file.createIfcGridPlacement() placement = self.file.createIfcGridPlacement()
subelement.ObjectPlacement = placement subelement.ObjectPlacement = placement
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement, relating_structure=element) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement], relating_structure=element)
assert subelement.ObjectPlacement == placement assert subelement.ObjectPlacement == placement
def test_removing_aggregation_if_it_exists(self): def test_removing_aggregation_if_it_exists(self):
@@ -117,5 +119,5 @@ class TestAssignContainer(test.bootstrap.IFC4):
aggregate = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcElementAssembly") aggregate = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcElementAssembly")
subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
ifcopenshell.api.run("aggregate.assign_object", self.file, product=subelement, relating_object=aggregate) ifcopenshell.api.run("aggregate.assign_object", self.file, product=subelement, relating_object=aggregate)
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement, relating_structure=element) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement], relating_structure=element)
assert not ifcopenshell.util.element.get_aggregate(subelement) assert not ifcopenshell.util.element.get_aggregate(subelement)
@@ -28,7 +28,7 @@ class TestRemoveContainer(test.bootstrap.IFC4):
def test_removing_a_container(self): def test_removing_a_container(self):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding")
subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement, relating_structure=element) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement], relating_structure=element)
ifcopenshell.api.run("spatial.remove_container", self.file, product=subelement) ifcopenshell.api.run("spatial.remove_container", self.file, product=subelement)
assert ifcopenshell.util.element.get_container(subelement) is None assert ifcopenshell.util.element.get_container(subelement) is None
@@ -41,14 +41,14 @@ class TestRemoveContainer(test.bootstrap.IFC4):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding")
subelement1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") subelement1 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
subelement2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") subelement2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement1, relating_structure=element) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement1], relating_structure=element)
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement2, relating_structure=element) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement2], relating_structure=element)
ifcopenshell.api.run("spatial.remove_container", self.file, product=subelement1) ifcopenshell.api.run("spatial.remove_container", self.file, product=subelement1)
assert self.file.by_type("IfcRelContainedInSpatialStructure")[0].RelatedElements == (subelement2,) assert self.file.by_type("IfcRelContainedInSpatialStructure")[0].RelatedElements == (subelement2,)
def test_deleting_the_rel_when_a_container_is_removed_with_no_elements(self): def test_deleting_the_rel_when_a_container_is_removed_with_no_elements(self):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding")
subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement, relating_structure=element) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement], relating_structure=element)
ifcopenshell.api.run("spatial.remove_container", self.file, product=subelement) ifcopenshell.api.run("spatial.remove_container", self.file, product=subelement)
assert len(self.file.by_type("IfcRelContainedInSpatialStructure")) == 0 assert len(self.file.by_type("IfcRelContainedInSpatialStructure")) == 0
@@ -28,7 +28,7 @@ class TestAssignContainer(test.bootstrap.IFC4):
def test_unassigning_a_container(self): def test_unassigning_a_container(self):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding")
subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement, relating_structure=element) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement], relating_structure=element)
ifcopenshell.api.run("spatial.unassign_container", self.file, product=subelement) ifcopenshell.api.run("spatial.unassign_container", self.file, product=subelement)
assert not self.file.by_type("IfcRelContainedInSpatialStructure") assert not self.file.by_type("IfcRelContainedInSpatialStructure")
@@ -36,8 +36,8 @@ class TestAssignContainer(test.bootstrap.IFC4):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding")
subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
subelement2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") subelement2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement, relating_structure=element) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement], relating_structure=element)
ifcopenshell.api.run("spatial.assign_container", self.file, product=subelement2, relating_structure=element) ifcopenshell.api.run("spatial.assign_container", self.file, products=[subelement2], relating_structure=element)
ifcopenshell.api.run("spatial.unassign_container", self.file, product=subelement) ifcopenshell.api.run("spatial.unassign_container", self.file, product=subelement)
rel = self.file.by_type("IfcRelContainedInSpatialStructure")[0] rel = self.file.by_type("IfcRelContainedInSpatialStructure")[0]
assert list(rel.RelatedElements) == [subelement2] assert list(rel.RelatedElements) == [subelement2]
@@ -698,14 +698,14 @@ 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.run("root.create_entity", self.file, ifc_class="IfcWall") element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
building = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") building = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding")
ifcopenshell.api.run("spatial.assign_container", self.file, product=element, relating_structure=building) ifcopenshell.api.run("spatial.assign_container", self.file, products=[element], relating_structure=building)
assert subject.get_container(element) == building assert subject.get_container(element) == building
def test_getting_an_indirect_spatial_container_of_an_element(self): def test_getting_an_indirect_spatial_container_of_an_element(self):
subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcElementAssembly") element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcElementAssembly")
building = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") building = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding")
ifcopenshell.api.run("spatial.assign_container", self.file, product=element, relating_structure=building) ifcopenshell.api.run("spatial.assign_container", self.file, products=[element], relating_structure=building)
ifcopenshell.api.run("aggregate.assign_object", self.file, product=subelement, relating_object=element) ifcopenshell.api.run("aggregate.assign_object", self.file, product=subelement, relating_object=element)
assert subject.get_container(subelement) == building assert subject.get_container(subelement) == building
@@ -713,7 +713,7 @@ class TestGetContainerIFC4(test.bootstrap.IFC4):
subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcElementAssembly") element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcElementAssembly")
building = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") building = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding")
ifcopenshell.api.run("spatial.assign_container", self.file, product=element, relating_structure=building) ifcopenshell.api.run("spatial.assign_container", self.file, products=[element], relating_structure=building)
ifcopenshell.api.run("aggregate.assign_object", self.file, product=subelement, relating_object=element) ifcopenshell.api.run("aggregate.assign_object", self.file, product=subelement, relating_object=element)
assert subject.get_container(subelement, should_get_direct=True) is None assert subject.get_container(subelement, should_get_direct=True) is None
@@ -735,7 +735,7 @@ class TestGetDecompositionIFC4(test.bootstrap.IFC4):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcElementAssembly") element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcElementAssembly")
subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBeam") subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBeam")
building = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") building = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding")
ifcopenshell.api.run("spatial.assign_container", self.file, product=element, relating_structure=building) ifcopenshell.api.run("spatial.assign_container", self.file, products=[element], relating_structure=building)
ifcopenshell.api.run("aggregate.assign_object", self.file, product=subelement, relating_object=element) ifcopenshell.api.run("aggregate.assign_object", self.file, product=subelement, relating_object=element)
results = subject.get_decomposition(building) results = subject.get_decomposition(building)
assert element in results assert element in results
@@ -234,8 +234,8 @@ class TestFilterElements(test.bootstrap.IFC4):
storey = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuildingStorey", name="G") storey = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuildingStorey", name="G")
building = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding", name="Building") building = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding", name="Building")
project = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcProject", name="Project") project = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcProject", name="Project")
ifcopenshell.api.run("spatial.assign_container", self.file, product=element, relating_structure=space) ifcopenshell.api.run("spatial.assign_container", self.file, products=[element], relating_structure=space)
ifcopenshell.api.run("spatial.assign_container", self.file, product=element2, relating_structure=storey) ifcopenshell.api.run("spatial.assign_container", self.file, products=[element2], relating_structure=storey)
ifcopenshell.api.run("aggregate.assign_object", self.file, product=space, relating_object=storey) ifcopenshell.api.run("aggregate.assign_object", self.file, product=space, relating_object=storey)
ifcopenshell.api.run("aggregate.assign_object", self.file, product=storey, relating_object=building) ifcopenshell.api.run("aggregate.assign_object", self.file, product=storey, relating_object=building)
ifcopenshell.api.run("aggregate.assign_object", self.file, product=building, relating_object=project) ifcopenshell.api.run("aggregate.assign_object", self.file, product=building, relating_object=project)
@@ -468,7 +468,7 @@ class TestSelector(test.bootstrap.IFC4):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall") element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcMember") subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcMember")
building = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding") building = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding")
ifcopenshell.api.run("spatial.assign_container", self.file, product=element, relating_structure=building) ifcopenshell.api.run("spatial.assign_container", self.file, products=[element], relating_structure=building)
ifcopenshell.api.run("aggregate.assign_object", self.file, product=subelement, relating_object=element) ifcopenshell.api.run("aggregate.assign_object", self.file, product=subelement, relating_object=element)
assert set(subject.Selector.parse(self.file, "@ .IfcBuilding")) == {element, subelement} assert set(subject.Selector.parse(self.file, "@ .IfcBuilding")) == {element, subelement}
+2 -2
View File
@@ -44,7 +44,7 @@ class TestExtractElements:
wall = ifcopenshell.api.run("root.create_entity", ifc_file, ifc_class="IfcWall") wall = ifcopenshell.api.run("root.create_entity", ifc_file, ifc_class="IfcWall")
ifcopenshell.api.run("aggregate.assign_object", ifc_file, product=building, relating_object=site) ifcopenshell.api.run("aggregate.assign_object", ifc_file, product=building, relating_object=site)
ifcopenshell.api.run("aggregate.assign_object", ifc_file, product=storey, relating_object=building) ifcopenshell.api.run("aggregate.assign_object", ifc_file, product=storey, relating_object=building)
ifcopenshell.api.run("spatial.assign_container", ifc_file, product=wall, relating_structure=storey) ifcopenshell.api.run("spatial.assign_container", ifc_file, products=[wall], relating_structure=storey)
output = ifcpatch.execute({"file": ifc_file, "recipe": "ExtractElements", "arguments": ["IfcWall"]}) output = ifcpatch.execute({"file": ifc_file, "recipe": "ExtractElements", "arguments": ["IfcWall"]})
@@ -60,7 +60,7 @@ class TestExtractElements:
element = ifcopenshell.api.run("root.create_entity", ifc_file, ifc_class="IfcElementAssembly") element = ifcopenshell.api.run("root.create_entity", ifc_file, ifc_class="IfcElementAssembly")
container = ifcopenshell.api.run("root.create_entity", ifc_file, ifc_class="IfcBuildingStorey") container = ifcopenshell.api.run("root.create_entity", ifc_file, ifc_class="IfcBuildingStorey")
subelement = ifcopenshell.api.run("root.create_entity", ifc_file, ifc_class="IfcWall") subelement = ifcopenshell.api.run("root.create_entity", ifc_file, ifc_class="IfcWall")
ifcopenshell.api.run("spatial.assign_container", ifc_file, product=element, relating_structure=container) ifcopenshell.api.run("spatial.assign_container", ifc_file, products=[element], relating_structure=container)
ifcopenshell.api.run("aggregate.assign_object", ifc_file, product=subelement, relating_object=element) ifcopenshell.api.run("aggregate.assign_object", ifc_file, product=subelement, relating_object=element)
output = ifcpatch.execute({"file": ifc_file, "recipe": "ExtractElements", "arguments": ["IfcWall"]}) output = ifcpatch.execute({"file": ifc_file, "recipe": "ExtractElements", "arguments": ["IfcWall"]})
+4 -1
View File
@@ -190,7 +190,10 @@ class IFC_Sv_write_file(bpy.types.Operator):
for element in elements: for element in elements:
if element not in elements_in_buildings: if element not in elements_in_buildings:
ifcopenshell.api.run( ifcopenshell.api.run(
"spatial.assign_container", file, product=element, relating_structure=file.by_type("IfcBuilding")[0] "spatial.assign_container",
file,
products=[element],
relating_structure=file.by_type("IfcBuilding")[0],
) )
for building in file.by_type("IfcBuilding"): for building in file.by_type("IfcBuilding"):
@@ -142,7 +142,7 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
ifcopenshell.api.run( ifcopenshell.api.run(
"spatial.assign_container", "spatial.assign_container",
self.file, self.file,
product=items, products=[items],
relating_structure=result, relating_structure=result,
) )
SvIfcStore.id_map.setdefault(self.node_id, []).append(result.id()) SvIfcStore.id_map.setdefault(self.node_id, []).append(result.id())
@@ -195,7 +195,7 @@ class SvIfcAddSpatialElement(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
ifcopenshell.api.run( ifcopenshell.api.run(
"spatial.assign_container", "spatial.assign_container",
self.file, self.file,
product=added_element, products=[added_element],
relating_structure=result, relating_structure=result,
) )
spatial_ids.append(result.id()) spatial_ids.append(result.id())
+1 -1
View File
@@ -108,7 +108,7 @@ class SvIfcWriteFile(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.Sv
ifcopenshell.api.run( ifcopenshell.api.run(
"spatial.assign_container", "spatial.assign_container",
file, file,
product=element, products=[element],
relating_structure=file.by_type("IfcBuilding")[0], relating_structure=file.by_type("IfcBuilding")[0],
) )
+1 -1
View File
@@ -347,6 +347,6 @@ for i in range(0, 4):
location = np.eye(4) location = np.eye(4)
location[1][3] += i * 1 location[1][3] += i * 1
ifcopenshell.api.run("geometry.edit_object_placement", model, product=wall, matrix=location) ifcopenshell.api.run("geometry.edit_object_placement", model, product=wall, matrix=location)
ifcopenshell.api.run("spatial.assign_container", model, relating_structure=storey, product=wall) ifcopenshell.api.run("spatial.assign_container", model, relating_structure=storey, products=[wall])
model.write(os.path.join(outdir, "library", "sample.ifc")) model.write(os.path.join(outdir, "library", "sample.ifc"))
+3 -3
View File
@@ -1495,14 +1495,14 @@ class TestPartOf:
container = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcSpace") container = ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcSpace")
facet = PartOf(name="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, products=[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)
run("The container itself always fails", facet=facet, inst=container, expected=False) run("The container itself always fails", facet=facet, inst=container, expected=False)
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")
ifcopenshell.api.run("spatial.assign_container", ifc, product=element, relating_structure=container) ifcopenshell.api.run("spatial.assign_container", ifc, products=[element], relating_structure=container)
facet = PartOf(relation="IFCRELCONTAINEDINSPATIALSTRUCTURE", name="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", name="IFCSPACE") facet = PartOf(relation="IFCRELCONTAINEDINSPATIALSTRUCTURE", name="IFCSPACE")
@@ -1519,7 +1519,7 @@ class TestPartOf:
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)
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, products=[element], relating_structure=container)
facet = PartOf(relation="IFCRELCONTAINEDINSPATIALSTRUCTURE", name="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)