See #1676. You can now duplicate space boundaries.

This commit is contained in:
Dion Moult
2023-05-03 20:37:59 +10:00
parent 41e88636ff
commit c615f7469a
12 changed files with 137 additions and 15 deletions
@@ -491,8 +491,7 @@ class ShowBoundaries(bpy.types.Operator, tool.Ifc.Operator):
element = tool.Ifc.get_entity(obj)
for rel in element.BoundedBy or []:
boundary_obj = loader.load_boundary(rel, obj)
new = props.boundaries.add()
new.obj = boundary_obj
tool.Boundary.decorate_boundary(boundary_obj)
BoundaryDecorator.install(bpy.context)
return {"FINISHED"}
@@ -527,6 +527,8 @@ class OverrideDuplicateMove(bpy.types.Operator):
array_pset = tool.Ifc.get().by_id(array_pset["id"])
ifcopenshell.api.run("pset.remove_pset", tool.Ifc.get(), product=new, pset=array_pset)
old_to_new[tool.Ifc.get_entity(obj)] = [new]
if new.is_a("IfcRelSpaceBoundary"):
tool.Boundary.decorate_boundary(new_obj)
# Recreate decompositions
tool.Root.recreate_decompositions(relationships, old_to_new)
blenderbim.bim.handler.purge_module_data()
+5 -1
View File
@@ -21,6 +21,10 @@ def copy_class(ifc, collector, geometry, root, obj=None):
element = ifc.get_entity(obj)
if not element:
return
if root.is_element_a(element, "IfcRelSpaceBoundary"):
new = ifc.run("boundary.copy_boundary", boundary=element)
ifc.link(new, obj)
return new
representation = root.get_object_representation(obj)
new = ifc.run("root.copy_class", product=element)
ifc.link(new, obj)
@@ -38,7 +42,7 @@ def copy_class(ifc, collector, geometry, root, obj=None):
geometry.link(new_representation, data)
root.assign_body_styles(new, obj)
collector.assign(obj)
if root.is_opening_element(new):
if root.is_element_a(new, "IfcOpeningElement"):
root.add_tracked_opening(obj)
return new
+1 -1
View File
@@ -606,7 +606,7 @@ class Root:
def get_object_name(cls, obj): pass
def get_object_representation(cls, obj): pass
def get_representation_context(cls, representation): pass
def is_opening_element(cls, element): pass
def is_element_a(cls, element, ifc_class): pass
def link_object_data(cls, source_obj, destination_obj): pass
def recreate_decompositions(cls, relationships, old_to_new): pass
def run_geometry_add_representation(cls, obj=None, context=None, ifc_representation_class=None, profile_set_usage=None): pass
@@ -70,3 +70,9 @@ class Boundary(blenderbim.core.tool.Boundary):
translation = obj.matrix_world.translation - space.matrix_world.translation
obj.data.transform(mathutils.Matrix.Translation(translation))
obj.matrix_world = space.matrix_world
@classmethod
def decorate_boundary(cls, obj):
new = bpy.context.scene.BIMBoundaryProperties.boundaries.add()
new.obj = obj
obj.show_in_front = True
+2 -2
View File
@@ -119,8 +119,8 @@ class Root(blenderbim.core.tool.Root):
return representation.ContextOfItems
@classmethod
def is_opening_element(cls, element):
return element.is_a("IfcOpeningElement")
def is_element_a(cls, element, ifc_class):
return element.is_a(ifc_class)
@classmethod
def link_object_data(cls, source_obj, destination_obj):
+16 -5
View File
@@ -28,6 +28,7 @@ class TestCopyClass:
def test_copy_with_new_geometry_derived_from_the_type(self, ifc, collector, root):
ifc.get_entity("obj").should_be_called().will_return("original_element")
root.is_element_a("original_element", "IfcRelSpaceBoundary").should_be_called().will_return(False)
root.get_object_representation("obj").should_be_called().will_return("representation")
ifc.run("root.copy_class", product="original_element").should_be_called().will_return("element")
ifc.link("element", "obj").should_be_called()
@@ -37,7 +38,7 @@ class TestCopyClass:
ifc.get_object("type").should_be_called().will_return("type_obj")
root.link_object_data("type_obj", "obj").should_be_called()
collector.assign("obj").should_be_called()
root.is_opening_element("element").should_be_called().will_return(False)
root.is_element_a("element", "IfcOpeningElement").should_be_called().will_return(False)
subject.copy_class(ifc, collector, geometry, root, obj="obj")
def test_copy_with_new_geometry_copied_from_the_old(self, ifc, collector, geometry, root):
@@ -45,6 +46,7 @@ class TestCopyClass:
# copied. This was faster (though I cannot recreate it now) but had the
# bigger problem of not preserving non-mesh geometry and openings.
ifc.get_entity("obj").should_be_called().will_return("original_element")
root.is_element_a("original_element", "IfcRelSpaceBoundary").should_be_called().will_return(False)
root.get_object_representation("obj").should_be_called().will_return("representation")
ifc.run("root.copy_class", product="original_element").should_be_called().will_return("element")
ifc.link("element", "obj").should_be_called()
@@ -60,22 +62,24 @@ class TestCopyClass:
root.assign_body_styles("element", "obj").should_be_called()
geometry.duplicate_object_data("obj").should_be_called().will_return("data")
collector.assign("obj").should_be_called()
root.is_opening_element("element").should_be_called().will_return(False)
root.is_element_a("element", "IfcOpeningElement").should_be_called().will_return(False)
subject.copy_class(ifc, collector, geometry, root, obj="obj")
def test_copy_with_no_new_geometry(self, ifc, collector, geometry, root):
ifc.get_entity("obj").should_be_called().will_return("original_element")
root.is_element_a("original_element", "IfcRelSpaceBoundary").should_be_called().will_return(False)
root.get_object_representation("obj").should_be_called().will_return(None)
ifc.run("root.copy_class", product="original_element").should_be_called().will_return("element")
ifc.link("element", "obj").should_be_called()
root.get_element_type("element").should_be_called().will_return("type")
root.does_type_have_representations("type").should_be_called().will_return(False)
collector.assign("obj").should_be_called()
root.is_opening_element("element").should_be_called().will_return(False)
root.is_element_a("element", "IfcOpeningElement").should_be_called().will_return(False)
subject.copy_class(ifc, collector, geometry, root, obj="obj")
def test_copied_openings_are_tracked_for_special_visualiation(self, ifc, collector, root):
def test_copied_openings_are_tracked_for_special_visualiation(self, ifc, collector, geometry, root):
ifc.get_entity("obj").should_be_called().will_return("original_element")
root.is_element_a("original_element", "IfcRelSpaceBoundary").should_be_called().will_return(False)
root.get_object_representation("obj").should_be_called().will_return(None)
ifc.run("root.copy_class", product="original_element").should_be_called().will_return("element")
ifc.link("element", "obj").should_be_called()
@@ -85,10 +89,17 @@ class TestCopyClass:
ifc.get_object("type").should_be_called().will_return("type_obj")
root.link_object_data("type_obj", "obj").should_be_called()
collector.assign("obj").should_be_called()
root.is_opening_element("element").should_be_called().will_return(True)
root.is_element_a("element", "IfcOpeningElement").should_be_called().will_return(True)
root.add_tracked_opening("obj").should_be_called()
subject.copy_class(ifc, collector, geometry, root, obj="obj")
def test_copying_boundaries_are_dealt_with_specially(self, ifc, collector, geometry, root):
ifc.get_entity("obj").should_be_called().will_return("original_element")
root.is_element_a("original_element", "IfcRelSpaceBoundary").should_be_called().will_return(True)
ifc.run("boundary.copy_boundary", boundary="original_element").should_be_called().will_return("element")
ifc.link("element", "obj").should_be_called()
assert subject.copy_class(ifc, collector, geometry, root, obj="obj") == "element"
class TestAssignClass:
def test_do_nothing_if_already_assigned(self, ifc, collector, root):
+3 -3
View File
@@ -132,11 +132,11 @@ class TestGetRepresentationContext(NewFile):
assert subject.get_representation_context(representation) == context
class TestIsOpeningElement(NewFile):
class TestIsElementA(NewFile):
def test_run(self):
ifc = ifcopenshell.file()
assert subject.is_opening_element(ifc.createIfcWall()) is False
assert subject.is_opening_element(ifc.createIfcOpeningElement()) is True
assert subject.is_a(ifc.createIfcWall(), "IfcSlab") is False
assert subject.is_a(ifc.createIfcOpeningElement(), "IfcOpeningElement") is True
class TestLinkObjectData(NewFile):