See #1848. Refactor structural data class.

This commit is contained in:
Dion Moult
2023-02-01 14:54:31 +11:00
parent cfaacf8650
commit 4efb80efe4
4 changed files with 448 additions and 369 deletions
@@ -18,29 +18,262 @@
import bpy
import blenderbim.tool as tool
import ifcopenshell.util.doc
def refresh():
StructuralData.is_loaded = False
StructuralBoundaryConditionsData.is_loaded = False
ConnectedStructuralMembersData.is_loaded = False
StructuralMemberData.is_loaded = False
StructuralConnectionData.is_loaded = False
StructuralAnalysisModelsData.is_loaded = False
StructuralLoadCasesData.is_loaded = False
StructuralLoadsData.is_loaded = False
BoundaryConditionsData.is_loaded = False
class StructuralData:
products = {}
number_of_structural_analysis_models = 0
class StructuralBoundaryConditionsData:
data = {}
is_loaded = False
@classmethod
def load(cls):
cls.load_structural_analysis_models()
cls.data = {"boundary_condition": cls.boundary_condition(), "connection_id": cls.connection_id()}
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"))
def boundary_condition(cls):
obj = bpy.context.active_object
element = tool.Ifc.get_entity(obj)
if not element or not element.AppliedCondition:
return
condition = element.AppliedCondition
attributes = []
for name, value in condition.get_info().items():
if name in ["id", "type"] or value is None:
continue
attributes.append({"name": name, "value": value, "is_bool": isinstance(value, bool)})
return {"id": condition.id(), "type": condition.is_a(), "attributes": attributes}
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())
@classmethod
def connection_id(cls):
obj = bpy.context.active_object
element = tool.Ifc.get_entity(obj)
if element:
return element.id()
class ConnectedStructuralMembersData:
data = {}
is_loaded = False
@classmethod
def load(cls):
cls.data = {"connections": cls.connections()}
cls.is_loaded = True
@classmethod
def connections(cls):
obj = bpy.context.active_object
element = tool.Ifc.get_entity(obj)
if not element:
return []
results = []
props = bpy.context.active_object.BIMStructuralProperties
for rel in element.ConnectsStructuralMembers or []:
condition = rel.AppliedCondition
if condition:
attributes = []
for name, value in condition.get_info().items():
if name in ["id", "type"] or value is None:
continue
attributes.append({"name": name, "value": value, "is_bool": isinstance(value, bool)})
condition = {"id": condition.id(), "type": condition.is_a(), "attributes": attributes}
results.append(
{
"id": rel.id(),
"member_name": rel.RelatingStructuralMember.Name or "Unnamed",
"is_active_condition": bool(condition and props.active_boundary_condition == condition["id"]),
"condition": condition,
}
)
return results
class StructuralMemberData:
data = {}
is_loaded = False
@classmethod
def load(cls):
cls.data = {"active_object_class": cls.active_object_class()}
cls.is_loaded = True
@classmethod
def active_object_class(cls):
obj = bpy.context.active_object
element = tool.Ifc.get_entity(obj)
if element:
return element.is_a()
class StructuralConnectionData:
data = {}
is_loaded = False
@classmethod
def load(cls):
cls.data = {"active_object_class": cls.active_object_class()}
cls.is_loaded = True
@classmethod
def active_object_class(cls):
obj = bpy.context.active_object
element = tool.Ifc.get_entity(obj)
if element:
return element.is_a()
class StructuralAnalysisModelsData:
data = {}
is_loaded = False
@classmethod
def load(cls):
cls.data = {"total_models": cls.total_models(), "active_model_ids": cls.active_model_ids()}
cls.is_loaded = True
@classmethod
def total_models(cls):
return len(tool.Ifc.get().by_type("IfcStructuralAnalysisModel"))
@classmethod
def active_model_ids(cls):
obj = bpy.context.active_object
element = tool.Ifc.get_entity(obj)
if not element:
return []
results = []
for rel in getattr(element, "HasAssignments", []) or []:
if rel.is_a("IfcRelAssignsToGroup"):
results.append(rel.RelatingGroup.id())
return results
class StructuralLoadCasesData:
data = {}
is_loaded = False
@classmethod
def load(cls):
cls.is_loaded = True
cls.data = {
"load_cases": cls.load_cases(),
"applicable_structural_load_types": cls.applicable_structural_load_types(),
"applicable_structural_loads": cls.applicable_structural_loads(),
}
@classmethod
def load_cases(cls):
results = []
for load_case in tool.Ifc.get().by_type("IfcStructuralLoadCase"):
load_groups = []
for rel in load_case.IsGroupedBy or []:
for related_object in rel.RelatedObjects:
load_groups.append({"id": related_object.id(), "name": related_object.Name or "Unnamed"})
results.append({"id": load_case.id(), "name": load_case.Name or "Unnamed", "load_groups": load_groups})
return results
@classmethod
def applicable_structural_load_types(cls):
element_classes = set()
for obj in bpy.context.selected_objects:
element = tool.Ifc.get_entity(obj)
if element:
element_classes.add(element.is_a())
types = [("IfcStructuralLoadTemperature", "IfcStructuralLoadTemperature", "")]
if "IfcStructuralPointConnection" in element_classes:
types.extend(
[
("IfcStructuralLoadSingleForce", "IfcStructuralLoadSingleForce", ""),
("IfcStructuralLoadSingleDisplacement", "IfcStructuralLoadSingleDisplacement", ""),
]
)
if "IfcStructuralCurveMember" in element_classes:
types.append(("IfcStructuralLoadLinearForce", "IfcStructuralLoadLinearForce", ""))
if "IfcStructuralSurfaceMember" in element_classes:
types.append(("IfcStructuralLoadPlanarForce", "IfcStructuralLoadPlanarForce", ""))
return types
@classmethod
def applicable_structural_loads(cls):
props = bpy.context.scene.BIMStructuralProperties
results = []
for load in tool.Ifc.get().by_type("IfcStructuralLoad"):
if not load.Name or not load.is_a(props.applicable_structural_load_types):
continue
results.append((str(load.id()), load.Name or "Unnamed", ""))
return results
class StructuralLoadsData:
data = {}
is_loaded = False
@classmethod
def load(cls):
cls.data = {
"total_loads": cls.total_loads(),
"load_classes": cls.load_classes(),
"structural_load_types": cls.structural_load_types()
}
cls.is_loaded = True
@classmethod
def total_loads(cls):
return len(tool.Ifc.get().by_type("IfcStructuralLoad"))
@classmethod
def load_classes(cls):
return {l.id(): l.is_a() for l in tool.Ifc.get().by_type("IfcStructuralLoad")}
@classmethod
def structural_load_types(cls):
declaration = tool.Ifc.schema().declaration_by_name("IfcStructuralLoadStatic")
version = tool.Ifc.get_schema()
return [
(d.name(), d.name(), ifcopenshell.util.doc.get_entity_doc(version, d.name()).get("description", ""))
for d in declaration.subtypes()
]
class BoundaryConditionsData:
data = {}
is_loaded = False
@classmethod
def load(cls):
cls.data = {
"total_conditions": cls.total_conditions(),
"condition_classes": cls.condition_classes(),
"boundary_condition_types": cls.boundary_condition_types(),
}
cls.is_loaded = True
@classmethod
def total_conditions(cls):
return len(tool.Ifc.get().by_type("IfcBoundaryCondition"))
@classmethod
def condition_classes(cls):
return {c.id(): c.is_a() for c in tool.Ifc.get().by_type("IfcBoundaryCondition")}
@classmethod
def boundary_condition_types(cls):
declaration = tool.Ifc.schema().declaration_by_name("IfcBoundaryCondition")
version = tool.Ifc.get_schema()
return [
(d.name(), d.name(), ifcopenshell.util.doc.get_entity_doc(version, d.name()).get("description", ""))
for d in declaration.subtypes()
]
@@ -28,27 +28,13 @@ import blenderbim.core.context
from math import degrees
from mathutils import Vector, Matrix
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):
class AddStructuralMemberConnection(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.add_structural_member_connection"
bl_label = "Add Structural Member Connection"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
obj = context.active_object
oprops = obj.BIMObjectProperties
@@ -65,7 +51,6 @@ class AddStructuralMemberConnection(bpy.types.Operator):
related_structural_connection=related_structural_connection,
)
props.relating_structural_member = None
Data.load(IfcStore.get_file(), related_structural_connection.id())
return {"FINISHED"}
@@ -79,7 +64,6 @@ class EnableEditingStructuralConnectionCondition(bpy.types.Operator):
obj = context.active_object
oprops = obj.BIMObjectProperties
props = obj.BIMStructuralProperties
applied_condition_id = Data.connects_structural_members[self.connects_structural_member]["AppliedCondition"]
props.active_connects_structural_member = self.connects_structural_member
return {"FINISHED"}
@@ -96,62 +80,43 @@ class DisableEditingStructuralConnectionCondition(bpy.types.Operator):
return {"FINISHED"}
class RemoveStructuralConnectionCondition(bpy.types.Operator):
class RemoveStructuralConnectionCondition(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.remove_structural_connection_condition"
bl_label = "Remove Structural Connection Condition"
bl_options = {"REGISTER", "UNDO"}
connects_structural_member: bpy.props.IntProperty()
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
file = IfcStore.get_file()
relation = file.by_id(self.connects_structural_member)
connection = relation.RelatedStructuralConnection
ifcopenshell.api.run("structural.remove_structural_connection_condition", file, **{"relation": relation})
Data.load(IfcStore.get_file(), connection.id())
return {"FINISHED"}
class AddStructuralBoundaryCondition(bpy.types.Operator):
class AddStructuralBoundaryCondition(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.add_structural_boundary_condition"
bl_label = "Add Structural Boundary Condition"
bl_options = {"REGISTER", "UNDO"}
connection: bpy.props.IntProperty()
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
file = IfcStore.get_file()
connection = file.by_id(self.connection)
ifcopenshell.api.run("structural.add_structural_boundary_condition", file, **{"connection": connection})
if connection.is_a("IfcRelConnectsStructuralMember"):
Data.load(IfcStore.get_file(), connection.RelatedStructuralConnection.id())
else:
Data.load(IfcStore.get_file(), connection.id())
return {"FINISHED"}
class RemoveStructuralBoundaryCondition(bpy.types.Operator):
class RemoveStructuralBoundaryCondition(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.remove_structural_boundary_condition"
bl_label = "Remove Structural Boundary Condition"
bl_options = {"REGISTER", "UNDO"}
connection: bpy.props.IntProperty()
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
file = IfcStore.get_file()
connection = file.by_id(self.connection)
ifcopenshell.api.run("structural.remove_structural_boundary_condition", file, **{"connection": connection})
if connection.is_a("IfcRelConnectsStructuralMember"):
Data.load(IfcStore.get_file(), connection.RelatedStructuralConnection.id())
else:
Data.load(IfcStore.get_file(), connection.id())
return {"FINISHED"}
@@ -166,10 +131,10 @@ class EnableEditingStructuralBoundaryCondition(bpy.types.Operator):
props = obj.BIMStructuralProperties
props.boundary_condition_attributes.clear()
data = Data.boundary_conditions[self.boundary_condition]
condition = tool.Ifc.get().by_id(self.boundary_condition)
for attribute in IfcStore.get_schema().declaration_by_name(data["type"]).all_attributes():
value = data[attribute.name()]
for attribute in IfcStore.get_schema().declaration_by_name(condition.is_a()).all_attributes():
value = getattr(condition, attribute.name(), None)
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
new = props.boundary_condition_attributes.add()
new.name = attribute.name()
@@ -179,30 +144,27 @@ class EnableEditingStructuralBoundaryCondition(bpy.types.Operator):
enum_items = [s.name() for s in ifcopenshell.util.attribute.get_select_items(attribute)]
new.enum_items = json.dumps(enum_items)
if isinstance(value, bool):
new.bool_value = False if new.is_null else data[attribute.name()]
new.bool_value = False if new.is_null else value
new.data_type = "bool"
new.enum_value = "IfcBoolean"
elif isinstance(value, float):
new.float_value = 0.0 if new.is_null else data[attribute.name()]
new.float_value = 0.0 if new.is_null else value
new.data_type = "float"
new.enum_value = [i for i in enum_items if i != "IfcBoolean"][0]
elif data_type == "string":
new.string_value = "" if new.is_null else data[attribute.name()]
new.string_value = "" if new.is_null else value
new.data_type = "string"
props.active_boundary_condition = self.boundary_condition
return {"FINISHED"}
class EditStructuralBoundaryCondition(bpy.types.Operator):
class EditStructuralBoundaryCondition(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.edit_structural_boundary_condition"
bl_label = "Edit Structural Boundary Condition"
bl_options = {"REGISTER", "UNDO"}
connection: bpy.props.IntProperty()
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
obj = context.active_object
props = obj.BIMStructuralProperties
@@ -225,10 +187,6 @@ class EditStructuralBoundaryCondition(bpy.types.Operator):
ifcopenshell.api.run(
"structural.edit_structural_boundary_condition", file, **{"condition": condition, "attributes": attributes}
)
if connection.is_a("IfcRelConnectsStructuralMember"):
Data.load(IfcStore.get_file(), connection.RelatedStructuralConnection.id())
else:
Data.load(IfcStore.get_file(), connection.id())
bpy.ops.bim.disable_editing_structural_boundary_condition()
return {"FINISHED"}
@@ -243,7 +201,7 @@ class DisableEditingStructuralBoundaryCondition(bpy.types.Operator):
return {"FINISHED"}
class LoadStructuralAnalysisModels(bpy.types.Operator, Operator):
class LoadStructuralAnalysisModels(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.load_structural_analysis_models"
bl_label = "Load Structural Analysis Models"
bl_options = {"REGISTER", "UNDO"}
@@ -252,7 +210,7 @@ class LoadStructuralAnalysisModels(bpy.types.Operator, Operator):
core.load_structural_analysis_models(tool.Structural)
class DisableStructuralAnalysisModelEditingUI(bpy.types.Operator, Operator):
class DisableStructuralAnalysisModelEditingUI(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.disable_structural_analysis_model_editing_ui"
bl_label = "Disable Structural Analysis Model Editing UI"
bl_options = {"REGISTER", "UNDO"}
@@ -261,7 +219,7 @@ class DisableStructuralAnalysisModelEditingUI(bpy.types.Operator, Operator):
core.disable_structural_analysis_model_editing_ui(tool.Structural)
class AddStructuralAnalysisModel(bpy.types.Operator, Operator):
class AddStructuralAnalysisModel(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.add_structural_analysis_model"
bl_label = "Add Structural Analysis Model"
bl_options = {"REGISTER", "UNDO"}
@@ -272,7 +230,7 @@ class AddStructuralAnalysisModel(bpy.types.Operator, Operator):
core.enable_editing_structural_analysis_model(tool.Structural, model=model.id())
class EditStructuralAnalysisModel(bpy.types.Operator, Operator):
class EditStructuralAnalysisModel(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.edit_structural_analysis_model"
bl_label = "Edit Structural Analysis Model"
bl_options = {"REGISTER", "UNDO"}
@@ -281,7 +239,7 @@ class EditStructuralAnalysisModel(bpy.types.Operator, Operator):
core.edit_structural_analysis_model(tool.Ifc, tool.Structural)
class RemoveStructuralAnalysisModel(bpy.types.Operator, Operator):
class RemoveStructuralAnalysisModel(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.remove_structural_analysis_model"
bl_label = "Remove Structural Analysis Model"
bl_options = {"REGISTER", "UNDO"}
@@ -291,7 +249,7 @@ class RemoveStructuralAnalysisModel(bpy.types.Operator, Operator):
core.remove_structural_analysis_model(tool.Ifc, tool.Structural, model=self.structural_analysis_model)
class EnableEditingStructuralAnalysisModel(bpy.types.Operator, Operator):
class EnableEditingStructuralAnalysisModel(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.enable_editing_structural_analysis_model"
bl_label = "Enable Editing Structural Analysis Model"
bl_options = {"REGISTER", "UNDO"}
@@ -302,7 +260,7 @@ class EnableEditingStructuralAnalysisModel(bpy.types.Operator, Operator):
core.enable_editing_structural_analysis_model(tool.Structural, model=self.structural_analysis_model)
class DisableEditingStructuralAnalysisModel(bpy.types.Operator, Operator):
class DisableEditingStructuralAnalysisModel(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.disable_editing_structural_analysis_model"
bl_label = "Disable Editing Structural Analysis Model"
bl_options = {"REGISTER", "UNDO"}
@@ -311,7 +269,7 @@ class DisableEditingStructuralAnalysisModel(bpy.types.Operator, Operator):
core.disable_editing_structural_analysis_model(tool.Structural)
class AssignStructuralAnalysisModel(bpy.types.Operator, Operator):
class AssignStructuralAnalysisModel(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.assign_structural_analysis_model"
bl_label = "Assign Structural Analysis Model"
bl_options = {"REGISTER", "UNDO"}
@@ -324,7 +282,7 @@ class AssignStructuralAnalysisModel(bpy.types.Operator, Operator):
)
class UnassignStructuralAnalysisModel(bpy.types.Operator, Operator):
class UnassignStructuralAnalysisModel(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.unassign_structural_analysis_model"
bl_label = "Unassign Structural Analysis Model"
bl_options = {"REGISTER", "UNDO"}
@@ -391,13 +349,10 @@ class DisableEditingStructuralItemAxis(bpy.types.Operator):
return {"FINISHED"}
class EditStructuralItemAxis(bpy.types.Operator):
class EditStructuralItemAxis(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.edit_structural_item_axis"
bl_label = "Edit Structural Item Axis"
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
obj = context.active_object
oprops = obj.BIMObjectProperties
@@ -481,14 +436,11 @@ class DisableEditingStructuralConnectionCS(bpy.types.Operator):
return {"FINISHED"}
class EditStructuralConnectionCS(bpy.types.Operator):
class EditStructuralConnectionCS(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.edit_structural_connection_cs"
bl_label = "Edit Structural Connection CS"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
obj = context.active_object
oprops = obj.BIMObjectProperties
@@ -508,13 +460,13 @@ class EditStructuralConnectionCS(bpy.types.Operator):
return {"FINISHED"}
class AssignStructuralLoadCase(bpy.types.Operator):
class AssignStructuralLoadCase(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.assign_structural_load_case"
bl_label = "Assign Structural Load Case"
work_plan: bpy.props.IntProperty()
load_case: bpy.props.IntProperty()
def execute(self, context):
def _execute(self, context):
self.file = IfcStore.get_file()
ifcopenshell.api.run(
"aggregate.assign_object",
@@ -524,17 +476,16 @@ class AssignStructuralLoadCase(bpy.types.Operator):
"product": self.file.by_id(self.load_case),
},
)
Data.load(IfcStore.get_file())
return {"FINISHED"}
class UnassignStructuralLoadCase(bpy.types.Operator):
class UnassignStructuralLoadCase(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.unassign_structural_load_case"
bl_label = "Unassign Structural Load Case"
work_plan: bpy.props.IntProperty()
load_case: bpy.props.IntProperty()
def execute(self, context):
def _execute(self, context):
self.file = IfcStore.get_file()
ifcopenshell.api.run(
"aggregate.unassign_object",
@@ -544,32 +495,24 @@ class UnassignStructuralLoadCase(bpy.types.Operator):
"product": self.file.by_id(self.load_case),
},
)
Data.load(IfcStore.get_file())
return {"FINISHED"}
class AddStructuralLoadCase(bpy.types.Operator):
class AddStructuralLoadCase(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.add_structural_load_case"
bl_label = "Add Structural Load Case"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
ifcopenshell.api.run("structural.add_structural_load_case", IfcStore.get_file())
Data.load(IfcStore.get_file())
return {"FINISHED"}
class EditStructuralLoadCase(bpy.types.Operator):
class EditStructuralLoadCase(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.edit_structural_load_case"
bl_label = "Edit Structural Load Case"
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.load_case_attributes)
@@ -579,26 +522,21 @@ class EditStructuralLoadCase(bpy.types.Operator):
self.file,
**{"load_case": self.file.by_id(props.active_load_case_id), "attributes": attributes},
)
Data.load(IfcStore.get_file())
bpy.ops.bim.disable_editing_structural_load_case()
return {"FINISHED"}
class RemoveStructuralLoadCase(bpy.types.Operator):
class RemoveStructuralLoadCase(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.remove_structural_load_case"
bl_label = "Remove Structural Load Case"
bl_options = {"REGISTER", "UNDO"}
load_case: bpy.props.IntProperty()
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
self.file = IfcStore.get_file()
ifcopenshell.api.run(
"structural.remove_structural_load_case", self.file, load_case=self.file.by_id(self.load_case)
)
Data.load(self.file)
return {"FINISHED"}
@@ -613,9 +551,8 @@ class EnableEditingStructuralLoadCase(bpy.types.Operator):
self.props.active_load_case_id = self.load_case
self.props.load_case_editing_type = "ATTRIBUTES"
self.props.load_case_attributes.clear()
data = Data.load_cases[self.load_case]
blenderbim.bim.helper.import_attributes(
"IfcStructuralLoadCase", self.props.load_case_attributes, data, self.import_attributes
blenderbim.bim.helper.import_attributes2(
tool.Ifc.get().by_id(self.load_case), self.props.load_case_attributes, callback=self.import_attributes
)
return {"FINISHED"}
@@ -634,15 +571,12 @@ class DisableEditingStructuralLoadCase(bpy.types.Operator):
return {"FINISHED"}
class EnableEditingStructuralLoadCaseGroups(bpy.types.Operator):
class EnableEditingStructuralLoadCaseGroups(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.enable_editing_structural_load_case_groups"
bl_label = "Enable Editing Structural Load Case Groups"
bl_options = {"REGISTER", "UNDO"}
load_case: bpy.props.IntProperty()
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
self.props = context.scene.BIMStructuralProperties
self.props.active_load_case_id = self.load_case
@@ -650,37 +584,32 @@ class EnableEditingStructuralLoadCaseGroups(bpy.types.Operator):
return {"FINISHED"}
class AddStructuralLoadGroup(bpy.types.Operator):
class AddStructuralLoadGroup(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.add_structural_load_group"
bl_label = "Add Structural Load Group"
bl_options = {"REGISTER", "UNDO"}
load_case: bpy.props.IntProperty()
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
self.file = IfcStore.get_file()
load_group = ifcopenshell.api.run("structural.add_structural_load_group", self.file)
ifcopenshell.api.run(
"group.assign_group", self.file, products=[load_group], group=self.file.by_id(self.load_case)
)
Data.load(IfcStore.get_file())
return {"FINISHED"}
class RemoveStructuralLoadGroup(bpy.types.Operator):
class RemoveStructuralLoadGroup(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.remove_structural_load_group"
bl_label = "Remove Structural Load Group"
bl_options = {"REGISTER", "UNDO"}
load_group: bpy.props.IntProperty()
def execute(self, context):
def _execute(self, context):
self.file = IfcStore.get_file()
ifcopenshell.api.run(
"structural.remove_structural_load_group", self.file, load_group=self.file.by_id(self.load_group)
)
Data.load(self.file)
return {"FINISHED"}
@@ -696,28 +625,24 @@ class EnableEditingStructuralLoadGroupActivities(bpy.types.Operator):
self.props.active_load_group_id = self.load_group
self.props.load_group_editing_type = "ACTIVITY"
self.load_structural_activities()
purge()
return {"FINISHED"}
def load_structural_activities(self):
self.props.load_group_activities.clear()
for activity_id in Data.load_groups[self.load_group]["IsGroupedBy"]:
activity = Data.structural_activities[activity_id]
new = self.props.load_group_activities.add()
new.ifc_definition_id = activity_id
new.name = self.file.by_id(activity["AssignedToStructuralItem"]).Name or "Unnamed"
new.applied_load_class = self.file.by_id(activity["AppliedLoad"]).is_a()
for rel in tool.Ifc.get().by_id(self.load_group).IsGroupedBy:
for activity in rel.RelatedObjects:
new = self.props.load_group_activities.add()
new.ifc_definition_id = activity.id()
new.name = activity.AssignedToStructuralItem.Name or "Unnamed"
new.applied_load_class = activity.AppliedLoad.is_a()
class AddStructuralActivity(bpy.types.Operator):
class AddStructuralActivity(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.add_structural_activity"
bl_label = "Add Structural Activity"
bl_options = {"REGISTER", "UNDO"}
load_group: bpy.props.IntProperty()
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
self.props = context.scene.BIMStructuralProperties
self.file = IfcStore.get_file()
@@ -758,39 +683,39 @@ class AddStructuralActivity(bpy.types.Operator):
ifcopenshell.api.run(
"group.assign_group", self.file, products=[activity], group=self.file.by_id(self.load_group)
)
Data.load(IfcStore.get_file())
bpy.ops.bim.enable_editing_structural_load_group_activities(load_group=self.load_group)
return {"FINISHED"}
class LoadStructuralLoads(bpy.types.Operator):
class LoadStructuralLoads(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.load_structural_loads"
bl_label = "Load Structural Loads"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
def _execute(self, context):
self.file = IfcStore.get_file()
props = context.scene.BIMStructuralProperties
props.structural_loads.clear()
loads = tool.Ifc.get().by_type("IfcStructuralLoad")
if props.filtered_structural_loads:
names = [structural_load["Name"] or "Unnamed" for _, structural_load in Data.structural_loads.items()]
for ifc_definition_id, structural_load in Data.structural_loads.items():
names = [structural_load.Name or "Unnamed" for structural_load in loads]
for structural_load in loads:
if (
names.count(structural_load["Name"] or "Unnamed") > 1
and len(self.file.get_inverse(self.file.by_id(ifc_definition_id))) < 2
names.count(structural_load.Name or "Unnamed") > 1
and len(self.file.get_inverse(structural_load)) < 2
):
continue
new = props.structural_loads.add()
new.ifc_definition_id = ifc_definition_id
new.name = structural_load["Name"] or "Unnamed"
new.number_of_inverse_references = len(self.file.get_inverse(self.file.by_id(ifc_definition_id)))
new.ifc_definition_id = structural_load.id()
new.name = structural_load.Name or "Unnamed"
new.number_of_inverse_references = self.file.get_total_inverses(structural_load)
else:
for ifc_definition_id, structural_load in Data.structural_loads.items():
for structural_load in loads:
new = props.structural_loads.add()
new.ifc_definition_id = ifc_definition_id
new.name = structural_load["Name"] or "Unnamed"
new.number_of_inverse_references = len(self.file.get_inverse(self.file.by_id(ifc_definition_id)))
new.ifc_definition_id = structural_load.id()
new.name = structural_load.Name or "Unnamed"
new.number_of_inverse_references = self.file.get_total_inverses(structural_load)
props.is_editing_loads = True
bpy.ops.bim.disable_editing_structural_load()
return {"FINISHED"}
@@ -806,20 +731,16 @@ class DisableStructuralLoadEditingUI(bpy.types.Operator):
return {"FINISHED"}
class AddStructuralLoad(bpy.types.Operator):
class AddStructuralLoad(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.add_structural_load"
bl_label = "Add Structural Load"
bl_options = {"REGISTER", "UNDO"}
ifc_class: bpy.props.StringProperty()
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
result = ifcopenshell.api.run(
"structural.add_structural_load", IfcStore.get_file(), name="New Load", ifc_class=self.ifc_class
)
Data.load(IfcStore.get_file())
bpy.ops.bim.load_structural_loads()
bpy.ops.bim.enable_editing_structural_load(structural_load=result.id())
return {"FINISHED"}
@@ -834,9 +755,9 @@ class EnableEditingStructuralLoad(bpy.types.Operator):
def execute(self, context):
props = context.scene.BIMStructuralProperties
props.structural_load_attributes.clear()
data = Data.structural_loads[self.structural_load]
blenderbim.bim.helper.import_attributes(data["type"], props.structural_load_attributes, data)
blenderbim.bim.helper.import_attributes2(
tool.Ifc.get().by_id(self.structural_load), props.structural_load_attributes
)
props.active_structural_load_id = self.structural_load
return {"FINISHED"}
@@ -851,15 +772,12 @@ class DisableEditingStructuralLoad(bpy.types.Operator):
return {"FINISHED"}
class RemoveStructuralLoad(bpy.types.Operator):
class RemoveStructuralLoad(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.remove_structural_load"
bl_label = "Remove Structural Load"
bl_options = {"REGISTER", "UNDO"}
structural_load: 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()
@@ -868,19 +786,15 @@ class RemoveStructuralLoad(bpy.types.Operator):
self.file,
**{"structural_load": self.file.by_id(self.structural_load)},
)
Data.load(IfcStore.get_file())
bpy.ops.bim.load_structural_loads()
return {"FINISHED"}
class EditStructuralLoad(bpy.types.Operator):
class EditStructuralLoad(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.edit_structural_load"
bl_label = "Edit Structural Load"
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_load_attributes)
@@ -893,7 +807,6 @@ class EditStructuralLoad(bpy.types.Operator):
"attributes": attributes,
},
)
Data.load(IfcStore.get_file())
bpy.ops.bim.load_structural_loads()
return {"FINISHED"}
@@ -919,27 +832,26 @@ class LoadBoundaryConditions(bpy.types.Operator):
self.file = IfcStore.get_file()
props = context.scene.BIMStructuralProperties
props.boundary_conditions.clear()
conditions = tool.Ifc.get().by_type("IfcBoundaryCondition")
if props.filtered_boundary_conditions:
names = [
boundary_condition["Name"] or "Unnamed" for _, boundary_condition in Data.boundary_conditions.items()
]
for ifc_definition_id, boundary_condition in Data.boundary_conditions.items():
names = [boundary_condition.Name or "Unnamed" for boundary_condition in conditions]
for boundary_condition in conditions:
if (
names.count(boundary_condition["Name"] or "Unnamed") > 1
and len(self.file.get_inverse(self.file.by_id(ifc_definition_id))) < 2
and self.file.get_total_inverses(boundary_condition) < 2
):
continue
new = props.boundary_conditions.add()
new.ifc_definition_id = ifc_definition_id
new.name = boundary_condition["Name"] or "Unnamed"
new.number_of_inverse_references = len(self.file.get_inverse(self.file.by_id(ifc_definition_id)))
new.ifc_definition_id = boundary_condition.id()
new.name = boundary_condition.Name or "Unnamed"
new.number_of_inverse_references = self.file.get_total_inverses(boundary_condition)
else:
for ifc_definition_id, boundary_condition in Data.boundary_conditions.items():
for boundary_condition in conditions:
new = props.boundary_conditions.add()
new.ifc_definition_id = ifc_definition_id
new.name = boundary_condition["Name"] or "Unnamed"
new.number_of_inverse_references = len(self.file.get_inverse(self.file.by_id(ifc_definition_id)))
new.ifc_definition_id = boundary_condition.id()
new.name = boundary_condition.Name or "Unnamed"
new.number_of_inverse_references = self.file.get_total_inverses(boundary_condition)
props.is_editing_boundary_conditions = True
bpy.ops.bim.disable_editing_boundary_condition()
return {"FINISHED"}
@@ -967,15 +879,12 @@ class DisableBoundaryConditionEditingUI(bpy.types.Operator):
return {"FINISHED"}
class AddBoundaryCondition(bpy.types.Operator):
class AddBoundaryCondition(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.add_boundary_condition"
bl_label = "Add Boundary Condition"
bl_options = {"REGISTER", "UNDO"}
ifc_class: bpy.props.StringProperty()
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
result = ifcopenshell.api.run(
"structural.add_structural_boundary_condition",
@@ -983,7 +892,6 @@ class AddBoundaryCondition(bpy.types.Operator):
name="New Load",
ifc_class=self.ifc_class,
)
Data.load(IfcStore.get_file())
bpy.ops.bim.load_boundary_conditions()
bpy.ops.bim.enable_editing_boundary_condition(boundary_condition=result.id())
return {"FINISHED"}
@@ -999,28 +907,28 @@ class EnableEditingBoundaryCondition(bpy.types.Operator):
props = context.scene.BIMStructuralProperties
props.boundary_condition_attributes.clear()
data = Data.boundary_conditions[self.boundary_condition]
boundary_condition = tool.Ifc.get().by_id(self.boundary_condition)
# blenderbim.bim.helper.import_attributes(data["type"], props.boundary_condition_attributes, data)
for attribute in IfcStore.get_schema().declaration_by_name(data["type"]).all_attributes():
value = data[attribute.name()]
for attribute in IfcStore.get_schema().declaration_by_name(boundary_condition.is_a()).all_attributes():
value = getattr(boundary_condition, attribute.name(), None)
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
new = props.boundary_condition_attributes.add()
new.name = attribute.name()
new.is_null = value is None
new.is_optional = attribute.optional()
if data_type == "select":
if isinstance(data_type, tuple) and data_type[0] == "select":
enum_items = [s.name() for s in ifcopenshell.util.attribute.get_select_items(attribute)]
new.enum_items = json.dumps(enum_items)
if isinstance(value, bool):
new.bool_value = False if new.is_null else data[attribute.name()]
new.bool_value = False if new.is_null else value
new.data_type = "bool"
new.enum_value = "IfcBoolean"
elif isinstance(value, float):
new.float_value = 0.0 if new.is_null else data[attribute.name()]
new.float_value = 0.0 if new.is_null else value
new.data_type = "float"
new.enum_value = [i for i in enum_items if i != "IfcBoolean"][0]
elif data_type == "string":
new.string_value = "" if new.is_null else data[attribute.name()]
new.string_value = "" if new.is_null else value
new.data_type = "string"
props.active_boundary_condition_id = self.boundary_condition
return {"FINISHED"}
@@ -1036,15 +944,12 @@ class DisableEditingBoundaryCondition(bpy.types.Operator):
return {"FINISHED"}
class RemoveBoundaryCondition(bpy.types.Operator):
class RemoveBoundaryCondition(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.remove_boundary_condition"
bl_label = "Remove Boundary Condition"
bl_options = {"REGISTER", "UNDO"}
boundary_condition: 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()
@@ -1053,19 +958,15 @@ class RemoveBoundaryCondition(bpy.types.Operator):
self.file,
**{"boundary_condition": self.file.by_id(self.boundary_condition)},
)
Data.load(IfcStore.get_file())
bpy.ops.bim.load_boundary_conditions()
return {"FINISHED"}
class EditBoundaryCondition(bpy.types.Operator):
class EditBoundaryCondition(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.edit_boundary_condition"
bl_label = "Edit Boundary Condition"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
return IfcStore.execute_ifc_operator(self, context)
def _execute(self, context):
props = context.scene.BIMStructuralProperties
self.file = IfcStore.get_file()
@@ -1085,6 +986,5 @@ class EditBoundaryCondition(bpy.types.Operator):
self.file,
**{"condition": self.file.by_id(props.active_boundary_condition_id), "attributes": attributes},
)
Data.load(IfcStore.get_file())
bpy.ops.bim.load_boundary_conditions()
return {"FINISHED"}
@@ -18,11 +18,10 @@
from math import radians
import bpy
from ifcopenshell.api.structural.data import Data
from ifcopenshell.util.doc import get_entity_doc
import blenderbim.tool as tool
from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.prop import StrProperty, Attribute
from blenderbim.bim.module.structural.data import StructuralLoadCasesData, StructuralLoadsData, BoundaryConditionsData
from bpy.types import PropertyGroup
from bpy.props import (
PointerProperty,
@@ -35,83 +34,35 @@ from bpy.props import (
CollectionProperty,
)
structuralloadtypes_enum = []
applicablestructuralloads_enum = []
def purge():
global structuralloadtypes_enum
global applicablestructuralloads_enum
structuralloadtypes_enum = []
applicablestructuralloads_enum = []
def getApplicableStructuralLoadTypes(self, context):
ifc_file = IfcStore.get_file()
element_classes = set(
[
ifc_file.by_id(o.BIMObjectProperties.ifc_definition_id).is_a()
for o in context.selected_objects
if o.BIMObjectProperties.ifc_definition_id
]
)
types = [("IfcStructuralLoadTemperature", "IfcStructuralLoadTemperature", "")]
if "IfcStructuralPointConnection" in element_classes:
types.extend(
[
("IfcStructuralLoadSingleForce", "IfcStructuralLoadSingleForce", ""),
("IfcStructuralLoadSingleDisplacement", "IfcStructuralLoadSingleDisplacement", ""),
]
)
if "IfcStructuralCurveMember" in element_classes:
types.append(("IfcStructuralLoadLinearForce", "IfcStructuralLoadLinearForce", ""))
if "IfcStructuralSurfaceMember" in element_classes:
types.append(("IfcStructuralLoadPlanarForce", "IfcStructuralLoadPlanarForce", ""))
return types
def get_applicable_structural_load_types(self, context):
if not StructuralLoadCasesData.is_loaded:
StructuralLoadCasesData.load()
return StructuralLoadCasesData.data["applicable_structural_load_types"]
def updateApplicableStructuralLoadTypes(self, context):
global applicablestructuralloads_enum
applicablestructuralloads_enum.clear()
StructuralLoadCasesData.data[
"applicable_structural_load_types"
] = StructuralLoadCasesData.applicable_structural_load_types()
def getApplicableStructuralLoads(self, context):
global applicablestructuralloads_enum
file = IfcStore.get_file()
if len(applicablestructuralloads_enum) < 1 and file:
for ifc_definition_id, load in Data.structural_loads.items():
if not load["Name"] or load["type"] != self.applicable_structural_load_types:
continue
applicablestructuralloads_enum.append((str(ifc_definition_id), load["Name"], ""))
return applicablestructuralloads_enum
def get_applicable_structural_loads(self, context):
if not StructuralLoadCasesData.is_loaded:
StructuralLoadCasesData.load()
return StructuralLoadCasesData.data["applicable_structural_loads"]
def get_structural_load_types(self, context):
global structuralloadtypes_enum
file = IfcStore.get_file()
if len(structuralloadtypes_enum) < 1 and file:
declaration = IfcStore.get_schema().declaration_by_name("IfcStructuralLoadStatic")
version = tool.Ifc.get_schema()
structuralloadtypes_enum.extend(
[
(d.name(), d.name(), get_entity_doc(version, d.name()).get("description", ""))
for d in declaration.subtypes()
]
)
return structuralloadtypes_enum
if not StructuralLoadsData.is_loaded:
StructuralLoadsData.load()
return StructuralLoadsData.data["structural_load_types"]
def get_boundary_condition_types(self, context):
file = IfcStore.get_file()
if file:
declaration = IfcStore.get_schema().declaration_by_name("IfcBoundaryCondition")
version = tool.Ifc.get_schema()
boundaryconditiontypes_enum = [
(d.name(), d.name(), get_entity_doc(version, d.name()).get("description", ""))
for d in declaration.subtypes()
]
return boundaryconditiontypes_enum
return []
if not BoundaryConditionsData.is_loaded:
BoundaryConditionsData.load()
return BoundaryConditionsData.data["boundary_condition_types"]
def updateAxisAngle(self, context):
@@ -177,11 +128,11 @@ class BIMStructuralProperties(PropertyGroup):
# load_group_attributes: CollectionProperty(name="Load Group Attributes", type=Attribute)
active_load_group_id: IntProperty(name="Active Load Group Id")
applicable_structural_load_types: EnumProperty(
items=getApplicableStructuralLoadTypes,
items=get_applicable_structural_load_types,
name="Applicable Structural Load Types",
update=updateApplicableStructuralLoadTypes,
)
applicable_structural_loads: EnumProperty(items=getApplicableStructuralLoads, name="Applicable Structural Loads")
applicable_structural_loads: EnumProperty(items=get_applicable_structural_loads, name="Applicable Structural Loads")
load_group_activities: CollectionProperty(name="Load Group Activities", type=StructuralActivity)
active_load_group_activity_index: IntProperty(name="Active Load Group Activity Index")
@@ -21,39 +21,42 @@ import blenderbim.bim.helper
from bpy.types import Panel, UIList
from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.helper import draw_attributes, prop_with_search
from ifcopenshell.api.structural.data import Data
from blenderbim.bim.module.structural.data import StructuralData
from blenderbim.bim.module.structural.data import (
StructuralBoundaryConditionsData,
ConnectedStructuralMembersData,
StructuralMemberData,
StructuralAnalysisModelsData,
StructuralLoadCasesData,
StructuralLoadsData,
StructuralConnectionData,
BoundaryConditionsData,
)
def draw_boundary_condition_ui(layout, boundary_condition_id, connection_id, props):
data = (
Data.boundary_conditions[boundary_condition_id]
if boundary_condition_id and boundary_condition_id in Data.boundary_conditions.keys()
else {}
)
def draw_boundary_condition_ui(layout, boundary_condition, connection_id, props):
row = layout.row(align=True)
if not data:
if not boundary_condition:
row.label(text="No Boundary Condition Found", icon="CON_TRACKTO")
row.operator("bim.add_structural_boundary_condition", text="", icon="ADD").connection = connection_id
return
if props.active_boundary_condition and props.active_boundary_condition == boundary_condition_id:
row.label(text=data["type"], icon="CON_TRACKTO")
if props.active_boundary_condition and props.active_boundary_condition == boundary_condition["id"]:
row.label(text=boundary_condition["type"], icon="CON_TRACKTO")
row.operator("bim.edit_structural_boundary_condition", text="", icon="CHECKMARK").connection = connection_id
row.operator("bim.disable_editing_structural_boundary_condition", text="", icon="CANCEL")
elif props.active_boundary_condition and props.active_boundary_condition != boundary_condition_id:
row.label(text=data["type"], icon="CON_TRACKTO")
elif props.active_boundary_condition and props.active_boundary_condition != boundary_condition["id"]:
row.label(text=boundary_condition["type"], icon="CON_TRACKTO")
row.operator("bim.remove_structural_boundary_condition", text="", icon="X").connection = connection_id
else:
row.label(text=data["type"], icon="CON_TRACKTO")
row.label(text=boundary_condition["type"], icon="CON_TRACKTO")
op = row.operator("bim.enable_editing_structural_boundary_condition", text="", icon="GREASEPENCIL")
op.boundary_condition = data["id"]
op.boundary_condition = boundary_condition["id"]
row.operator("bim.remove_structural_boundary_condition", text="", icon="X").connection = connection_id
if props.active_boundary_condition and props.active_boundary_condition == boundary_condition_id:
if props.active_boundary_condition and props.active_boundary_condition == boundary_condition["id"]:
draw_boundary_condition_editable_ui(layout, props)
else:
draw_boundary_condition_read_only_ui(layout, data)
draw_boundary_condition_read_only_ui(layout, boundary_condition)
def draw_boundary_condition_editable_ui(layout, props):
@@ -72,16 +75,14 @@ def draw_boundary_condition_editable_ui(layout, props):
row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="")
def draw_boundary_condition_read_only_ui(layout, boundary_condition_data):
for key, value in boundary_condition_data.items():
if key == "id" or key == "type" or value == None:
continue
def draw_boundary_condition_read_only_ui(layout, boundary_condition):
for attribute in boundary_condition["attributes"]:
row = layout.row(align=True)
row.label(text=key)
if isinstance(value, bool):
row.label(text="", icon="CHECKBOX_HLT" if value else "CHECKBOX_DEHLT")
row.label(text=attribute["name"])
if attribute["is_bool"]:
row.label(text="", icon="CHECKBOX_HLT" if attribute["value"] else "CHECKBOX_DEHLT")
else:
row.label(text=str(value))
row.label(text=str(attribute["value"]))
class BIM_PT_structural_boundary_conditions(Panel):
@@ -91,7 +92,6 @@ class BIM_PT_structural_boundary_conditions(Panel):
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "object"
# bl_parent_id = "BIM_PT_structural_connection"
bl_parent_id = "BIM_PT_misc_object"
@classmethod
@@ -108,13 +108,15 @@ class BIM_PT_structural_boundary_conditions(Panel):
return True
def draw(self, context):
self.oprops = context.active_object.BIMObjectProperties
self.props = context.active_object.BIMStructuralProperties
if self.oprops.ifc_definition_id not in Data.connections:
Data.load(IfcStore.get_file(), self.oprops.ifc_definition_id)
if not StructuralBoundaryConditionsData.is_loaded:
StructuralBoundaryConditionsData.load()
applied_condition_id = Data.connections[self.oprops.ifc_definition_id]["AppliedCondition"]
draw_boundary_condition_ui(self.layout, applied_condition_id, self.oprops.ifc_definition_id, self.props)
draw_boundary_condition_ui(
self.layout,
StructuralBoundaryConditionsData.data["boundary_condition"],
StructuralBoundaryConditionsData.data["connection_id"],
context.active_object.BIMStructuralProperties,
)
class BIM_PT_connected_structural_members(Panel):
@@ -124,7 +126,6 @@ class BIM_PT_connected_structural_members(Panel):
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "object"
# bl_parent_id = "BIM_PT_structural_connection"
bl_parent_id = "BIM_PT_misc_object"
@classmethod
@@ -141,38 +142,33 @@ class BIM_PT_connected_structural_members(Panel):
return True
def draw(self, context):
self.oprops = context.active_object.BIMObjectProperties
self.props = context.active_object.BIMStructuralProperties
if self.oprops.ifc_definition_id not in Data.connections:
Data.load(IfcStore.get_file(), self.oprops.ifc_definition_id)
if not ConnectedStructuralMembersData.is_loaded:
ConnectedStructuralMembersData.load()
rel_ids = Data.connections[self.oprops.ifc_definition_id]["ConnectsStructuralMembers"]
self.props = context.active_object.BIMStructuralProperties
row = self.layout.row(align=True)
row.prop(self.props, "relating_structural_member", text="", icon="CON_TRACKTO")
row.operator("bim.add_structural_member_connection", text="", icon="ADD")
for rel_id in rel_ids:
rel = Data.connects_structural_members[rel_id]
for connection in ConnectedStructuralMembersData.data["connections"]:
row = self.layout.row(align=True)
row.label(text=f"To Member #{IfcStore.get_file().by_id(rel['RelatingStructuralMember']).Name}")
if self.props.active_connects_structural_member and self.props.active_connects_structural_member == rel_id:
row.label(text=f"To Member #{connection['member_name']}")
if (
self.props.active_connects_structural_member
and self.props.active_connects_structural_member == connection["id"]
):
row.operator("bim.disable_editing_structural_connection_condition", text="", icon="CANCEL")
row.enabled = self.props.active_boundary_condition != rel["AppliedCondition"]
self.draw_editable_ui(context, self.layout, rel)
row.enabled = connection["is_active_condition"]
draw_boundary_condition_ui(self.layout.box(), connection["condition"], connection["id"], self.props)
elif self.props.active_connects_structural_member:
op = row.operator("bim.remove_structural_connection_condition", text="", icon="X")
op.connects_structural_member = rel_id
op.connects_structural_member = connection["id"]
else:
op = row.operator("bim.enable_editing_structural_connection_condition", text="", icon="GREASEPENCIL")
op.connects_structural_member = rel_id
op.connects_structural_member = connection["id"]
op = row.operator("bim.remove_structural_connection_condition", text="", icon="X")
op.connects_structural_member = rel_id
def draw_editable_ui(self, context, layout, data):
box = layout.box()
row = box.row(align=True)
draw_boundary_condition_ui(box, data["AppliedCondition"], data["id"], self.props)
op.connects_structural_member = connection["id"]
class BIM_PT_structural_member(Panel):
@@ -198,11 +194,12 @@ class BIM_PT_structural_member(Panel):
return True
def draw(self, context):
self.oprops = context.active_object.BIMObjectProperties
self.props = context.active_object.BIMStructuralProperties
self.file = IfcStore.get_file()
if not StructuralMemberData.is_loaded:
StructuralMemberData.load()
if self.file.by_id(self.oprops.ifc_definition_id).is_a("IfcStructuralCurveMember"):
self.props = context.active_object.BIMStructuralProperties
if StructuralMemberData.data["active_object_class"] == "IfcStructuralCurveMember":
if self.props.is_editing_axis:
row = self.layout.row(align=True)
row.prop(self.props, "axis_angle")
@@ -239,11 +236,12 @@ class BIM_PT_structural_connection(Panel):
return True
def draw(self, context):
self.oprops = context.active_object.BIMObjectProperties
self.props = context.active_object.BIMStructuralProperties
self.file = IfcStore.get_file()
if not StructuralConnectionData.is_loaded:
StructuralConnectionData.load()
if self.file.by_id(self.oprops.ifc_definition_id).is_a("IfcStructuralCurveConnection"):
self.props = context.active_object.BIMStructuralProperties
if StructuralConnectionData.data["active_object_class"] == "IfcStructuralCurveConnection":
if self.props.is_editing_axis:
row = self.layout.row(align=True)
row.prop(self.props, "axis_angle")
@@ -252,8 +250,7 @@ class BIM_PT_structural_connection(Panel):
else:
row = self.layout.row()
row.operator("bim.enable_editing_structural_item_axis", text="Edit Axis", icon="GREASEPENCIL")
elif self.file.by_id(self.oprops.ifc_definition_id).is_a("IfcStructuralPointConnection"):
elif StructuralConnectionData.data["active_object_class"] == "IfcStructuralPointConnection":
if self.props.is_editing_connection_cs:
row = self.layout.row(align=True)
row.label(text="Editing Connection CS")
@@ -290,13 +287,14 @@ class BIM_PT_structural_analysis_models(Panel):
return file and hasattr(file, "schema") and file.schema != "IFC2X3"
def draw(self, context):
if not StructuralData.is_loaded:
StructuralData.load()
if not StructuralAnalysisModelsData.is_loaded:
StructuralAnalysisModelsData.load()
self.props = context.scene.BIMStructuralProperties
row = self.layout.row(align=True)
row.label(
text="{} Structural Analysis Models Found".format(StructuralData.number_of_structural_analysis_models),
text=f"{StructuralAnalysisModelsData.data['total_models']} Structural Analysis Models Found",
icon="MOD_SIMPLIFY",
)
if self.props.is_editing:
@@ -316,10 +314,7 @@ class BIM_PT_structural_analysis_models(Panel):
)
if self.props.active_structural_analysis_model_id:
self.draw_editable_ui(context)
def draw_editable_ui(self, context):
draw_attributes(self.props.structural_analysis_model_attributes, self.layout)
draw_attributes(self.props.structural_analysis_model_attributes, self.layout)
class BIM_UL_structural_analysis_models(UIList):
@@ -330,10 +325,7 @@ class BIM_UL_structural_analysis_models(UIList):
if context.active_object:
oprops = context.active_object.BIMObjectProperties
if (
oprops.ifc_definition_id in StructuralData.products
and item.ifc_definition_id in StructuralData.products[oprops.ifc_definition_id]
):
if item.ifc_definition_id in StructuralAnalysisModelsData.data["active_model_ids"]:
op = row.operator(
"bim.unassign_structural_analysis_model", text="", icon="KEYFRAME_HLT", emboss=False
)
@@ -370,39 +362,39 @@ class BIM_PT_structural_load_cases(Panel):
return file and hasattr(file, "schema") and file.schema != "IFC2X3"
def draw(self, context):
self.props = context.scene.BIMStructuralProperties
if not StructuralLoadCasesData.is_loaded:
StructuralLoadCasesData.load()
if not Data.is_loaded:
Data.load(IfcStore.get_file())
self.props = context.scene.BIMStructuralProperties
row = self.layout.row()
row.operator("bim.add_structural_load_case", icon="ADD")
for load_case_id, load_case in Data.load_cases.items():
self.draw_load_case_ui(load_case_id, load_case)
for load_case in StructuralLoadCasesData.data["load_cases"]:
self.draw_load_case_ui(load_case)
def draw_load_case_ui(self, load_case_id, load_case):
def draw_load_case_ui(self, load_case):
row = self.layout.row(align=True)
row.label(text=load_case["Name"] or "Unnamed", icon="CON_CLAMPTO")
row.label(text=load_case["name"], icon="CON_CLAMPTO")
if self.props.active_load_case_id and self.props.active_load_case_id == load_case_id:
if self.props.active_load_case_id and self.props.active_load_case_id == load_case["id"]:
if self.props.load_case_editing_type == "ATTRIBUTES":
row.operator("bim.edit_structural_load_case", text="", icon="CHECKMARK")
elif self.props.load_case_editing_type == "GROUPS":
row.operator("bim.add_structural_load_group", text="", icon="ADD").load_case = load_case_id
row.operator("bim.add_structural_load_group", text="", icon="ADD").load_case = load_case["id"]
row.operator("bim.disable_editing_structural_load_case", text="", icon="CANCEL")
elif self.props.active_load_case_id:
row.operator("bim.remove_structural_load_case", text="", icon="X").load_case = load_case_id
row.operator("bim.remove_structural_load_case", text="", icon="X").load_case = load_case["id"]
else:
row.operator(
"bim.enable_editing_structural_load_case_groups", text="", icon="GHOST_ENABLED"
).load_case = load_case_id
row.operator(
"bim.enable_editing_structural_load_case", text="", icon="GREASEPENCIL"
).load_case = load_case_id
row.operator("bim.remove_structural_load_case", text="", icon="X").load_case = load_case_id
).load_case = load_case["id"]
row.operator("bim.enable_editing_structural_load_case", text="", icon="GREASEPENCIL").load_case = load_case[
"id"
]
row.operator("bim.remove_structural_load_case", text="", icon="X").load_case = load_case["id"]
if self.props.active_load_case_id == load_case_id:
if self.props.active_load_case_id == load_case["id"]:
if self.props.load_case_editing_type == "ATTRIBUTES":
self.draw_editable_load_case_ui()
elif self.props.load_case_editing_type == "GROUPS":
@@ -413,18 +405,17 @@ class BIM_PT_structural_load_cases(Panel):
def draw_editable_load_case_group_ui(self, load_case):
box = self.layout.box()
if not len(load_case["IsGroupedBy"]):
if not load_case["load_groups"]:
row = box.row(align=True)
row.label(text="No Load Groups Found")
for load_group_id in load_case["IsGroupedBy"]:
load_group = Data.load_groups[load_group_id]
for load_group in load_case["load_groups"]:
row = box.row(align=True)
row.label(text=load_group["Name"] or "Unnamed", icon="GHOST_ENABLED")
row.label(text=load_group["name"], icon="GHOST_ENABLED")
op = row.operator("bim.enable_editing_structural_load_group_activities", text="", icon="GHOST_ENABLED")
op.load_group = load_group_id
row.operator("bim.remove_structural_load_group", text="", icon="X").load_group = load_group_id
op.load_group = load_group["id"]
row.operator("bim.remove_structural_load_group", text="", icon="X").load_group = load_group["id"]
if self.props.active_load_group_id == load_group_id:
if self.props.active_load_group_id == load_group["id"]:
if self.props.load_group_editing_type == "ACTIVITY":
self.draw_editable_load_group_activities_ui(box, load_group)
@@ -467,12 +458,13 @@ class BIM_PT_structural_loads(Panel):
return file and hasattr(file, "schema") and file.schema != "IFC2X3"
def draw(self, context):
if not Data.is_loaded:
Data.load(IfcStore.get_file())
if not StructuralLoadsData.is_loaded:
StructuralLoadsData.load()
self.props = context.scene.BIMStructuralProperties
row = self.layout.row(align=True)
row.label(text="{} Structural Loads Found".format(len(Data.structural_loads)), icon="ANIM_DATA")
row.label(text=f"{StructuralLoadsData.data['total_loads']} Structural Loads Found", icon="ANIM_DATA")
if self.props.is_editing_loads:
row.operator(
"bim.toggle_filter_structural_loads",
@@ -506,7 +498,7 @@ class BIM_UL_structural_loads(UIList):
if item:
row = layout.row(align=True)
row.label(text=f"{item.name} ({item.number_of_inverse_references})")
row.label(text=Data.structural_loads[item.ifc_definition_id]["type"])
row.label(text=StructuralLoadsData.data["load_classes"][item.ifc_definition_id])
if context.scene.BIMStructuralProperties.active_structural_load_id == item.ifc_definition_id:
row.operator("bim.edit_structural_load", text="", icon="CHECKMARK")
@@ -536,12 +528,15 @@ class BIM_PT_boundary_conditions(Panel):
return file and hasattr(file, "schema") and file.schema != "IFC2X3"
def draw(self, context):
if not Data.is_loaded:
Data.load(IfcStore.get_file())
if not BoundaryConditionsData.is_loaded:
BoundaryConditionsData.load()
self.props = context.scene.BIMStructuralProperties
row = self.layout.row(align=True)
row.label(text="{} Boundary Conditions Found".format(len(Data.boundary_conditions)), icon="CON_TRACKTO")
row.label(
text=f"{BoundaryConditionsData.data['total_conditions']} Boundary Conditions Found", icon="CON_TRACKTO"
)
if self.props.is_editing_boundary_conditions:
row.operator(
"bim.toggle_filter_boundary_conditions",
@@ -578,7 +573,7 @@ class BIM_UL_boundary_conditions(UIList):
if item:
row = layout.row(align=True)
row.label(text=f"{item.name} ({item.number_of_inverse_references})")
row.label(text=Data.boundary_conditions[item.ifc_definition_id]["type"])
row.label(text=BoundaryConditionsData.data["condition_classes"][item.ifc_definition_id])
if context.scene.BIMStructuralProperties.active_boundary_condition_id == item.ifc_definition_id:
row.operator("bim.edit_boundary_condition", text="", icon="CHECKMARK")