diff --git a/src/blenderbim/blenderbim/bim/module/structural/data.py b/src/blenderbim/blenderbim/bim/module/structural/data.py new file mode 100644 index 0000000000..b547c2b2c5 --- /dev/null +++ b/src/blenderbim/blenderbim/bim/module/structural/data.py @@ -0,0 +1,46 @@ +# BlenderBIM Add-on - OpenBIM Blender Add-on +# Copyright (C) 2021 Dion Moult +# +# This file is part of BlenderBIM Add-on. +# +# BlenderBIM Add-on is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# BlenderBIM Add-on is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with BlenderBIM Add-on. If not, see . + +import bpy +import blenderbim.tool as tool + + +def refresh(): + StructuralData.is_loaded = False + + +class StructuralData: + products = {} + number_of_structural_analysis_models = 0 + is_loaded = False + + @classmethod + def load(cls): + cls.load_structural_analysis_models() + cls.is_loaded = True + + @classmethod + def load_structural_analysis_models(cls): + cls.products = {} + cls.number_of_structural_analysis_models = len(tool.Ifc.get().by_type("IfcStructuralAnalysisModel")) + + for model in tool.Ifc.get().by_type("IfcStructuralAnalysisModel"): + if model.IsGroupedBy: + for rel in model.IsGroupedBy: + for product in rel.RelatedObjects: + cls.products.setdefault(product.id(), []).append(model.id()) diff --git a/src/blenderbim/blenderbim/bim/module/structural/operator.py b/src/blenderbim/blenderbim/bim/module/structural/operator.py index aca1df208c..ff7db4599a 100644 --- a/src/blenderbim/blenderbim/bim/module/structural/operator.py +++ b/src/blenderbim/blenderbim/bim/module/structural/operator.py @@ -21,6 +21,8 @@ import json import ifcopenshell import ifcopenshell.api import blenderbim.bim.helper +import blenderbim.bim.handler +import blenderbim.core.structural as core import blenderbim.tool as tool import blenderbim.core.context from math import degrees @@ -29,6 +31,14 @@ from blenderbim.bim.ifc import IfcStore from blenderbim.bim.module.structural.prop import purge from ifcopenshell.api.structural.data import Data from ifcopenshell.api.context.data import Data as ContextData +from blenderbim.bim.module.structural.data import StructuralData + + +class Operator: + def execute(self, context): + IfcStore.execute_ifc_operator(self, context) + blenderbim.bim.handler.refresh_ui_data() + return {"FINISHED"} class AddStructuralMemberConnection(bpy.types.Operator): @@ -233,198 +243,102 @@ class DisableEditingStructuralBoundaryCondition(bpy.types.Operator): return {"FINISHED"} -class LoadStructuralAnalysisModels(bpy.types.Operator): +class LoadStructuralAnalysisModels(bpy.types.Operator, Operator): bl_idname = "bim.load_structural_analysis_models" bl_label = "Load Structural Analysis Models" bl_options = {"REGISTER", "UNDO"} - def execute(self, context): - props = context.scene.BIMStructuralProperties - props.structural_analysis_models.clear() - 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"] or "Unnamed" - props.is_editing = True - bpy.ops.bim.disable_editing_structural_analysis_model() - return {"FINISHED"} + def _execute(self, context): + core.load_structural_analysis_models(tool.Structural) -class DisableStructuralAnalysisModelEditingUI(bpy.types.Operator): +class DisableStructuralAnalysisModelEditingUI(bpy.types.Operator, Operator): bl_idname = "bim.disable_structural_analysis_model_editing_ui" bl_label = "Disable Structural Analysis Model Editing UI" bl_options = {"REGISTER", "UNDO"} - def execute(self, context): - context.scene.BIMStructuralProperties.is_editing = False - return {"FINISHED"} + def _execute(self, context): + core.disable_structural_analysis_model_editing_ui(tool.Structural) -class AddStructuralAnalysisModel(bpy.types.Operator): +class AddStructuralAnalysisModel(bpy.types.Operator, Operator): bl_idname = "bim.add_structural_analysis_model" bl_label = "Add Structural Analysis Model" bl_options = {"REGISTER", "UNDO"} - def execute(self, context): - return IfcStore.execute_ifc_operator(self, context) - def _execute(self, context): - result = ifcopenshell.api.run("structural.add_structural_analysis_model", IfcStore.get_file()) - - model = ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Model") - if not model: - model = blenderbim.core.context.add_context( - tool.Ifc, context_type="Model", context_identifier="", target_view="", parent=0 - ) - graph = ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Model", "Reference", "GRAPH_VIEW") - if not graph: - model = blenderbim.core.context.add_context( - tool.Ifc, context_type="Model", context_identifier="Reference", target_view="GRAPH_VIEW", parent=model - ) - - Data.load(IfcStore.get_file()) - bpy.ops.bim.load_structural_analysis_models() - bpy.ops.bim.enable_editing_structural_analysis_model(structural_analysis_model=result.id()) - return {"FINISHED"} + model = core.add_structural_analysis_model(tool.Ifc, tool.Structural) + core.load_structural_analysis_model_attributes(tool.Structural, model=model.id()) + core.enable_editing_structural_analysis_model(tool.Structural, model=model.id()) -class EditStructuralAnalysisModel(bpy.types.Operator): +class EditStructuralAnalysisModel(bpy.types.Operator, Operator): bl_idname = "bim.edit_structural_analysis_model" bl_label = "Edit Structural Analysis Model" bl_options = {"REGISTER", "UNDO"} - def execute(self, context): - return IfcStore.execute_ifc_operator(self, context) - def _execute(self, context): - props = context.scene.BIMStructuralProperties - attributes = blenderbim.bim.helper.export_attributes(props.structural_analysis_model_attributes) - self.file = IfcStore.get_file() - ifcopenshell.api.run( - "structural.edit_structural_analysis_model", - self.file, - **{ - "structural_analysis_model": self.file.by_id(props.active_structural_analysis_model_id), - "attributes": attributes, - }, - ) - Data.load(IfcStore.get_file()) - bpy.ops.bim.load_structural_analysis_models() - return {"FINISHED"} + core.edit_structural_analysis_model(tool.Ifc, tool.Structural) -class RemoveStructuralAnalysisModel(bpy.types.Operator): +class RemoveStructuralAnalysisModel(bpy.types.Operator, Operator): bl_idname = "bim.remove_structural_analysis_model" bl_label = "Remove Structural Analysis Model" bl_options = {"REGISTER", "UNDO"} structural_analysis_model: bpy.props.IntProperty() - def execute(self, context): - return IfcStore.execute_ifc_operator(self, context) - def _execute(self, context): - props = context.scene.BIMStructuralProperties - self.file = IfcStore.get_file() - ifcopenshell.api.run( - "structural.remove_structural_analysis_model", - self.file, - **{"structural_analysis_model": self.file.by_id(self.structural_analysis_model)}, - ) - Data.load(IfcStore.get_file()) - bpy.ops.bim.load_structural_analysis_models() - return {"FINISHED"} + core.remove_structural_analysis_model(tool.Ifc, tool.Structural, model=self.structural_analysis_model) -class EnableEditingStructuralAnalysisModel(bpy.types.Operator): +class EnableEditingStructuralAnalysisModel(bpy.types.Operator, Operator): bl_idname = "bim.enable_editing_structural_analysis_model" bl_label = "Enable Editing Structural Analysis Model" bl_options = {"REGISTER", "UNDO"} structural_analysis_model: bpy.props.IntProperty() - def execute(self, context): - props = context.scene.BIMStructuralProperties - props.structural_analysis_model_attributes.clear() - - 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 " +# +# This file is part of BlenderBIM Add-on. +# +# BlenderBIM Add-on is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# BlenderBIM Add-on is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with BlenderBIM Add-on. If not, see . + + +def add_structural_analysis_model(ifc, structural): + result = ifc.run("structural.add_structural_analysis_model") + structural.load_structural_analysis_models() + structural.ensure_representation_contexts() + return result + + +def assign_structural_analysis_model(ifc, structural, product=None, structural_analysis_model=None): + product = structural.get_product_or_active_object(product) + if structural_analysis_model and product: + ifc.run( + "structural.assign_structural_analysis_model", + **{ + "product": ifc.get().by_id(product.BIMObjectProperties.ifc_definition_id), + "structural_analysis_model": ifc.get().by_id(structural_analysis_model), + }, + ) + + +def disable_editing_structural_analysis_model(structural): + structural.disable_editing_structural_analysis_model() + + +def disable_structural_analysis_model_editing_ui(structural): + structural.disable_structural_analysis_model_editing_ui() + + +def edit_structural_analysis_model(ifc, structural): + attributes = structural.get_structural_analysis_model_attributes() + ifc.run( + "structural.edit_structural_analysis_model", + **{ + "structural_analysis_model": structural.get_active_structural_analysis_model(), + "attributes": attributes, + } + ) + structural.load_structural_analysis_models() + structural.disable_editing_structural_analysis_model() + + +def enable_editing_structural_analysis_model(structural, model=None): + structural.enable_editing_structural_analysis_model(model) + + +def enable_structural_analysis_model_editing_ui(structural): + structural.enable_structural_analysis_model_editing_ui() + + +def load_structural_analysis_model_attributes(structural, model=None): + data = structural.get_ifc_structural_analysis_model_attributes(model) + structural.load_structural_analysis_model_attributes(data) + + +def load_structural_analysis_models(structural): + structural.load_structural_analysis_models() + structural.enable_structural_analysis_model_editing_ui() + # structural.disable_editing_structural_analysis_model() + + +def remove_structural_analysis_model(ifc, structural, model=None): + ifc.run( + "structural.remove_structural_analysis_model", + **{"structural_analysis_model": ifc.get().by_id(model)}, + ) + structural.load_structural_analysis_models() + + +def unassign_structural_analysis_model(ifc, structural, product=None, structural_analysis_model=None): + product = structural.get_product_or_active_object(product) + if structural_analysis_model and product: + ifc.run( + "structural.unassign_structural_analysis_model", + **{ + "product": ifc.get().by_id(product.BIMObjectProperties.ifc_definition_id), + "structural_analysis_model": ifc.get().by_id(structural_analysis_model), + }, + ) diff --git a/src/blenderbim/blenderbim/core/tool.py b/src/blenderbim/blenderbim/core/tool.py index 6786ac1590..d3221a94af 100644 --- a/src/blenderbim/blenderbim/core/tool.py +++ b/src/blenderbim/blenderbim/core/tool.py @@ -255,6 +255,23 @@ class Spatial: def set_relative_object_matrix(cls, target_obj, relative_to_obj, matrix): pass +@interface +class Structural: + def disable_editing_structural_analysis_model(cls): pass + def disable_structural_analysis_model_editing_ui(cls): pass + def enable_editing_structural_analysis_model(cls, model): pass + def enable_structural_analysis_model_editing_ui(cls): pass + def enabled_structural_analysis_model_editing_ui(cls): pass + def ensure_representation_contexts(cls): pass + def get_active_structural_analysis_model(cls): pass + def get_ifc_structural_analysis_model_attributes(cls, model): pass + def get_ifc_structural_analysis_models(cls): pass + def get_product_or_active_object(cls): pass + def get_structural_analysis_model_attributes(cls): pass + def load_structural_analysis_model_attributes(cls, data): pass + def load_structural_analysis_models(cls): pass + + @interface class Style: def disable_editing(cls, obj): pass diff --git a/src/blenderbim/blenderbim/tool/__init__.py b/src/blenderbim/blenderbim/tool/__init__.py index ea37429716..7de559ecbe 100644 --- a/src/blenderbim/blenderbim/tool/__init__.py +++ b/src/blenderbim/blenderbim/tool/__init__.py @@ -32,6 +32,7 @@ from blenderbim.tool.pset import Pset from blenderbim.tool.qto import Qto from blenderbim.tool.root import Root from blenderbim.tool.spatial import Spatial +from blenderbim.tool.structural import Structural from blenderbim.tool.style import Style from blenderbim.tool.surveyor import Surveyor from blenderbim.tool.type import Type diff --git a/src/blenderbim/blenderbim/tool/structural.py b/src/blenderbim/blenderbim/tool/structural.py new file mode 100644 index 0000000000..089120d1ba --- /dev/null +++ b/src/blenderbim/blenderbim/tool/structural.py @@ -0,0 +1,156 @@ +# BlenderBIM Add-on - OpenBIM Blender Add-on +# Copyright (C) 2021 Dion Moult +# +# This file is part of BlenderBIM Add-on. +# +# BlenderBIM Add-on is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# BlenderBIM Add-on is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with BlenderBIM Add-on. If not, see . + +import bpy +import ifcopenshell +import json +import blenderbim.bim.helper +import blenderbim.core.tool +import blenderbim.core.structural +import blenderbim.tool as tool +from blenderbim.bim.ifc import IfcStore +from pprint import pprint + + +class Structural(blenderbim.core.tool.Structural): + @classmethod + def disable_editing_structural_analysis_model(cls): + bpy.context.scene.BIMStructuralProperties.active_structural_analysis_model_id = 0 + + @classmethod + def disable_structural_analysis_model_editing_ui(cls): + bpy.context.scene.BIMStructuralProperties.is_editing = False + + @classmethod + def enable_editing_structural_analysis_model(cls, model): + if model: + bpy.context.scene.BIMStructuralProperties.active_structural_analysis_model_id = model + + @classmethod + def enable_structural_analysis_model_editing_ui(cls): + bpy.context.scene.BIMStructuralProperties.is_editing = True + + @classmethod + def enabled_structural_analysis_model_editing_ui(cls): + return bpy.context.scene.BIMStructuralProperties.is_editing + + @classmethod + def ensure_representation_contexts(cls): + model = ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Model") + if not model: + model = tool.Ifc.run( + "context.add_context", + context_type="Model", + context_identifier="", + target_view="", + parent=0, + ) + graph = ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Model", "Reference", "GRAPH_VIEW") + if not graph: + model = tool.Ifc.run( + "context.add_context", + context_type="Model", + context_identifier="Reference", + target_view="GRAPH_VIEW", + parent=model, + ) + + @classmethod + def get_active_structural_analysis_model(cls): + props = bpy.context.scene.BIMStructuralProperties + model = tool.Ifc.get().by_id(props.active_structural_analysis_model_id) + return model + + @classmethod + def get_ifc_structural_analysis_model_attributes(cls, model): + if model: + ifc_model = tool.Ifc.get().by_id(model) + data = ifc_model.get_info() + + del data["OwnerHistory"] + + loaded_by = [] + for load_group in ifc_model.LoadedBy or []: + loaded_by.append(load_group.id()) + data["LoadedBy"] = loaded_by + + has_results = [] + for result_group in ifc_model.HasResults or []: + has_results.append(result_group.id()) + data["HasResults"] = has_results + + data["OrientationOf2DPlane"] = ( + ifc_model.OrientationOf2DPlane.id() if ifc_model.OrientationOf2DPlane else None + ) + data["SharedPlacement"] = ifc_model.SharedPlacement.id() if ifc_model.SharedPlacement else None + return data + + @classmethod + def get_ifc_structural_analysis_models(cls): + models = {} + for model in tool.Ifc.get().by_type("IfcStructuralAnalysisModel"): + models[model.id()] = {"Name": model.Name} + return models + + @classmethod + def get_product_or_active_object(cls, product): + product = bpy.data.objects.get(product) if product else bpy.context.active_object + try: + if product.BIMObjectProperties.ifc_definition_id: + return product + else: + return None + except: + return None + + @classmethod + def get_structural_analysis_model_attributes(cls): + props = bpy.context.scene.BIMStructuralProperties + attributes = blenderbim.bim.helper.export_attributes(props.structural_analysis_model_attributes) + return attributes + + @classmethod + def load_structural_analysis_model_attributes(cls, data): + props = bpy.context.scene.BIMStructuralProperties + props.structural_analysis_model_attributes.clear() + for attribute in IfcStore.get_schema().declaration_by_name("IfcStructuralAnalysisModel").all_attributes(): + data_type = str(attribute.type_of_attribute) + if "