From aa3a855b4c07ce8f971879c8500323bba061a14f Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Sat, 23 Jan 2021 18:01:29 +1100 Subject: [PATCH] Refactor qto utils and migrate to bmesh volume calculation. See #1222. --- .../blenderbim/bim/__init__.py | 6 +- .../blenderbim/bim/module/qto/__init__.py | 18 +++++ .../blenderbim/bim/module/qto/operator.py | 51 ++++++++++++++ .../blenderbim/bim/module/qto/prop.py | 17 +++++ .../blenderbim/bim/module/qto/ui.py | 23 +++++++ .../blenderbim/bim/operator.py | 67 ------------------- src/ifcblenderexport/blenderbim/bim/prop.py | 1 - src/ifcblenderexport/blenderbim/bim/ui.py | 24 ------- 8 files changed, 110 insertions(+), 97 deletions(-) create mode 100644 src/ifcblenderexport/blenderbim/bim/module/qto/__init__.py create mode 100644 src/ifcblenderexport/blenderbim/bim/module/qto/operator.py create mode 100644 src/ifcblenderexport/blenderbim/bim/module/qto/prop.py create mode 100644 src/ifcblenderexport/blenderbim/bim/module/qto/ui.py diff --git a/src/ifcblenderexport/blenderbim/bim/__init__.py b/src/ifcblenderexport/blenderbim/bim/__init__.py index 97ec732645..c8c1321c83 100644 --- a/src/ifcblenderexport/blenderbim/bim/__init__.py +++ b/src/ifcblenderexport/blenderbim/bim/__init__.py @@ -30,6 +30,7 @@ if bpy is not None: "owner": None, "project": None, "pset": None, + "qto": None, "search": None, "spatial": None, "style": None, @@ -117,10 +118,6 @@ if bpy is not None: operator.SelectIfcPatchInput, operator.SelectIfcPatchOutput, operator.ExecuteIfcPatch, - operator.CalculateEdgeLengths, - operator.CalculateFaceAreas, - operator.CalculateObjectVolumes, - operator.AddOpening, operator.SetOverrideColour, operator.AddDrawing, operator.RemoveDrawing, @@ -198,7 +195,6 @@ if bpy is not None: ui.BIM_PT_text, ui.BIM_PT_modeling_utilities, ui.BIM_PT_annotation_utilities, - ui.BIM_PT_qto_utilities, ui.BIM_PT_clash_manager, ui.BIM_PT_misc_utilities, ui.BIM_UL_generic, diff --git a/src/ifcblenderexport/blenderbim/bim/module/qto/__init__.py b/src/ifcblenderexport/blenderbim/bim/module/qto/__init__.py new file mode 100644 index 0000000000..cc11de2cde --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/qto/__init__.py @@ -0,0 +1,18 @@ +import bpy +from . import ui, prop, operator + +classes = ( + operator.CalculateEdgeLengths, + operator.CalculateFaceAreas, + operator.CalculateObjectVolumes, + prop.BIMQtoProperties, + ui.BIM_PT_qto_utilities, +) + + +def register(): + bpy.types.Scene.BIMQtoProperties = bpy.props.PointerProperty(type=prop.BIMQtoProperties) + + +def unregister(): + del bpy.types.Scene.BIMQtoProperties diff --git a/src/ifcblenderexport/blenderbim/bim/module/qto/operator.py b/src/ifcblenderexport/blenderbim/bim/module/qto/operator.py new file mode 100644 index 0000000000..a83c3183ff --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/qto/operator.py @@ -0,0 +1,51 @@ +import bpy +import bmesh + + +class CalculateEdgeLengths(bpy.types.Operator): + bl_idname = "bim.calculate_edge_lengths" + bl_label = "Calculate Edge Lengths" + + def execute(self, context): + result = 0 + for obj in bpy.context.selected_objects: + if not obj.data or not obj.data.edges: + continue + for edge in obj.data.edges: + if edge.select: + result += (obj.data.vertices[edge.vertices[1]].co - obj.data.vertices[edge.vertices[0]].co).length + bpy.context.scene.BIMQtoProperties.qto_result = str(round(result, 3)) + return {"FINISHED"} + + +class CalculateFaceAreas(bpy.types.Operator): + bl_idname = "bim.calculate_face_areas" + bl_label = "Calculate Face Areas" + + def execute(self, context): + result = 0 + for obj in bpy.context.selected_objects: + if not obj.data or not obj.data.polygons: + continue + for polygon in obj.data.polygons: + if polygon.select: + result += polygon.area + bpy.context.scene.BIMQtoProperties.qto_result = str(round(result, 3)) + return {"FINISHED"} + + +class CalculateObjectVolumes(bpy.types.Operator): + bl_idname = "bim.calculate_object_volumes" + bl_label = "Calculate Object Volumes" + + def execute(self, context): + result = 0 + for obj in bpy.context.selected_objects: + if not obj.data or not isinstance(obj.data, bpy.types.Mesh): + continue + bm = bmesh.new() + bm.from_mesh(obj.data) + result += bm.calc_volume() + bm.free() + bpy.context.scene.BIMQtoProperties.qto_result = str(round(result, 3)) + return {"FINISHED"} diff --git a/src/ifcblenderexport/blenderbim/bim/module/qto/prop.py b/src/ifcblenderexport/blenderbim/bim/module/qto/prop.py new file mode 100644 index 0000000000..ef3b6f0369 --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/qto/prop.py @@ -0,0 +1,17 @@ +import bpy +from blenderbim.bim.prop import StrProperty, Attribute +from blenderbim.bim.module.owner.data import Data +from bpy.types import PropertyGroup +from bpy.props import ( + PointerProperty, + StringProperty, + EnumProperty, + BoolProperty, + IntProperty, + FloatProperty, + FloatVectorProperty, + CollectionProperty, +) + +class BIMQtoProperties(PropertyGroup): + qto_result: StringProperty(default="", name="Qto Result") diff --git a/src/ifcblenderexport/blenderbim/bim/module/qto/ui.py b/src/ifcblenderexport/blenderbim/bim/module/qto/ui.py new file mode 100644 index 0000000000..d31283183a --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/qto/ui.py @@ -0,0 +1,23 @@ +from bpy.types import Panel + + +class BIM_PT_qto_utilities(Panel): + bl_idname = "BIM_PT_qto_utilities" + bl_label = "Quantity Take-off" + bl_space_type = "VIEW_3D" + bl_region_type = "UI" + bl_category = "BlenderBIM" + + def draw(self, context): + layout = self.layout + props = context.scene.BIMQtoProperties + + row = layout.row() + row.prop(props, "qto_result", text="Results") + + row = layout.row(align=True) + row.operator("bim.calculate_edge_lengths") + row = layout.row(align=True) + row.operator("bim.calculate_face_areas") + row = layout.row(align=True) + row.operator("bim.calculate_object_volumes") diff --git a/src/ifcblenderexport/blenderbim/bim/operator.py b/src/ifcblenderexport/blenderbim/bim/operator.py index 9621724e90..b5781196c8 100644 --- a/src/ifcblenderexport/blenderbim/bim/operator.py +++ b/src/ifcblenderexport/blenderbim/bim/operator.py @@ -1838,73 +1838,6 @@ class SelectIfcPatchOutput(bpy.types.Operator): return {"RUNNING_MODAL"} -class CalculateEdgeLengths(bpy.types.Operator): - bl_idname = "bim.calculate_edge_lengths" - bl_label = "Calculate Edge Lengths" - - def execute(self, context): - result = 0 - for obj in bpy.context.selected_objects: - if not obj.data or not obj.data.edges: - continue - for edge in obj.data.edges: - if edge.select: - result += (obj.data.vertices[edge.vertices[1]].co - obj.data.vertices[edge.vertices[0]].co).length - bpy.context.scene.BIMProperties.qto_result = str(round(result, 3)) - return {"FINISHED"} - - -class CalculateFaceAreas(bpy.types.Operator): - bl_idname = "bim.calculate_face_areas" - bl_label = "Calculate Face Areas" - - def execute(self, context): - result = 0 - for obj in bpy.context.selected_objects: - if not obj.data or not obj.data.polygons: - continue - for polygon in obj.data.polygons: - if polygon.select: - result += polygon.area - bpy.context.scene.BIMProperties.qto_result = str(round(result, 3)) - return {"FINISHED"} - - -class CalculateObjectVolumes(bpy.types.Operator): - bl_idname = "bim.calculate_object_volumes" - bl_label = "Calculate Object Volumes" - - def execute(self, context): - # TODO: reimplement - qto_calculator = qto.QtoCalculator() - result = 0 - for obj in bpy.context.selected_objects: - if not obj.data: - continue - result += qto_calculator.get_volume(obj) - bpy.context.scene.BIMProperties.qto_result = str(round(result, 3)) - return {"FINISHED"} - - -class AddOpening(bpy.types.Operator): - bl_idname = "bim.add_opening" - bl_label = "Add Opening" - - def execute(self, context): - if context.active_object.children and "IfcOpeningElement/" in context.active_object.children[0].name: - opening = context.active_object.children[0] - else: - opening = context.active_object - if context.selected_objects[0] != context.active_object: - obj = context.selected_objects[0] - else: - obj = context.selected_objects[1] - modifier = obj.modifiers.new("IfcOpeningElement", "BOOLEAN") - modifier.operation = "DIFFERENCE" - modifier.object = opening - return {"FINISHED"} - - class SetOverrideColour(bpy.types.Operator): bl_idname = "bim.set_override_colour" bl_label = "Set Override Colour" diff --git a/src/ifcblenderexport/blenderbim/bim/prop.py b/src/ifcblenderexport/blenderbim/bim/prop.py index af5812a98a..7d4b6d1860 100644 --- a/src/ifcblenderexport/blenderbim/bim/prop.py +++ b/src/ifcblenderexport/blenderbim/bim/prop.py @@ -764,7 +764,6 @@ class BIMProperties(PropertyGroup): ifc_patch_input: StringProperty(default="", name="IFC Patch Input IFC") ifc_patch_output: StringProperty(default="", name="IFC Patch Output IFC") ifc_patch_args: StringProperty(default="", name="Arguments") - qto_result: StringProperty(default="", name="Qto Result") area_unit: EnumProperty( default="SQUARE_METRE", items=[ diff --git a/src/ifcblenderexport/blenderbim/bim/ui.py b/src/ifcblenderexport/blenderbim/bim/ui.py index 41b0a3cb95..8fc7837313 100644 --- a/src/ifcblenderexport/blenderbim/bim/ui.py +++ b/src/ifcblenderexport/blenderbim/bim/ui.py @@ -832,30 +832,6 @@ class BIM_PT_annotation_utilities(Panel): layout.prop(props, "decorations_colour") -class BIM_PT_qto_utilities(Panel): - bl_idname = "BIM_PT_qto_utilities" - bl_label = "Quantity Take-off" - bl_space_type = "VIEW_3D" - bl_region_type = "UI" - bl_category = "BlenderBIM" - - def draw(self, context): - layout = self.layout - props = context.scene.BIMProperties - - row = layout.row() - layout.label(text="Results:") - row = layout.row() - row.prop(props, "qto_result", text="") - - row = layout.row(align=True) - row.operator("bim.calculate_edge_lengths") - row = layout.row(align=True) - row.operator("bim.calculate_face_areas") - row = layout.row(align=True) - row.operator("bim.calculate_object_volumes") - - class BIM_PT_clash_manager(Panel): bl_idname = "BIM_PT_clash_manager" bl_label = "Clash Manager"