diff --git a/src/blenderbim/blenderbim/bim/module/qto/helper.py b/src/blenderbim/blenderbim/bim/module/qto/helper.py index 09908fb6a8..721a2334da 100644 --- a/src/blenderbim/blenderbim/bim/module/qto/helper.py +++ b/src/blenderbim/blenderbim/bim/module/qto/helper.py @@ -62,7 +62,7 @@ def calculate_formwork_area(objs, context): """ Formwork is defined as the surface area required to cover all exposed surfaces of one or more objects, excluding top surfaces (i.e. that have a - face normal with a significant Z component). + face normal with a significant +Z component). """ copied_objs = [] result = 0 @@ -105,3 +105,19 @@ def calculate_formwork_area(objs, context): continue result += polygon.area return result + + +def calculate_side_formwork_area(objs, context): + """ + Side formwork is defined as the surface area required to cover all exposed + surfaces of one or more objects, excluding top and bottom surfaces (i.e. + that have a face normal with a significant Z component). + """ + result = 0 + for obj in objs: + mesh = obj.evaluated_get(context.evaluated_depsgraph_get()).to_mesh() + for polygon in mesh.polygons: + if abs(polygon.normal.z) > 0.8: + continue + result += polygon.area + return result diff --git a/src/blenderbim/blenderbim/bim/module/qto/operator.py b/src/blenderbim/blenderbim/bim/module/qto/operator.py index 0054dda845..90c55ac401 100644 --- a/src/blenderbim/blenderbim/bim/module/qto/operator.py +++ b/src/blenderbim/blenderbim/bim/module/qto/operator.py @@ -105,6 +105,8 @@ class ExecuteQtoMethod(bpy.types.Operator): result = helper.calculate_volumes(selected_mesh_objects, context) elif props.qto_methods == "FORMWORK": result = helper.calculate_formwork_area(selected_mesh_objects, context) + elif props.qto_methods == "SIDE_FORMWORK": + result = helper.calculate_side_formwork_area(selected_mesh_objects, context) props.qto_result = str(round(result, 3)) return {"FINISHED"} @@ -134,6 +136,8 @@ class QuantifyObjects(bpy.types.Operator): result = helper.calculate_volumes([obj], context) elif props.qto_methods == "FORMWORK": result = helper.calculate_formwork_area([obj], context) + elif props.qto_methods == "SIDE_FORMWORK": + result = helper.calculate_side_formwork_area([obj], context) if not result: continue result = round(result, 3) diff --git a/src/blenderbim/blenderbim/bim/module/qto/prop.py b/src/blenderbim/blenderbim/bim/module/qto/prop.py index 0bc3eb4af9..823d8921c1 100644 --- a/src/blenderbim/blenderbim/bim/module/qto/prop.py +++ b/src/blenderbim/blenderbim/bim/module/qto/prop.py @@ -37,7 +37,16 @@ class BIMQtoProperties(PropertyGroup): items=[ ("HEIGHT", "Height", "Calculate the Z height of an object"), ("VOLUME", "Volume", "Calculate the volume of an object"), - ("FORMWORK", "Formwork", "Calculate the exposed formwork for all bottoms and sides of one or more objects"), + ( + "FORMWORK", + "Formwork", + "Calculate the exposed formwork for all bottoms and sides (e.g. for beams and slabs) of one or more objects", + ), + ( + "SIDE_FORMWORK", + "Side Formwork", + "Calculate the exposed formwork for all sides only (e.g. for columns) of one or more objects", + ), ], name="Qto Methods", ) diff --git a/src/blenderbim/test/bim/feature/qto.feature b/src/blenderbim/test/bim/feature/qto.feature index 9fa0e005ff..def16ad469 100644 --- a/src/blenderbim/test/bim/feature/qto.feature +++ b/src/blenderbim/test/bim/feature/qto.feature @@ -29,7 +29,7 @@ Scenario: Calculate object volumes When I press "bim.calculate_object_volumes" Then "scene.BIMQtoProperties.qto_result" is "8.0" -Scenario: Calculate formwork areas +Scenario: Execute qto method - formwork areas Given an empty Blender session And I add a cube And I add a cube of size "1" at "1,0,0" @@ -38,3 +38,11 @@ Scenario: Calculate formwork areas When I set "scene.BIMQtoProperties.qto_methods" to "FORMWORK" And I press "bim.execute_qto_method" Then "scene.BIMQtoProperties.qto_result" is "21.5" + +Scenario: Execute qto method - side formwork areas + Given an empty Blender session + And I add a cube + And the object "Cube" is selected + When I set "scene.BIMQtoProperties.qto_methods" to "SIDE_FORMWORK" + And I press "bim.execute_qto_method" + Then "scene.BIMQtoProperties.qto_result" is "16.0" diff --git a/src/blenderbim/test/bim/feature/void.feature b/src/blenderbim/test/bim/feature/void.feature index e9a12ea8bc..7e901d23f4 100644 --- a/src/blenderbim/test/bim/feature/void.feature +++ b/src/blenderbim/test/bim/feature/void.feature @@ -38,7 +38,7 @@ Scenario: Add an opening on an opening Then the object "IfcOpeningElement/Cube.001" has no boolean difference by "IfcOpeningElement/Cube" And the object "IfcOpeningElement/Cube.001" is not voided by "Cube" -Scenario: Add an opening on a null object +Scenario: Add an opening on a null object Given an empty IFC project And I add a cube When the object "Cube" is selected @@ -89,11 +89,11 @@ Scenario: Add an opening to Element B with a void that already voids Element A 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" 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" + And the object "IfcWall/Cube.001" has a boolean difference by "IfcOpeningElement/Cube" -Scenario: Remove an opening +Scenario: Remove an opening Given an empty IFC project And I add a cube When the object "Cube" is selected @@ -108,7 +108,7 @@ Scenario: Remove an opening Then the object "IfcWall/Cube" has no boolean difference by "IfcOpeningElement/Cube" And the object "IfcWall/Cube" is not voided by "Cube" And the object "Cube" is not an IFC element - + Scenario: Remove a non dynamic opening manually Given an empty IFC project And I add a cube