mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-18 22:33:33 +00:00
Improve filling operators and tests (#1754)
* Test add_filling operator
* Test Remove filling
* Update bootstrap defs for filling test
* Fix possible errors in add_filling and remove_filling
* Enable adding fillings from the opening object ui
* Typo
* Revert "Enable adding fillings from the opening object ui"
This reverts commit b217860840.
* Display a list of all fillings when an opening is selected
* Ensure an IfcOpeningElement can't be voided
* merge 0.7.0
* Add test cases for filling operators
* Test Opening operators
* Delete related fill relations on object deletion
* Remove try/except
* typo
* Minor fix
* Remove boolean modifier on previous element when voiding a new one
* Don't show ui elements when not applicable
* Test filling void b with an element that already fills void a
correctly removes the filling from void a
Co-authored-by: Dion Moult <dion@thinkmoult.com>
This commit is contained in:
@@ -34,7 +34,18 @@ class AddOpening(bpy.types.Operator):
|
|||||||
return IfcStore.execute_ifc_operator(self, context)
|
return IfcStore.execute_ifc_operator(self, context)
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
|
self.file = IfcStore.get_file()
|
||||||
obj = context.scene.objects.get(self.obj, context.active_object)
|
obj = context.scene.objects.get(self.obj, context.active_object)
|
||||||
|
if obj is None:
|
||||||
|
return {"FINISHED"}
|
||||||
|
element_id = obj.BIMObjectProperties.ifc_definition_id
|
||||||
|
if not element_id:
|
||||||
|
return {"FINISHED"}
|
||||||
|
element = self.file.by_id(element_id)
|
||||||
|
if element.is_a("IfcOpeningElement"):
|
||||||
|
self.report({"WARNING"}, "An IfcOpeningElement can't be voided")
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
opening = bpy.data.objects.get(self.opening)
|
opening = bpy.data.objects.get(self.opening)
|
||||||
if opening is None:
|
if opening is None:
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
@@ -45,14 +56,22 @@ class AddOpening(bpy.types.Operator):
|
|||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
bpy.ops.bim.assign_class(obj=opening.name, ifc_class="IfcOpeningElement", context_id=body_context.id())
|
bpy.ops.bim.assign_class(obj=opening.name, ifc_class="IfcOpeningElement", context_id=body_context.id())
|
||||||
|
|
||||||
self.file = IfcStore.get_file()
|
# If the IfcOpeningElement aleady voids another object, remove the boolean modifier
|
||||||
element_id = obj.BIMObjectProperties.ifc_definition_id
|
opening_element = self.file.by_id(opening.BIMObjectProperties.ifc_definition_id)
|
||||||
|
if opening_element.VoidsElements:
|
||||||
|
other_obj = IfcStore.get_element(opening_element.VoidsElements[0].RelatingBuildingElement.id())
|
||||||
|
try:
|
||||||
|
modifier = next(m for m in other_obj.modifiers if m.type == "BOOLEAN" and m.object == opening)
|
||||||
|
other_obj.modifiers.remove(modifier)
|
||||||
|
except StopIteration:
|
||||||
|
pass
|
||||||
|
|
||||||
ifcopenshell.api.run(
|
ifcopenshell.api.run(
|
||||||
"void.add_opening",
|
"void.add_opening",
|
||||||
self.file,
|
self.file,
|
||||||
**{
|
**{
|
||||||
"opening": self.file.by_id(opening.BIMObjectProperties.ifc_definition_id),
|
"opening": opening_element,
|
||||||
"element": self.file.by_id(element_id),
|
"element": element,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
Data.load(self.file, element_id)
|
Data.load(self.file, element_id)
|
||||||
@@ -129,7 +148,7 @@ class AddFilling(bpy.types.Operator):
|
|||||||
self.file = IfcStore.get_file()
|
self.file = IfcStore.get_file()
|
||||||
element_id = obj.BIMObjectProperties.ifc_definition_id
|
element_id = obj.BIMObjectProperties.ifc_definition_id
|
||||||
opening_id = opening.BIMObjectProperties.ifc_definition_id
|
opening_id = opening.BIMObjectProperties.ifc_definition_id
|
||||||
if not element_id or not opening_id:
|
if not element_id or not opening_id or element_id == opening_id:
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
ifcopenshell.api.run(
|
ifcopenshell.api.run(
|
||||||
"void.add_filling",
|
"void.add_filling",
|
||||||
@@ -154,11 +173,14 @@ class RemoveFilling(bpy.types.Operator):
|
|||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
obj = bpy.data.objects.get(self.obj) if self.obj else context.active_object
|
obj = bpy.data.objects.get(self.obj) if self.obj else context.active_object
|
||||||
|
if not obj:
|
||||||
|
return {"FINISHED"}
|
||||||
self.file = IfcStore.get_file()
|
self.file = IfcStore.get_file()
|
||||||
ifcopenshell.api.run(
|
element_id = obj.BIMObjectProperties.ifc_definition_id
|
||||||
"void.remove_filling", self.file, **{"element": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)}
|
if not element_id:
|
||||||
)
|
return {"FINISHED"}
|
||||||
Data.load(IfcStore.get_file(), obj.BIMObjectProperties.ifc_definition_id)
|
ifcopenshell.api.run("void.remove_filling", self.file, **{"element": self.file.by_id(element_id)})
|
||||||
|
Data.load(self.file, element_id)
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -40,9 +40,10 @@ class BIM_PT_voids(Panel):
|
|||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
props = context.active_object.BIMObjectProperties
|
props = context.active_object.BIMObjectProperties
|
||||||
|
file = IfcStore.get_file()
|
||||||
if props.ifc_definition_id not in Data.products:
|
if props.ifc_definition_id not in Data.products:
|
||||||
Data.load(IfcStore.get_file(), props.ifc_definition_id)
|
Data.load(file, props.ifc_definition_id)
|
||||||
|
active_object_is_an_opening = file.by_id(props.ifc_definition_id).is_a("IfcOpeningElement")
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
if len(context.selected_objects) == 2:
|
if len(context.selected_objects) == 2:
|
||||||
op = row.operator("bim.add_opening", icon="ADD", text="Add Opening")
|
op = row.operator("bim.add_opening", icon="ADD", text="Add Opening")
|
||||||
@@ -71,14 +72,16 @@ class BIM_PT_voids(Panel):
|
|||||||
row.label(text="Select an opening and an element to modify", icon="HELP")
|
row.label(text="Select an opening and an element to modify", icon="HELP")
|
||||||
|
|
||||||
opening_ids = Data.products[props.ifc_definition_id]
|
opening_ids = Data.products[props.ifc_definition_id]
|
||||||
if not opening_ids:
|
if not opening_ids and not active_object_is_an_opening:
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
row.label(text="No Openings", icon="SELECT_SUBTRACT")
|
row.label(text="No Openings", icon="SELECT_SUBTRACT")
|
||||||
for opening_id in opening_ids:
|
for opening_id in opening_ids:
|
||||||
opening = Data.openings[opening_id]
|
opening = Data.openings[opening_id]
|
||||||
if opening["HasFillings"]:
|
if opening["HasFillings"]:
|
||||||
for filling_id in opening["HasFillings"]:
|
for filling_id in opening["HasFillings"]:
|
||||||
filling = Data.fillings[filling_id]
|
filling = Data.fillings.get(filling_id)
|
||||||
|
if filling is None:
|
||||||
|
continue
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
row.label(text=opening["Name"], icon="SELECT_SUBTRACT")
|
row.label(text=opening["Name"], icon="SELECT_SUBTRACT")
|
||||||
row.label(text=filling["Name"], icon="SELECT_INTERSECT")
|
row.label(text=filling["Name"], icon="SELECT_INTERSECT")
|
||||||
@@ -87,8 +90,18 @@ class BIM_PT_voids(Panel):
|
|||||||
row.label(text=opening["Name"], icon="SELECT_SUBTRACT")
|
row.label(text=opening["Name"], icon="SELECT_SUBTRACT")
|
||||||
op = row.operator("bim.remove_opening", icon="X", text="")
|
op = row.operator("bim.remove_opening", icon="X", text="")
|
||||||
op.opening_id = opening_id
|
op.opening_id = opening_id
|
||||||
|
if props.ifc_definition_id in Data.openings:
|
||||||
if props.ifc_definition_id not in Data.fillings:
|
for filling_id in Data.openings[props.ifc_definition_id]["HasFillings"]:
|
||||||
|
filling = Data.fillings.get(filling_id)
|
||||||
|
if filling is None:
|
||||||
|
continue
|
||||||
|
row = self.layout.row(align=True)
|
||||||
|
row.label(text=filling["Name"], icon="SELECT_INTERSECT")
|
||||||
|
op = row.operator("bim.remove_filling", icon="X", text="")
|
||||||
|
op.obj = IfcStore.get_element(filling_id).name
|
||||||
|
if active_object_is_an_opening:
|
||||||
|
pass
|
||||||
|
elif props.ifc_definition_id not in Data.fillings:
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
row.prop(context.scene.VoidProperties, "desired_opening", text="", icon="SELECT_INTERSECT")
|
row.prop(context.scene.VoidProperties, "desired_opening", text="", icon="SELECT_INTERSECT")
|
||||||
row.operator("bim.add_filling", icon="ADD", text="")
|
row.operator("bim.add_filling", icon="ADD", text="")
|
||||||
|
|||||||
@@ -663,11 +663,17 @@ class OverrideDelete(bpy.types.Operator):
|
|||||||
return context.window_manager.invoke_confirm(self, event)
|
return context.window_manager.invoke_confirm(self, event)
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
|
file = IfcStore.get_file()
|
||||||
for obj in context.selected_objects:
|
for obj in context.selected_objects:
|
||||||
if obj.BIMObjectProperties.ifc_definition_id:
|
if obj.BIMObjectProperties.ifc_definition_id:
|
||||||
element = IfcStore.get_file().by_id(obj.BIMObjectProperties.ifc_definition_id)
|
element = file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||||
|
if element.FillsVoids:
|
||||||
|
self.delete_filling_element(element)
|
||||||
if element.is_a("IfcOpeningElement"):
|
if element.is_a("IfcOpeningElement"):
|
||||||
self.delete_opening_element(element)
|
if element.VoidsElements:
|
||||||
|
self.delete_opening_element(element)
|
||||||
|
# for rel in element.HasFillings:
|
||||||
|
# self.delete_filling_element(rel.RelatedBuildingElement)
|
||||||
elif element.HasOpenings:
|
elif element.HasOpenings:
|
||||||
for rel in element.HasOpenings:
|
for rel in element.HasOpenings:
|
||||||
self.delete_opening_element(rel.RelatedOpeningElement)
|
self.delete_opening_element(rel.RelatedOpeningElement)
|
||||||
@@ -677,3 +683,7 @@ class OverrideDelete(bpy.types.Operator):
|
|||||||
def delete_opening_element(self, element):
|
def delete_opening_element(self, element):
|
||||||
obj = IfcStore.get_element(element.VoidsElements[0].RelatingBuildingElement.id())
|
obj = IfcStore.get_element(element.VoidsElements[0].RelatingBuildingElement.id())
|
||||||
bpy.ops.bim.remove_opening(opening_id=element.id(), obj=obj.name)
|
bpy.ops.bim.remove_opening(opening_id=element.id(), obj=obj.name)
|
||||||
|
|
||||||
|
def delete_filling_element(self, element):
|
||||||
|
obj = IfcStore.get_element(element.id())
|
||||||
|
bpy.ops.bim.remove_filling(obj=obj.name)
|
||||||
|
|||||||
@@ -40,9 +40,10 @@ class NewFile:
|
|||||||
def setup(self):
|
def setup(self):
|
||||||
IfcStore.purge()
|
IfcStore.purge()
|
||||||
bpy.ops.wm.read_homefile(app_template="")
|
bpy.ops.wm.read_homefile(app_template="")
|
||||||
while bpy.data.objects:
|
if bpy.data.objects:
|
||||||
bpy.data.objects.remove(bpy.data.objects[0])
|
while bpy.data.objects:
|
||||||
bpy.ops.outliner.orphans_purge(do_local_ids=True, do_linked_ids=True, do_recursive=True)
|
bpy.data.objects.remove(bpy.data.objects[0])
|
||||||
|
bpy.ops.outliner.orphans_purge(do_local_ids=True, do_linked_ids=True, do_recursive=True)
|
||||||
|
|
||||||
|
|
||||||
class NewIfc:
|
class NewIfc:
|
||||||
@@ -83,7 +84,7 @@ def i_add_a_cube_of_size_size_at_location(size, location):
|
|||||||
|
|
||||||
|
|
||||||
def the_object_name_is_selected(name):
|
def the_object_name_is_selected(name):
|
||||||
bpy.ops.object.select_all(action="DESELECT")
|
i_deselect_all_objects()
|
||||||
additionally_the_object_name_is_selected(name)
|
additionally_the_object_name_is_selected(name)
|
||||||
|
|
||||||
|
|
||||||
@@ -94,6 +95,10 @@ def additionally_the_object_name_is_selected(name):
|
|||||||
bpy.context.view_layer.objects.active = obj
|
bpy.context.view_layer.objects.active = obj
|
||||||
obj.select_set(True)
|
obj.select_set(True)
|
||||||
|
|
||||||
|
def i_deselect_all_objects():
|
||||||
|
bpy.context.view_layer.objects.active = None
|
||||||
|
bpy.ops.object.select_all(action="DESELECT")
|
||||||
|
|
||||||
|
|
||||||
def i_am_on_frame_number(number):
|
def i_am_on_frame_number(number):
|
||||||
bpy.context.scene.frame_set(int(number))
|
bpy.context.scene.frame_set(int(number))
|
||||||
@@ -278,6 +283,42 @@ def the_object_name_is_not_voided_by_void(name, void):
|
|||||||
assert False, "A void was found"
|
assert False, "A void was found"
|
||||||
|
|
||||||
|
|
||||||
|
def the_object_name_is_not_voided(name):
|
||||||
|
ifc = IfcStore.get_file()
|
||||||
|
element = ifc.by_id(the_object_name_exists(name).BIMObjectProperties.ifc_definition_id)
|
||||||
|
if any(element.HasOpenings):
|
||||||
|
assert False, "An opening was found"
|
||||||
|
|
||||||
|
|
||||||
|
def the_object_name_is_not_a_void(name):
|
||||||
|
ifc = IfcStore.get_file()
|
||||||
|
element = ifc.by_id(the_object_name_exists(name).BIMObjectProperties.ifc_definition_id)
|
||||||
|
if any(element.VoidsElements):
|
||||||
|
assert False, "A void was found"
|
||||||
|
|
||||||
|
|
||||||
|
def the_void_name_is_filled_by_filling(name, filling):
|
||||||
|
ifc = IfcStore.get_file()
|
||||||
|
element = ifc.by_id(the_object_name_exists(name).BIMObjectProperties.ifc_definition_id)
|
||||||
|
if any(rel.RelatedBuildingElement.Name == filling for rel in element.HasFillings):
|
||||||
|
return True
|
||||||
|
assert False, "No filling found"
|
||||||
|
|
||||||
|
|
||||||
|
def the_void_name_is_not_filled_by_filling(name, filling):
|
||||||
|
ifc = IfcStore.get_file()
|
||||||
|
element = ifc.by_id(the_object_name_exists(name).BIMObjectProperties.ifc_definition_id)
|
||||||
|
if any(rel.RelatedBuildingElement.Name == filling for rel in element.HasFillings):
|
||||||
|
assert False, "A filling was found"
|
||||||
|
|
||||||
|
|
||||||
|
def the_object_name_is_not_a_filling(name):
|
||||||
|
ifc = IfcStore.get_file()
|
||||||
|
element = ifc.by_id(the_object_name_exists(name).BIMObjectProperties.ifc_definition_id)
|
||||||
|
if any(element.FillsVoids):
|
||||||
|
assert False, "A filling was found"
|
||||||
|
|
||||||
|
|
||||||
def the_object_name_should_display_as_mode(name, mode):
|
def the_object_name_should_display_as_mode(name, mode):
|
||||||
assert the_object_name_exists(name).display_type == mode
|
assert the_object_name_exists(name).display_type == mode
|
||||||
|
|
||||||
@@ -305,6 +346,7 @@ definitions = {
|
|||||||
'I add a cube of size "([0-9]+)" at "(.*)"': i_add_a_cube_of_size_size_at_location,
|
'I add a cube of size "([0-9]+)" at "(.*)"': i_add_a_cube_of_size_size_at_location,
|
||||||
'the object "(.*)" is selected': the_object_name_is_selected,
|
'the object "(.*)" is selected': the_object_name_is_selected,
|
||||||
'additionally the object "(.*)" is selected': additionally_the_object_name_is_selected,
|
'additionally the object "(.*)" is selected': additionally_the_object_name_is_selected,
|
||||||
|
'I deselect all objects': i_deselect_all_objects,
|
||||||
'I am on frame "([0-9]+)"': i_am_on_frame_number,
|
'I am on frame "([0-9]+)"': i_am_on_frame_number,
|
||||||
'I set "(.*)" to "(.*)"': i_set_prop_to_value,
|
'I set "(.*)" to "(.*)"': i_set_prop_to_value,
|
||||||
'"(.*)" is "(.*)"': prop_is_value,
|
'"(.*)" is "(.*)"': prop_is_value,
|
||||||
@@ -333,10 +375,15 @@ definitions = {
|
|||||||
'the object "(.*)" has no boolean difference by "(.*)"': the_object_name1_has_no_boolean_difference_by_name2,
|
'the object "(.*)" has no boolean difference by "(.*)"': the_object_name1_has_no_boolean_difference_by_name2,
|
||||||
'the object "(.*)" is voided by "(.*)"': the_object_name_is_voided_by_void,
|
'the object "(.*)" is voided by "(.*)"': the_object_name_is_voided_by_void,
|
||||||
'the object "(.*)" is not voided by "(.*)"': the_object_name_is_not_voided_by_void,
|
'the object "(.*)" is not voided by "(.*)"': the_object_name_is_not_voided_by_void,
|
||||||
|
'the object "(.*)" is not a void': the_object_name_is_not_a_void,
|
||||||
|
'the object "(.*)" is not voided': the_object_name_is_not_voided,
|
||||||
'the object "(.*)" should display as "(.*)"': the_object_name_should_display_as_mode,
|
'the object "(.*)" should display as "(.*)"': the_object_name_should_display_as_mode,
|
||||||
'the object "(.*)" has "([0-9]+)" vertices': the_object_name_has_number_vertices,
|
'the object "(.*)" has "([0-9]+)" vertices': the_object_name_has_number_vertices,
|
||||||
'the object "(.*)" is at "(.*)"': the_object_name_is_at_location,
|
'the object "(.*)" is at "(.*)"': the_object_name_is_at_location,
|
||||||
"nothing interesting happens": lambda: None,
|
"nothing interesting happens": lambda: None,
|
||||||
|
'the void "(.*)" is filled by "(.*)"': the_void_name_is_filled_by_filling,
|
||||||
|
'the void "(.*)" is not filled by "(.*)"': the_void_name_is_not_filled_by_filling,
|
||||||
|
'the object "(.*)" is not a filling': the_object_name_is_not_a_filling,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,99 @@ class TestAddOpening(test.bim.bootstrap.NewFile):
|
|||||||
And the object "IfcWall/Cube" is voided by "Cube"
|
And the object "IfcWall/Cube" is voided by "Cube"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@test.bim.bootstrap.scenario
|
||||||
|
def test_adding_an_opening_on_an_opening(self):
|
||||||
|
"""An opening can't legally be voided by another opening"""
|
||||||
|
return """
|
||||||
|
Given an empty IFC project
|
||||||
|
And I add a cube
|
||||||
|
When the object "Cube" is selected
|
||||||
|
And I set "scene.BIMRootProperties.ifc_class" to "IfcOpeningElement"
|
||||||
|
And I press "bim.assign_class"
|
||||||
|
And I add a cube
|
||||||
|
And the object "Cube" is selected
|
||||||
|
And I set "scene.BIMRootProperties.ifc_class" to "IfcOpeningElement"
|
||||||
|
And I press "bim.assign_class"
|
||||||
|
And the object "IfcOpeningElement/Cube" is selected
|
||||||
|
And additionally the object "IfcOpeningElement/Cube.001" is selected
|
||||||
|
And I press "bim.add_opening(opening='IfcOpeningElement/Cube', obj='IfcOpeningElement/Cube.001')"
|
||||||
|
Then the object "IfcOpeningElement/Cube" is an "IfcOpeningElement"
|
||||||
|
And the object "IfcOpeningElement/Cube" should display as "WIRE"
|
||||||
|
And the object "IfcOpeningElement/Cube" is not a void
|
||||||
|
Then the object "IfcOpeningElement/Cube.001" is an "IfcOpeningElement"
|
||||||
|
And the object "IfcOpeningElement/Cube.001" should display as "WIRE"
|
||||||
|
Then the object "IfcOpeningElement/Cube.001" has no boolean difference by "IfcOpeningElement/Cube"
|
||||||
|
And the object "IfcOpeningElement/Cube.001" is not voided by "Cube"
|
||||||
|
"""
|
||||||
|
|
||||||
|
@test.bim.bootstrap.scenario
|
||||||
|
def test_adding_an_opening_on_a_null_object(self):
|
||||||
|
return """
|
||||||
|
Given an empty IFC project
|
||||||
|
And I add a cube
|
||||||
|
When the object "Cube" is selected
|
||||||
|
And I set "scene.BIMRootProperties.ifc_class" to "IfcOpeningElement"
|
||||||
|
And I press "bim.assign_class"
|
||||||
|
And I deselect all objects
|
||||||
|
And I press "bim.add_opening(opening='IfcOpeningElement/Cube')"
|
||||||
|
Then the object "IfcOpeningElement/Cube" is an "IfcOpeningElement"
|
||||||
|
And the object "IfcOpeningElement/Cube" should display as "WIRE"
|
||||||
|
And the object "IfcOpeningElement/Cube" is not a void
|
||||||
|
"""
|
||||||
|
|
||||||
|
@test.bim.bootstrap.scenario
|
||||||
|
def test_adding_an_opening_on_a_non_ifc_object(self):
|
||||||
|
return """
|
||||||
|
Given an empty IFC project
|
||||||
|
And I add a cube
|
||||||
|
When the object "Cube" is selected
|
||||||
|
And I set "scene.BIMRootProperties.ifc_class" to "IfcOpeningElement"
|
||||||
|
And I press "bim.assign_class"
|
||||||
|
And I add a cube
|
||||||
|
And the object "Cube" is selected
|
||||||
|
And I press "bim.add_opening(opening='IfcOpeningElement/Cube', obj='Cube')"
|
||||||
|
Then the object "IfcOpeningElement/Cube" is an "IfcOpeningElement"
|
||||||
|
And the object "IfcOpeningElement/Cube" should display as "WIRE"
|
||||||
|
And the object "IfcOpeningElement/Cube" is not a void
|
||||||
|
And the object "Cube" is not an IFC element
|
||||||
|
"""
|
||||||
|
|
||||||
|
@test.bim.bootstrap.scenario
|
||||||
|
def test_adding_an_opening_with_a_null_object(self):
|
||||||
|
return """
|
||||||
|
Given an empty IFC project
|
||||||
|
And I add a cube
|
||||||
|
When the object "Cube" is selected
|
||||||
|
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
|
||||||
|
And I press "bim.assign_class"
|
||||||
|
And I deselect all objects
|
||||||
|
And I press "bim.add_opening(obj='IfcWall/Cube')"
|
||||||
|
Then the object "IfcWall/Cube" is an "IfcWall"
|
||||||
|
And the object "IfcWall/Cube" is not voided
|
||||||
|
"""
|
||||||
|
|
||||||
|
@test.bim.bootstrap.scenario
|
||||||
|
def test_adding_an_opening_to_element_b_with_a_void_that_already_voids_element_a(self):
|
||||||
|
"""An opening can legally void at most one element"""
|
||||||
|
return """
|
||||||
|
Given an empty IFC project
|
||||||
|
And I add a cube
|
||||||
|
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 I press "bim.add_opening(opening='Cube', obj='IfcWall/Cube')"
|
||||||
|
And I add a cube
|
||||||
|
And the object "Cube" is selected
|
||||||
|
And I set "scene.BIMRootProperties.ifc_class" to "IfcWall"
|
||||||
|
And I press "bim.assign_class"
|
||||||
|
And I press "bim.add_opening(opening='IfcOpeningElement/Cube', obj='IfcWall/Cube.001')"
|
||||||
|
Then the object "IfcWall/Cube" is not voided
|
||||||
|
And the object "IfcWall/Cube" has no boolean difference by "IfcOpeningElement/Cube"
|
||||||
|
And the object "IfcWall/Cube.001" is voided by "Cube"
|
||||||
|
And the object "IfcWall/Cube.001" has a boolean difference by "IfcOpeningElement/Cube"
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class TestRemoveOpening(test.bim.bootstrap.NewFile):
|
class TestRemoveOpening(test.bim.bootstrap.NewFile):
|
||||||
@test.bim.bootstrap.scenario
|
@test.bim.bootstrap.scenario
|
||||||
@@ -115,3 +208,197 @@ class TestRemoveOpening(test.bim.bootstrap.NewFile):
|
|||||||
And I delete the selected objects
|
And I delete the selected objects
|
||||||
Then the object "Cube" is not an IFC element
|
Then the object "Cube" is not an IFC element
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class TestAddFilling(test.bim.bootstrap.NewFile):
|
||||||
|
@test.bim.bootstrap.scenario
|
||||||
|
def test_adding_a_filling(self):
|
||||||
|
return """
|
||||||
|
Given an empty IFC project
|
||||||
|
And I add a cube
|
||||||
|
When the object "Cube" is selected
|
||||||
|
And I set "scene.BIMRootProperties.ifc_class" to "IfcOpeningElement"
|
||||||
|
And I press "bim.assign_class"
|
||||||
|
And I add a cube
|
||||||
|
And the object "Cube" is selected
|
||||||
|
And I set "scene.BIMRootProperties.ifc_class" to "IfcDoor"
|
||||||
|
And I press "bim.assign_class"
|
||||||
|
And the object "IfcOpeningElement/Cube" is selected
|
||||||
|
And I press "bim.add_filling(opening='IfcOpeningElement/Cube', obj='IfcDoor/Cube')"
|
||||||
|
Then the object "IfcOpeningElement/Cube" is an "IfcOpeningElement"
|
||||||
|
And the object "IfcOpeningElement/Cube" should display as "WIRE"
|
||||||
|
And the object "IfcDoor/Cube" is an "IfcDoor"
|
||||||
|
And the void "IfcOpeningElement/Cube" is filled by "Cube"
|
||||||
|
"""
|
||||||
|
|
||||||
|
@test.bim.bootstrap.scenario
|
||||||
|
def test_adding_a_filling_on_null_object(self):
|
||||||
|
return """
|
||||||
|
Given an empty IFC project
|
||||||
|
And I add a cube
|
||||||
|
When the object "Cube" is selected
|
||||||
|
And I set "scene.BIMRootProperties.ifc_class" to "IfcDoor"
|
||||||
|
And I press "bim.assign_class"
|
||||||
|
And the object "IfcDoor/Cube" is selected
|
||||||
|
And I press "bim.add_filling(obj='IfcDoor/Cube')"
|
||||||
|
Then the object "IfcDoor/Cube" is an "IfcDoor"
|
||||||
|
And the object "IfcDoor/Cube" is not a filling
|
||||||
|
"""
|
||||||
|
|
||||||
|
@test.bim.bootstrap.scenario
|
||||||
|
def test_adding_a_filling_on_itself(self):
|
||||||
|
return """
|
||||||
|
Given an empty IFC project
|
||||||
|
And I add a cube
|
||||||
|
When the object "Cube" is selected
|
||||||
|
And I set "scene.BIMRootProperties.ifc_class" to "IfcOpeningElement"
|
||||||
|
And I press "bim.assign_class"
|
||||||
|
And the object "IfcOpeningElement/Cube" is selected
|
||||||
|
And I press "bim.add_filling(opening='IfcOpeningElement/Cube', obj='IfcOpeningElement/Cube')"
|
||||||
|
Then the object "IfcOpeningElement/Cube" is an "IfcOpeningElement"
|
||||||
|
And the void "IfcOpeningElement/Cube" is not filled by "Cube"
|
||||||
|
And the object "IfcOpeningElement/Cube" is not a filling
|
||||||
|
"""
|
||||||
|
|
||||||
|
@test.bim.bootstrap.scenario
|
||||||
|
def test_adding_a_filling_with_a_non_ifc_object(self):
|
||||||
|
return """
|
||||||
|
Given an empty IFC project
|
||||||
|
And I add a cube
|
||||||
|
When the object "Cube" is selected
|
||||||
|
And I set "scene.BIMRootProperties.ifc_class" to "IfcOpeningElement"
|
||||||
|
And I press "bim.assign_class"
|
||||||
|
And I add a cube
|
||||||
|
And the object "IfcOpeningElement/Cube" is selected
|
||||||
|
And I press "bim.add_filling(opening='IfcOpeningElement/Cube', obj='Cube')"
|
||||||
|
Then the object "Cube" is not an IFC element
|
||||||
|
And the object "IfcOpeningElement/Cube" is an "IfcOpeningElement"
|
||||||
|
And the void "IfcOpeningElement/Cube" is not filled by "Cube"
|
||||||
|
"""
|
||||||
|
|
||||||
|
@test.bim.bootstrap.scenario
|
||||||
|
def test_adding_a_filling_on_a_non_ifc_object(self):
|
||||||
|
return """
|
||||||
|
Given an empty IFC project
|
||||||
|
And I add a cube
|
||||||
|
When the object "Cube" is selected
|
||||||
|
And I set "scene.BIMRootProperties.ifc_class" to "IfcDoor"
|
||||||
|
And I press "bim.assign_class"
|
||||||
|
And I add a cube
|
||||||
|
And the object "Cube" is selected
|
||||||
|
And I press "bim.add_filling(opening='Cube', obj='IfcDoor/Cube')"
|
||||||
|
Then the object "Cube" is not an IFC element
|
||||||
|
And the object "IfcDoor/Cube" is an "IfcDoor"
|
||||||
|
"""
|
||||||
|
|
||||||
|
@test.bim.bootstrap.scenario
|
||||||
|
def test_adding_a_filling_on_opening_b_when_the_filling_alread_fills_element_a(self):
|
||||||
|
return """
|
||||||
|
Given an empty IFC project
|
||||||
|
And I add a cube
|
||||||
|
When the object "Cube" is selected
|
||||||
|
And I set "scene.BIMRootProperties.ifc_class" to "IfcOpeningElement"
|
||||||
|
And I press "bim.assign_class"
|
||||||
|
And I add a cube
|
||||||
|
And the object "Cube" is selected
|
||||||
|
And I set "scene.BIMRootProperties.ifc_class" to "IfcDoor"
|
||||||
|
And I press "bim.assign_class"
|
||||||
|
And I press "bim.add_filling(opening='IfcOpeningElement/Cube', obj='IfcDoor/Cube')"
|
||||||
|
And I add a cube
|
||||||
|
And the object "Cube" is selected
|
||||||
|
And I set "scene.BIMRootProperties.ifc_class" to "IfcOpeningElement"
|
||||||
|
And I press "bim.assign_class"
|
||||||
|
And I press "bim.add_filling(opening='IfcOpeningElement/Cube.001', obj='IfcDoor/Cube')"
|
||||||
|
Then the void "IfcOpeningElement/Cube" is not filled by "Cube"
|
||||||
|
And the void "IfcOpeningElement/Cube.001" is filled by "Cube"
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class TestRemoveFilling(test.bim.bootstrap.NewFile):
|
||||||
|
@test.bim.bootstrap.scenario
|
||||||
|
def test_removing_a_filling(self):
|
||||||
|
return """
|
||||||
|
Given an empty IFC project
|
||||||
|
And I add a cube
|
||||||
|
When the object "Cube" is selected
|
||||||
|
And I set "scene.BIMRootProperties.ifc_class" to "IfcOpeningElement"
|
||||||
|
And I press "bim.assign_class"
|
||||||
|
And I add a cube
|
||||||
|
And the object "Cube" is selected
|
||||||
|
And I set "scene.BIMRootProperties.ifc_class" to "IfcDoor"
|
||||||
|
And I press "bim.assign_class"
|
||||||
|
And I press "bim.add_filling(opening='IfcOpeningElement/Cube', obj='IfcDoor/Cube')"
|
||||||
|
And I press "bim.remove_filling(obj='IfcDoor/Cube')"
|
||||||
|
Then the object "IfcOpeningElement/Cube" is an "IfcOpeningElement"
|
||||||
|
And the object "IfcDoor/Cube" is an "IfcDoor"
|
||||||
|
And the void "IfcOpeningElement/Cube" is not filled by "Cube"
|
||||||
|
"""
|
||||||
|
|
||||||
|
@test.bim.bootstrap.scenario
|
||||||
|
def test_removing_a_filling_which_is_not_an_ifc_object(self):
|
||||||
|
return """
|
||||||
|
Given an empty IFC project
|
||||||
|
And I add a cube
|
||||||
|
When the object "Cube" is selected
|
||||||
|
And I press "bim.remove_filling(obj='Cube')"
|
||||||
|
Then the object "Cube" is not an IFC element
|
||||||
|
"""
|
||||||
|
|
||||||
|
@test.bim.bootstrap.scenario
|
||||||
|
def test_removing_a_filling_which_is_not_a_filling(self):
|
||||||
|
return """
|
||||||
|
Given an empty IFC project
|
||||||
|
And I add a cube
|
||||||
|
When the object "Cube" is selected
|
||||||
|
And I set "scene.BIMRootProperties.ifc_class" to "IfcDoor"
|
||||||
|
And I press "bim.assign_class"
|
||||||
|
And I press "bim.remove_filling(obj='IfcDoor/Cube')"
|
||||||
|
Then the object "IfcDoor/Cube" is an "IfcDoor"
|
||||||
|
And the object "IfcDoor/Cube" is not a filling
|
||||||
|
"""
|
||||||
|
|
||||||
|
@test.bim.bootstrap.scenario
|
||||||
|
def test_removing_a_filling_which_is_null(self):
|
||||||
|
return """
|
||||||
|
Given an empty IFC project
|
||||||
|
And I press "bim.remove_filling()"
|
||||||
|
Then nothing interesting happens
|
||||||
|
"""
|
||||||
|
|
||||||
|
@test.bim.bootstrap.scenario
|
||||||
|
def test_removing_a_filling_using_deletion_on_the_filling(self):
|
||||||
|
return """
|
||||||
|
Given an empty IFC project
|
||||||
|
And I add a cube
|
||||||
|
When the object "Cube" is selected
|
||||||
|
And I set "scene.BIMRootProperties.ifc_class" to "IfcOpeningElement"
|
||||||
|
And I press "bim.assign_class"
|
||||||
|
And I add a cube
|
||||||
|
And the object "Cube" is selected
|
||||||
|
And I set "scene.BIMRootProperties.ifc_class" to "IfcDoor"
|
||||||
|
And I press "bim.assign_class"
|
||||||
|
And I press "bim.add_filling(opening='IfcOpeningElement/Cube', obj='IfcDoor/Cube')"
|
||||||
|
And the object "IfcDoor/Cube" is selected
|
||||||
|
And I delete the selected objects
|
||||||
|
Then the object "IfcOpeningElement/Cube" is an "IfcOpeningElement"
|
||||||
|
And the void "IfcOpeningElement/Cube" is not filled by "Cube"
|
||||||
|
"""
|
||||||
|
|
||||||
|
@test.bim.bootstrap.scenario
|
||||||
|
def test_removing_a_filling_using_deletion_on_the_opening(self):
|
||||||
|
return """
|
||||||
|
Given an empty IFC project
|
||||||
|
And I add a cube
|
||||||
|
When the object "Cube" is selected
|
||||||
|
And I set "scene.BIMRootProperties.ifc_class" to "IfcOpeningElement"
|
||||||
|
And I press "bim.assign_class"
|
||||||
|
And I add a cube
|
||||||
|
And the object "Cube" is selected
|
||||||
|
And I set "scene.BIMRootProperties.ifc_class" to "IfcDoor"
|
||||||
|
And I press "bim.assign_class"
|
||||||
|
And I press "bim.add_filling(opening='IfcOpeningElement/Cube', obj='IfcDoor/Cube')"
|
||||||
|
And the object "IfcOpeningElement/Cube" is selected
|
||||||
|
And I delete the selected objects
|
||||||
|
Then the object "IfcDoor/Cube" is an "IfcDoor"
|
||||||
|
And the object "IfcDoor/Cube" is not a filling
|
||||||
|
"""
|
||||||
|
|||||||
Reference in New Issue
Block a user