From b6072423395e9b6c3145af6ebd3994562678898a Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Thu, 11 Mar 2021 10:46:55 +1100 Subject: [PATCH] You can now add/edit/remove/assign/unassign structural analysis models --- .../blenderbim/bim/__init__.py | 1 + .../bim/module/structural/__init__.py | 26 +++ .../add_structural_analysis_model.py | 18 ++ .../assign_structural_analysis_model.py | 28 +++ .../blenderbim/bim/module/structural/data.py | 39 +++++ .../edit_structural_analysis_model.py | 13 ++ .../bim/module/structural/operator.py | 160 ++++++++++++++++++ .../blenderbim/bim/module/structural/prop.py | 26 +++ .../remove_structural_analysis_model.py | 11 ++ .../blenderbim/bim/module/structural/ui.py | 87 ++++++++++ .../unassign_structural_analysis_model.py | 25 +++ 11 files changed, 434 insertions(+) create mode 100644 src/ifcblenderexport/blenderbim/bim/module/structural/__init__.py create mode 100644 src/ifcblenderexport/blenderbim/bim/module/structural/add_structural_analysis_model.py create mode 100644 src/ifcblenderexport/blenderbim/bim/module/structural/assign_structural_analysis_model.py create mode 100644 src/ifcblenderexport/blenderbim/bim/module/structural/data.py create mode 100644 src/ifcblenderexport/blenderbim/bim/module/structural/edit_structural_analysis_model.py create mode 100644 src/ifcblenderexport/blenderbim/bim/module/structural/operator.py create mode 100644 src/ifcblenderexport/blenderbim/bim/module/structural/prop.py create mode 100644 src/ifcblenderexport/blenderbim/bim/module/structural/remove_structural_analysis_model.py create mode 100644 src/ifcblenderexport/blenderbim/bim/module/structural/ui.py create mode 100644 src/ifcblenderexport/blenderbim/bim/module/structural/unassign_structural_analysis_model.py diff --git a/src/ifcblenderexport/blenderbim/bim/__init__.py b/src/ifcblenderexport/blenderbim/bim/__init__.py index 117e5451d4..c467131273 100644 --- a/src/ifcblenderexport/blenderbim/bim/__init__.py +++ b/src/ifcblenderexport/blenderbim/bim/__init__.py @@ -26,6 +26,7 @@ if bpy is not None: "cobie": None, "sequence": None, "group": None, + "structural": None, "material": None, "style": None, "layer": None, diff --git a/src/ifcblenderexport/blenderbim/bim/module/structural/__init__.py b/src/ifcblenderexport/blenderbim/bim/module/structural/__init__.py new file mode 100644 index 0000000000..234a1a8742 --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/structural/__init__.py @@ -0,0 +1,26 @@ +import bpy +from . import ui, prop, operator + +classes = ( + operator.LoadStructuralAnalysisModels, + operator.DisableStructuralAnalysisModelEditingUI, + operator.AddStructuralAnalysisModel, + operator.EditStructuralAnalysisModel, + operator.RemoveStructuralAnalysisModel, + operator.AssignStructuralAnalysisModel, + operator.UnassignStructuralAnalysisModel, + operator.EnableEditingStructuralAnalysisModel, + operator.DisableEditingStructuralAnalysisModel, + prop.StructuralAnalysisModel, + prop.BIMStructuralProperties, + ui.BIM_PT_structural, + ui.BIM_UL_structural_analysis_models, +) + + +def register(): + bpy.types.Scene.BIMStructuralProperties = bpy.props.PointerProperty(type=prop.BIMStructuralProperties) + + +def unregister(): + del bpy.types.Scene.BIMStructuralProperties diff --git a/src/ifcblenderexport/blenderbim/bim/module/structural/add_structural_analysis_model.py b/src/ifcblenderexport/blenderbim/bim/module/structural/add_structural_analysis_model.py new file mode 100644 index 0000000000..f7539c02ed --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/structural/add_structural_analysis_model.py @@ -0,0 +1,18 @@ +import ifcopenshell +from blenderbim.bim.module.owner.api import create_owner_history + + +class Usecase: + def __init__(self, file, settings={}): + self.file = file + self.settings = {} + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + return self.file.create_entity("IfcStructuralAnalysisModel", **{ + "GlobalId": ifcopenshell.guid.new(), + "OwnerHistory": create_owner_history(), + "Name": "Unnamed", + "PredefinedType": "LOADING_3D" + }) diff --git a/src/ifcblenderexport/blenderbim/bim/module/structural/assign_structural_analysis_model.py b/src/ifcblenderexport/blenderbim/bim/module/structural/assign_structural_analysis_model.py new file mode 100644 index 0000000000..e130b87548 --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/structural/assign_structural_analysis_model.py @@ -0,0 +1,28 @@ +import ifcopenshell +from blenderbim.bim.module.owner.api import create_owner_history +from blenderbim.bim.module.owner.api import update_owner_history + + +class Usecase: + def __init__(self, file, settings=None): + self.file = file + self.settings = { + "product": None, + "structural_analysis_model": None, + } + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + if not self.settings["structural_analysis_model"].IsGroupedBy: + return self.file.create_entity("IfcRelAssignsToGroup", **{ + "GlobalId": ifcopenshell.guid.new(), + "OwnerHistory": create_owner_history(), + "RelatedObjects": [self.settings["product"]], + "RelatingGroup": self.settings["structural_analysis_model"] + }) + rel = self.settings["structural_analysis_model"].IsGroupedBy[0] + related_objects = set(rel.RelatedObjects) or set() + related_objects.add(self.settings["product"]) + rel.RelatedObjects = list(related_objects) + update_owner_history(rel) diff --git a/src/ifcblenderexport/blenderbim/bim/module/structural/data.py b/src/ifcblenderexport/blenderbim/bim/module/structural/data.py new file mode 100644 index 0000000000..4016609056 --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/structural/data.py @@ -0,0 +1,39 @@ +from blenderbim.bim.ifc import IfcStore + + +class Data: + is_loaded = False + products = {} + structural_analysis_models = {} + + @classmethod + def purge(cls): + cls.is_loaded = False + cls.products = {} + cls.structural_analysis_models = {} + + @classmethod + def load(cls): + cls.products = {} + cls.structural_analysis_models = {} + for model in IfcStore.get_file().by_type("IfcStructuralAnalysisModel"): + if model.IsGroupedBy: + for rel in model.IsGroupedBy: + for product in rel.RelatedObjects: + cls.products.setdefault(product.id(), []).append(model.id()) + data = model.get_info() + del data["OwnerHistory"] + del data["OrientationOf2DPlane"] + + loaded_by = [] + for load_group in model.LoadedBy or []: + loaded_by.append(load_group.id()) + data["LoadedBy"] = loaded_by + + has_results = [] + for result_group in model.HasResults or []: + has_results.append(result_group.id()) + data["HasResults"] = has_results + + cls.structural_analysis_models[model.id()] = data + cls.is_loaded=True diff --git a/src/ifcblenderexport/blenderbim/bim/module/structural/edit_structural_analysis_model.py b/src/ifcblenderexport/blenderbim/bim/module/structural/edit_structural_analysis_model.py new file mode 100644 index 0000000000..ba542d7795 --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/structural/edit_structural_analysis_model.py @@ -0,0 +1,13 @@ +class Usecase: + def __init__(self, file, settings=None): + self.file = file + self.settings = { + "structural_analysis_model": None, + "attributes": {} + } + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + for name, value in self.settings["attributes"].items(): + setattr(self.settings["structural_analysis_model"], name, value) diff --git a/src/ifcblenderexport/blenderbim/bim/module/structural/operator.py b/src/ifcblenderexport/blenderbim/bim/module/structural/operator.py new file mode 100644 index 0000000000..a4dfa6d073 --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/structural/operator.py @@ -0,0 +1,160 @@ +import bpy +import json +import blenderbim.bim.module.structural.add_structural_analysis_model as add_structural_analysis_model +import blenderbim.bim.module.structural.edit_structural_analysis_model as edit_structural_analysis_model +import blenderbim.bim.module.structural.remove_structural_analysis_model as remove_structural_analysis_model +import blenderbim.bim.module.structural.assign_structural_analysis_model as assign_structural_analysis_model +import blenderbim.bim.module.structural.unassign_structural_analysis_model as unassign_structural_analysis_model +from blenderbim.bim.ifc import IfcStore +from blenderbim.bim.module.structural.data import Data + + +class LoadStructuralAnalysisModels(bpy.types.Operator): + bl_idname = "bim.load_structural_analysis_models" + bl_label = "Load Structural Analysis Models" + + def execute(self, context): + props = context.scene.BIMStructuralProperties + while len(props.structural_analysis_models) > 0: + props.structural_analysis_models.remove(0) + for ifc_definition_id, structural_analysis_model in Data.structural_analysis_models.items(): + new = props.structural_analysis_models.add() + new.ifc_definition_id = ifc_definition_id + new.name = structural_analysis_model["Name"] + props.is_editing = True + bpy.ops.bim.disable_editing_structural_analysis_model() + return {"FINISHED"} + + +class DisableStructuralAnalysisModelEditingUI(bpy.types.Operator): + bl_idname = "bim.disable_structural_analysis_model_editing_ui" + bl_label = "Disable Structural Analysis Model Editing UI" + + def execute(self, context): + context.scene.BIMStructuralProperties.is_editing = False + return {"FINISHED"} + + +class AddStructuralAnalysisModel(bpy.types.Operator): + bl_idname = "bim.add_structural_analysis_model" + bl_label = "Add Structural Analysis Model" + + def execute(self, context): + result = add_structural_analysis_model.Usecase(IfcStore.get_file()).execute() + Data.load() + bpy.ops.bim.load_structural_analysis_models() + bpy.ops.bim.enable_editing_structural_analysis_model(structural_analysis_model=result.id()) + return {"FINISHED"} + + +class EditStructuralAnalysisModel(bpy.types.Operator): + bl_idname = "bim.edit_structural_analysis_model" + bl_label = "Edit Structural Analysis Model" + + def execute(self, context): + props = context.scene.BIMStructuralProperties + attributes = {} + for attribute in props.structural_analysis_model_attributes: + if attribute.is_null: + attributes[attribute.name] = None + else: + if attribute.data_type == "string": + attributes[attribute.name] = attribute.string_value + elif attribute.data_type == "enum": + attributes[attribute.name] = attribute.enum_value + self.file = IfcStore.get_file() + edit_structural_analysis_model.Usecase( + self.file, {"structural_analysis_model": self.file.by_id(props.active_structural_analysis_model_id), "attributes": attributes} + ).execute() + Data.load() + bpy.ops.bim.load_structural_analysis_models() + return {"FINISHED"} + + +class RemoveStructuralAnalysisModel(bpy.types.Operator): + bl_idname = "bim.remove_structural_analysis_model" + bl_label = "Remove Structural Analysis Model" + structural_analysis_model: bpy.props.IntProperty() + + def execute(self, context): + props = context.scene.BIMStructuralProperties + self.file = IfcStore.get_file() + remove_structural_analysis_model.Usecase(self.file, {"structural_analysis_model": self.file.by_id(self.structural_analysis_model)}).execute() + Data.load() + bpy.ops.bim.load_structural_analysis_models() + return {"FINISHED"} + + +class EnableEditingStructuralAnalysisModel(bpy.types.Operator): + bl_idname = "bim.enable_editing_structural_analysis_model" + bl_label = "Enable Editing Structural Analysis Model" + structural_analysis_model: bpy.props.IntProperty() + + def execute(self, context): + props = context.scene.BIMStructuralProperties + while len(props.structural_analysis_model_attributes) > 0: + props.structural_analysis_model_attributes.remove(0) + + data = Data.structural_analysis_models[self.structural_analysis_model] + + for attribute in IfcStore.get_schema().declaration_by_name("IfcStructuralAnalysisModel").all_attributes(): + data_type = str(attribute.type_of_attribute) + if "