From 1abf854f014a6a5ca9bb4267f183bbed594e15f6 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Mon, 24 May 2021 18:56:20 +1000 Subject: [PATCH] New formwork area calculation feature --- .../blenderbim/bim/module/qto/helper.py | 48 +++++++++++++++++++ .../blenderbim/bim/module/qto/operator.py | 4 ++ 2 files changed, 52 insertions(+) diff --git a/src/blenderbim/blenderbim/bim/module/qto/helper.py b/src/blenderbim/blenderbim/bim/module/qto/helper.py index ac95e84b2c..b55992bf00 100644 --- a/src/blenderbim/blenderbim/bim/module/qto/helper.py +++ b/src/blenderbim/blenderbim/bim/module/qto/helper.py @@ -1,3 +1,4 @@ +import bpy import bmesh @@ -11,3 +12,50 @@ def calculate_volume(obj): result = bm.calc_volume() bm.free() return result + + +def calculate_formwork_area(objs): + """ + 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). + """ + copied_objs = [] + result = 0 + + for obj in objs: + new_obj = obj.copy() + new_obj.data = obj.data.copy() + new_obj.animation_data_clear() + bpy.context.collection.objects.link(new_obj) + copied_objs.append(new_obj) + + context_override = {} + context_override["object"] = context_override["active_object"] = copied_objs[0] + context_override["selected_objects"] = context_override["selected_editable_objects"] = copied_objs + bpy.ops.object.join(context_override) + + copied_objs[0].name = "Formwork" + copied_objs[0].BIMObjectProperties.ifc_definition_id = 0 + modifier = copied_objs[0].modifiers.new("Formwork", "REMESH") + modifier.mode = "SHARP" + # This hardcoded value may be optimised through a better understanding of the octree division. + # These values are based off some trial and error heuristics I've learned through experience. + max_dim = max(copied_objs[0].dimensions) + if max_dim > 45: + modifier.octree_depth = 9 + elif max_dim > 35: + modifier.octree_depth = 8 + elif max_dim > 12: + modifier.octree_depth = 7 + elif max_dim > 5: + modifier.octree_depth = 6 + else: + modifier.octree_depth = 5 + + mesh = copied_objs[0].evaluated_get(bpy.context.evaluated_depsgraph_get()).to_mesh() + for polygon in mesh.polygons: + if polygon.normal.z > 0.5: + 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 90911a67e3..ee09dc4a82 100644 --- a/src/blenderbim/blenderbim/bim/module/qto/operator.py +++ b/src/blenderbim/blenderbim/bim/module/qto/operator.py @@ -69,6 +69,8 @@ class ExecuteQtoMethod(bpy.types.Operator): elif props.qto_methods == "VOLUME": for obj in bpy.context.selected_objects: result += helper.calculate_volume(obj) + elif props.qto_methods == "FORMWORK": + result = helper.calculate_formwork_area(bpy.context.selected_objects) props.qto_result = str(round(result, 3)) return {"FINISHED"} @@ -88,6 +90,8 @@ class QuantifyObjects(bpy.types.Operator): result = helper.calculate_height(obj) elif props.qto_methods == "VOLUME": result = helper.calculate_volume(obj) + elif props.qto_methods == "FORMWORK": + result = helper.calculate_formwork_area([obj]) if not result: continue result = round(result, 3)