mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-12 18:43:26 +00:00
Fix #1737. Bug where copying an opening didn't copy relevant boolean modifiers too.
This commit is contained in:
@@ -21,6 +21,7 @@ import ifcopenshell
|
||||
import ifcopenshell.api
|
||||
import ifcopenshell.util.schema
|
||||
import ifcopenshell.util.element
|
||||
import blenderbim.bim.handler
|
||||
from ifcopenshell.api.void.data import Data as VoidData
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
|
||||
@@ -310,11 +311,14 @@ class CopyClass(bpy.types.Operator):
|
||||
else:
|
||||
bpy.ops.bim.add_representation(obj=obj.name)
|
||||
if result.is_a("IfcSpatialElement") or result.is_a("IfcSpatialStructureElement"):
|
||||
self.place_in_spatial_collection(old_element, obj)
|
||||
self.place_in_spatial_collection(result, obj)
|
||||
elif result.is_a("IfcOpeningElement"):
|
||||
self.add_opening_modifiers(result, obj)
|
||||
blenderbim.bim.handler.purge_module_data()
|
||||
return {"FINISHED"}
|
||||
|
||||
def place_in_spatial_collection(self, old_element, obj):
|
||||
aggregate = ifcopenshell.util.element.get_aggregate(old_element)
|
||||
def place_in_spatial_collection(self, element, obj):
|
||||
aggregate = ifcopenshell.util.element.get_aggregate(element)
|
||||
if not aggregate:
|
||||
return
|
||||
container_obj = IfcStore.get_element(aggregate.id())
|
||||
@@ -327,3 +331,17 @@ class CopyClass(bpy.types.Operator):
|
||||
new = bpy.data.collections.new(obj.name)
|
||||
new.objects.link(obj)
|
||||
collection.children.link(new)
|
||||
|
||||
def add_opening_modifiers(self, result, obj):
|
||||
for rel in result.VoidsElements:
|
||||
building_obj = IfcStore.get_element(rel.RelatingBuildingElement.id())
|
||||
try:
|
||||
modifier = next(m for m in obj.modifiers if m.type == "BOOLEAN" and m.object == obj)
|
||||
except StopIteration:
|
||||
modifier = building_obj.modifiers.new("IfcOpeningElement", "BOOLEAN")
|
||||
modifier.object = obj
|
||||
finally:
|
||||
modifier.operation = "DIFFERENCE"
|
||||
modifier.solver = "EXACT"
|
||||
modifier.use_self = True
|
||||
modifier.operand_type = "OBJECT"
|
||||
|
||||
@@ -107,3 +107,21 @@ class TestCopyClass(test.bim.bootstrap.NewFile):
|
||||
And the object "IfcBuildingStorey/My Storey.001" is in the collection "IfcBuildingStorey/My Storey.001"
|
||||
And the collection "IfcBuildingStorey/My Storey.001" is in the collection "IfcBuilding/My Building"
|
||||
"""
|
||||
|
||||
@test.bim.bootstrap.scenario
|
||||
def test_copying_an_opening(self):
|
||||
return """
|
||||
Given an empty IFC project
|
||||
When the object "Cube" is selected
|
||||
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
|
||||
And I press "bim.assign_class"
|
||||
And I add a cube
|
||||
And the object "Cube" is selected
|
||||
And additionally the object "IfcWall/Cube" is selected
|
||||
And I press "bim.add_opening(opening='Cube', obj='IfcWall/Cube')"
|
||||
And the object "IfcOpeningElement/Cube" is selected
|
||||
And I duplicate the selected objects
|
||||
Then the object "IfcOpeningElement/Cube" and "IfcOpeningElement/Cube.001" are different elements
|
||||
And the object "IfcWall/Cube" has a boolean difference by "IfcOpeningElement/Cube"
|
||||
And the object "IfcWall/Cube" has a boolean difference by "IfcOpeningElement/Cube.001"
|
||||
"""
|
||||
|
||||
@@ -32,6 +32,13 @@ class TestCopyClass(test.bootstrap.IFC4):
|
||||
assert element.IsDecomposedBy
|
||||
assert not new.IsDecomposedBy
|
||||
|
||||
def test_copying_an_aggregate_decomposition(self):
|
||||
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcElementAssembly")
|
||||
subelement = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBeam")
|
||||
ifcopenshell.api.run("aggregate.assign_object", self.file, product=subelement, relating_object=element)
|
||||
new = ifcopenshell.api.run("root.copy_class", self.file, product=subelement)
|
||||
assert new.Decomposes[0].RelatingObject == element
|
||||
|
||||
def test_not_copying_any_representations_because_life_is_hard(self):
|
||||
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
|
||||
element.Representation = self.file.createIfcProductDefinitionShape()
|
||||
@@ -56,3 +63,10 @@ class TestCopyClass(test.bootstrap.IFC4):
|
||||
ifcopenshell.api.run("void.add_filling", self.file, opening=opening, element=door)
|
||||
new = ifcopenshell.api.run("root.copy_class", self.file, product=opening)
|
||||
assert not new.HasFillings
|
||||
|
||||
def test_copying_a_filling(self):
|
||||
door = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcDoor")
|
||||
opening = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcOpeningElement")
|
||||
ifcopenshell.api.run("void.add_filling", self.file, opening=opening, element=door)
|
||||
new = ifcopenshell.api.run("root.copy_class", self.file, product=door)
|
||||
assert not new.FillsVoids
|
||||
|
||||
Reference in New Issue
Block a user