diff --git a/src/blenderbim/blenderbim/bim/import_ifc.py b/src/blenderbim/blenderbim/bim/import_ifc.py index 9d1b5a5ae9..6ec10e5145 100644 --- a/src/blenderbim/blenderbim/bim/import_ifc.py +++ b/src/blenderbim/blenderbim/bim/import_ifc.py @@ -718,7 +718,7 @@ class IfcImporter: # Create structural collections self.structural_member_collection = bpy.data.collections.new("Members") self.structural_connection_collection = bpy.data.collections.new("Connections") - self.structural_collection = bpy.data.collections.new("StructuralEntities") + self.structural_collection = bpy.data.collections.new("StructuralItems") self.structural_collection.children.link(self.structural_member_collection) self.structural_collection.children.link(self.structural_connection_collection) self.project["blender"].children.link(self.structural_collection) diff --git a/src/blenderbim/blenderbim/bim/module/structural/__init__.py b/src/blenderbim/blenderbim/bim/module/structural/__init__.py index 23c81445d0..7a0a231153 100644 --- a/src/blenderbim/blenderbim/bim/module/structural/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/structural/__init__.py @@ -20,9 +20,12 @@ classes = ( operator.EnableEditingStructuralConnectionCondition, operator.DisableEditingStructuralConnectionCondition, operator.RemoveStructuralConnectionCondition, - operator.EnableEditingStructuralMemberAxis, - operator.DisableEditingStructuralMemberAxis, - operator.EditStructuralMemberAxis, + operator.EnableEditingStructuralItemAxis, + operator.DisableEditingStructuralItemAxis, + operator.EditStructuralItemAxis, + operator.EnableEditingStructuralItemConnectionCS, + operator.DisableEditingStructuralItemConnectionCS, + operator.EditStructuralItemConnectionCS, operator.AddStructuralLoadCase, operator.EditStructuralLoadCase, operator.RemoveStructuralLoadCase, @@ -35,6 +38,7 @@ classes = ( ui.BIM_PT_structural_boundary_conditions, ui.BIM_PT_connected_structural_members, ui.BIM_PT_structural_member, + ui.BIM_PT_structural_connection, ui.BIM_UL_structural_analysis_models, ui.BIM_PT_structural_load_cases, ) diff --git a/src/blenderbim/blenderbim/bim/module/structural/operator.py b/src/blenderbim/blenderbim/bim/module/structural/operator.py index 4fdb84203b..abbc95e116 100644 --- a/src/blenderbim/blenderbim/bim/module/structural/operator.py +++ b/src/blenderbim/blenderbim/bim/module/structural/operator.py @@ -367,9 +367,9 @@ class UnassignStructuralAnalysisModel(bpy.types.Operator): return {"FINISHED"} -class EnableEditingStructuralMemberAxis(bpy.types.Operator): - bl_idname = "bim.enable_editing_structural_member_axis" - bl_label = "Enable Editing Structural Member Axis" +class EnableEditingStructuralItemAxis(bpy.types.Operator): + bl_idname = "bim.enable_editing_structural_item_axis" + bl_label = "Enable Editing Structural Item Axis" def execute(self, context): obj = bpy.context.active_object @@ -377,11 +377,11 @@ class EnableEditingStructuralMemberAxis(bpy.types.Operator): props = obj.BIMStructuralProperties self.file = IfcStore.get_file() - member = self.file.by_id(oprops.ifc_definition_id) - z_axis = Vector(member.Axis.DirectionRatios).normalized() @ obj.matrix_world if member.Axis else None + item = self.file.by_id(oprops.ifc_definition_id) + z_axis = Vector(item.Axis.DirectionRatios).normalized() @ obj.matrix_world if item.Axis else None x_axis = (obj.data.vertices[1].co - obj.data.vertices[0].co).normalized() location = obj.data.vertices[0].co - empty = bpy.data.objects.new("Member Axis", None) + empty = bpy.data.objects.new("Item Axis", None) empty.empty_display_type = "ARROWS" if z_axis: y_axis = (z_axis.cross(x_axis)).normalized() @@ -404,9 +404,9 @@ class EnableEditingStructuralMemberAxis(bpy.types.Operator): return {"FINISHED"} -class DisableEditingStructuralMemberAxis(bpy.types.Operator): - bl_idname = "bim.disable_editing_structural_member_axis" - bl_label = "Disable Editing Structural Member Axis" +class DisableEditingStructuralItemAxis(bpy.types.Operator): + bl_idname = "bim.disable_editing_structural_item_axis" + bl_label = "Disable Editing Structural Item Axis" def execute(self, context): obj = bpy.context.active_object @@ -417,9 +417,9 @@ class DisableEditingStructuralMemberAxis(bpy.types.Operator): return {"FINISHED"} -class EditStructuralMemberAxis(bpy.types.Operator): - bl_idname = "bim.edit_structural_member_axis" - bl_label = "Edit Structural Member Axis" +class EditStructuralItemAxis(bpy.types.Operator): + bl_idname = "bim.edit_structural_item_axis" + bl_label = "Edit Structural Item Axis" def execute(self, context): obj = bpy.context.active_object @@ -429,12 +429,83 @@ class EditStructuralMemberAxis(bpy.types.Operator): z_axis = relative_matrix.col[2][0:3] self.file = IfcStore.get_file() ifcopenshell.api.run( - "structural.edit_structural_member_axis", + "structural.edit_structural_item_axis", self.file, - structural_member=self.file.by_id(oprops.ifc_definition_id), + structural_item=self.file.by_id(oprops.ifc_definition_id), axis=z_axis, ) - bpy.ops.bim.disable_editing_structural_member_axis() + bpy.ops.bim.disable_editing_structural_item_axis() + return {"FINISHED"} + + +class EnableEditingStructuralItemConnectionCS(bpy.types.Operator): + bl_idname = "bim.enable_editing_structural_item_connection_cs" + bl_label = "Enable Editing Structural Item Connection CS" + + def execute(self, context): + obj = bpy.context.active_object + oprops = obj.BIMObjectProperties + props = obj.BIMStructuralProperties + + self.file = IfcStore.get_file() + item = self.file.by_id(oprops.ifc_definition_id) + z_axis = Vector(item.Axis.DirectionRatios).normalized() @ obj.matrix_world if item.Axis else None + x_axis = (obj.data.vertices[1].co - obj.data.vertices[0].co).normalized() + location = obj.data.vertices[0].co + empty = bpy.data.objects.new("Item Connection CS", None) + empty.empty_display_type = "ARROWS" + if z_axis: + y_axis = (z_axis.cross(x_axis)).normalized() + empty.matrix_world = Matrix(( + (x_axis[0], y_axis[0], z_axis[0], location[0]), + (x_axis[1], y_axis[1], z_axis[1], location[1]), + (x_axis[2], y_axis[2], z_axis[2], location[2]), + (0, 0, 0, 1), + )) + else: + empty.location = location + empty.rotation_mode = "QUATERNION" + empty.rotation_quaternion = x_axis.to_track_quat("X", "Z") + + props.axis_angle = degrees(empty.rotation_euler[0]) + props.axis_empty = empty + context.scene.collection.objects.link(empty) + + props.is_editing_axis = True + return {"FINISHED"} + + +class DisableEditingStructuralItemConnectionCS(bpy.types.Operator): + bl_idname = "bim.disable_editing_structural_item_connection_cs" + bl_label = "Disable Editing Structural Item Connection CS" + + def execute(self, context): + obj = bpy.context.active_object + props = obj.BIMStructuralProperties + props.is_editing_axis = False + if props.axis_empty: + bpy.data.objects.remove(props.axis_empty) + return {"FINISHED"} + + +class EditStructuralItemConnectionCS(bpy.types.Operator): + bl_idname = "bim.edit_structural_item_connection_cs" + bl_label = "Edit Structural Item Connection CS" + + def execute(self, context): + obj = bpy.context.active_object + oprops = obj.BIMObjectProperties + props = obj.BIMStructuralProperties + relative_matrix = props.axis_empty.matrix_world @ obj.matrix_world.inverted() + z_axis = relative_matrix.col[2][0:3] + self.file = IfcStore.get_file() + ifcopenshell.api.run( + "structural.edit_structural_item_connection_cs", + self.file, + structural_item=self.file.by_id(oprops.ifc_definition_id), + axis=z_axis, + ) + bpy.ops.bim.disable_editing_structural_item_axis() return {"FINISHED"} diff --git a/src/blenderbim/blenderbim/bim/module/structural/prop.py b/src/blenderbim/blenderbim/bim/module/structural/prop.py index c05101ea84..c824fa338e 100644 --- a/src/blenderbim/blenderbim/bim/module/structural/prop.py +++ b/src/blenderbim/blenderbim/bim/module/structural/prop.py @@ -26,6 +26,17 @@ def updateAxisAngle(self, context): empty.rotation_mode = "XYZ" empty.rotation_euler[0] = radians(self.axis_angle) +def updateConnectionCS(self, context): + if not self.ccs_empty: + return + obj = context.active_object + empty = self.ccs_empty + empty.location = obj.data.vertices[0].co + empty.rotation_mode = "XYZ" + empty.rotation_euler[0] = radians(self.ccs_x_angle) + empty.rotation_euler[1] = radians(self.ccs_y_angle) + empty.rotation_euler[2] = radians(self.ccs_z_angle) + class StructuralAnalysisModel(PropertyGroup): name: StringProperty(name="Name") @@ -58,3 +69,8 @@ class BIMObjectStructuralProperties(PropertyGroup): axis_empty: PointerProperty(name="Axis Empty", type=bpy.types.Object) # relating_structural_activity: PointerProperty(name="Relating Structural Activity", type=bpy.types.Object) + is_editing_connection_cs: BoolProperty(name="Is Editing Connection CS", default=False) + ccs_x_angle: FloatProperty(name="Connection CS X Angle", update=updateConnectionCS) + ccs_y_angle: FloatProperty(name="Connection CS Y Angle", update=updateConnectionCS) + ccs_z_angle: FloatProperty(name="Connection CS Z Angle", update=updateConnectionCS) + ccs_empty: PointerProperty(name="CCS Empty", type=bpy.types.Object) diff --git a/src/blenderbim/blenderbim/bim/module/structural/ui.py b/src/blenderbim/blenderbim/bim/module/structural/ui.py index 4f33f899d1..4f9b0e0c0a 100644 --- a/src/blenderbim/blenderbim/bim/module/structural/ui.py +++ b/src/blenderbim/blenderbim/bim/module/structural/ui.py @@ -169,11 +169,63 @@ class BIM_PT_structural_member(Panel): if self.props.is_editing_axis: row = self.layout.row(align=True) row.prop(self.props, "axis_angle") - row.operator("bim.edit_structural_member_axis", text="", icon="CHECKMARK") - row.operator("bim.disable_editing_structural_member_axis", text="", icon="CANCEL") + row.operator("bim.edit_structural_item_axis", text="", icon="CHECKMARK") + row.operator("bim.disable_editing_structural_item_axis", text="", icon="CANCEL") else: row = self.layout.row() - row.operator("bim.enable_editing_structural_member_axis", text="Edit Axis", icon="GREASEPENCIL") + row.operator("bim.enable_editing_structural_item_axis", text="Edit Axis", icon="GREASEPENCIL") + else: + row = self.layout.row() + row.label(text="TODO") + + +class BIM_PT_structural_connection(Panel): + bl_label = "IFC Structural Connection" + bl_idname = "BIM_PT_structural_connection" + bl_options = {"DEFAULT_CLOSED"} + bl_space_type = "PROPERTIES" + bl_region_type = "WINDOW" + bl_context = "object" + + @classmethod + def poll(cls, context): + if not context.active_object: + return False + props = context.active_object.BIMObjectProperties + if not props.ifc_definition_id: + return False + if not IfcStore.get_file().by_id(props.ifc_definition_id).is_a("IfcStructuralConnection"): + return False + return True + + def draw(self, context): + self.oprops = context.active_object.BIMObjectProperties + self.props = context.active_object.BIMStructuralProperties + self.file = IfcStore.get_file() + + if self.file.by_id(self.oprops.ifc_definition_id).is_a("IfcStructuralCurveConnection"): + if self.props.is_editing_axis: + row = self.layout.row(align=True) + row.prop(self.props, "axis_angle") + row.operator("bim.edit_structural_item_axis", text="", icon="CHECKMARK") + row.operator("bim.disable_editing_structural_item_axis", text="", icon="CANCEL") + 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"): + if self.props.is_editing_connection_cs: + row = self.layout.row(align=True) + row.label(text="Editing Connection CS") + row.operator("bim.edit_structural_item_connection_cs", text="", icon="CHECKMARK") + row.operator("bim.disable_editing_structural_item_connection_cs", text="", icon="CANCEL") + row = self.layout.row(align=True) + row.prop(self.props, "ccs_x_angle") + row.prop(self.props, "ccs_y_angle") + row.prop(self.props, "ccs_z_angle") + else: + row = self.layout.row() + row.operator("bim.enable_editing_structural_item_connection_cs", text="Edit Connection CS", icon="GREASEPENCIL") else: row = self.layout.row() row.label(text="TODO") diff --git a/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_item_axis.py b/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_item_axis.py new file mode 100644 index 0000000000..11ed08cebb --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_item_axis.py @@ -0,0 +1,11 @@ +class Usecase: + def __init__(self, file, **settings): + self.file = file + self.settings = {"structural_item": None, "axis": [0.0, 0.0, 1.0]} + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + if len(self.file.get_inverse(self.settings["structural_item"].Axis)) == 1: + self.file.remove(self.settings["structural_item"].Axis) + self.settings["structural_item"].Axis = self.file.createIfcDirection(self.settings["axis"]) diff --git a/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_item_connection_cs.py b/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_item_connection_cs.py new file mode 100644 index 0000000000..60be7a633c --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_item_connection_cs.py @@ -0,0 +1,12 @@ +class Usecase: + def __init__(self, file, **settings): + self.file = file + self.settings = {"structural_item": None, "axis": [0.0, 0.0, 1.0]} + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + return + if len(self.file.get_inverse(self.settings["structural_item"].Axis)) == 1: + self.file.remove(self.settings["structural_item"].Axis) + self.settings["structural_item"].Axis = self.file.createIfcDirection(self.settings["axis"]) diff --git a/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_member_axis.py b/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_member_axis.py deleted file mode 100644 index 8701699914..0000000000 --- a/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_member_axis.py +++ /dev/null @@ -1,11 +0,0 @@ -class Usecase: - def __init__(self, file, **settings): - self.file = file - self.settings = {"structural_member": None, "axis": [0.0, 0.0, 1.0]} - for key, value in settings.items(): - self.settings[key] = value - - def execute(self): - if self.file.get_inverse(self.settings["structural_member"].Axis) == 1: - self.file.remove(self.settings["structural_member"].Axis) - self.settings["structural_member"].Axis = self.file.createIfcDirection(self.settings["axis"])