mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
Copy deep can now exclude things, useful for copying representation graphs where you don't want to duplicate the context
This commit is contained in:
@@ -190,13 +190,17 @@ def get_elements_by_material(ifc_file, material):
|
||||
"""
|
||||
Retrieves the elements related to a material.
|
||||
|
||||
This includes elements using the material as part of a material set or set
|
||||
usage.
|
||||
|
||||
:param ifc_file: The IFC file
|
||||
:param material: The IFC Material entity
|
||||
:return: The elements related to the material
|
||||
:return: A list of elements using the to the material
|
||||
|
||||
Example::
|
||||
material = file.by_type("IfcMaterial")[0]
|
||||
elements = ifcopenshell.util.element.get_elements_by_material(file, material)
|
||||
|
||||
material = file.by_type("IfcMaterial")[0]
|
||||
elements = ifcopenshell.util.element.get_elements_by_material(file, material)
|
||||
"""
|
||||
results = set()
|
||||
for inverse in ifc_file.get_inverse(material):
|
||||
@@ -229,9 +233,9 @@ def get_elements_by_style(ifc_file, style):
|
||||
:return: The elements related to the style
|
||||
|
||||
Example::
|
||||
style = file.by_type("IfcSurfaceStyle")[0]
|
||||
elements = ifcopenshell.util.element.get_elements_by_style(file, style)
|
||||
|
||||
style = file.by_type("IfcSurfaceStyle")[0]
|
||||
elements = ifcopenshell.util.element.get_elements_by_style(file, style)
|
||||
"""
|
||||
results = set()
|
||||
inverses = list(ifc_file.get_inverse(style))
|
||||
@@ -482,6 +486,15 @@ def remove_deep2(ifc_file, element, also_consider=[], do_not_delete=[]):
|
||||
|
||||
|
||||
def copy(ifc_file, element):
|
||||
"""
|
||||
Copy a single element. Any referenced elements are not copied.
|
||||
|
||||
GlobalIds are regenerated.
|
||||
|
||||
:param ifc_file: The IFC file object
|
||||
:param element: The IFC element to copy
|
||||
:return: The newly copied element
|
||||
"""
|
||||
new = ifc_file.create_entity(element.is_a())
|
||||
for i, attribute in enumerate(element):
|
||||
if attribute is None:
|
||||
@@ -493,16 +506,33 @@ def copy(ifc_file, element):
|
||||
return new
|
||||
|
||||
|
||||
def copy_deep(ifc_file, element):
|
||||
def copy_deep(ifc_file, element, exclude=None):
|
||||
"""
|
||||
Recursively copy an element and all of its directly related subelements.
|
||||
|
||||
GlobalIds are regenerated.
|
||||
|
||||
:param ifc_file: The IFC file object
|
||||
:param element: The IFC element to copy
|
||||
:param exclude: An optional list of strings of IFC class names to not copy.
|
||||
If any of the subelement is this class, it will not be copied and the
|
||||
original instance will be referenced.
|
||||
:return: The newly copied element
|
||||
"""
|
||||
new = ifc_file.create_entity(element.is_a())
|
||||
for i, attribute in enumerate(element):
|
||||
if attribute is None:
|
||||
continue
|
||||
if isinstance(attribute, ifcopenshell.entity_instance):
|
||||
attribute = copy_deep(ifc_file, attribute)
|
||||
if not exclude or (exclude and not any([attribute.is_a(e) for e in exclude])):
|
||||
attribute = copy_deep(ifc_file, attribute, exclude=exclude)
|
||||
elif isinstance(attribute, tuple) and attribute and isinstance(attribute[0], ifcopenshell.entity_instance):
|
||||
attribute = list(attribute)
|
||||
for j, item in enumerate(attribute):
|
||||
attribute[j] = copy_deep(ifc_file, item)
|
||||
new[i] = attribute
|
||||
if not exclude or (exclude and not any([attribute[0].is_a(e) for e in exclude])):
|
||||
attribute = list(attribute)
|
||||
for j, item in enumerate(attribute):
|
||||
attribute[j] = copy_deep(ifc_file, item, exclude=exclude)
|
||||
if new.attribute_name(i) == "GlobalId":
|
||||
new[i] = ifcopenshell.guid.new()
|
||||
else:
|
||||
new[i] = attribute
|
||||
return new
|
||||
|
||||
@@ -668,6 +668,7 @@ class TestCopyDeepIFC4(test.bootstrap.IFC4):
|
||||
element = self.file.createIfcWall(GlobalId="id", Name="name", OwnerHistory=owner)
|
||||
element2 = subject.copy_deep(self.file, element)
|
||||
assert element.OwnerHistory != element2.OwnerHistory
|
||||
assert element.GlobalId != element2.GlobalId
|
||||
assert element.OwnerHistory.State == element2.OwnerHistory.State
|
||||
|
||||
def test_copying_an_element_recursively_even_if_references_are_aggregated(self):
|
||||
@@ -677,3 +678,17 @@ class TestCopyDeepIFC4(test.bootstrap.IFC4):
|
||||
rel2 = subject.copy_deep(self.file, rel)
|
||||
assert rel.RelatedObjects != rel2.RelatedObjects
|
||||
assert rel.RelatedObjects[0].Name == rel2.RelatedObjects[0].Name
|
||||
|
||||
def test_copying_an_element_recursively_with_an_exclude_filter(self):
|
||||
owner = self.file.createIfcOwnerHistory()
|
||||
owner.State = "READWRITE"
|
||||
element = self.file.createIfcWall(GlobalId="id", Name="name", OwnerHistory=owner)
|
||||
element2 = subject.copy_deep(self.file, element, exclude=["IfcOwnerHistory"])
|
||||
assert element.OwnerHistory == element2.OwnerHistory
|
||||
|
||||
def test_copying_an_element_recursively_with_aggregates_with_an_exclude_filter(self):
|
||||
element = self.file.createIfcWall(Name="name")
|
||||
rel = self.file.createIfcRelAggregates()
|
||||
rel.RelatedObjects = [element]
|
||||
rel2 = subject.copy_deep(self.file, rel, exclude=["IfcWall"])
|
||||
assert rel.RelatedObjects == rel2.RelatedObjects
|
||||
|
||||
Reference in New Issue
Block a user