From d5c70e51f2f17f72c2a50a304edcc99afc4fc580 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Tue, 13 Apr 2021 13:04:05 +1000 Subject: [PATCH] You can now edit structural member axis orientations. Thanks Jesusbill! --- .../blenderbim/bim/module/aggregate/ui.py | 3 +- .../bim/module/structural/__init__.py | 4 + .../bim/module/structural/operator.py | 73 +++++++++++++++++++ .../blenderbim/bim/module/structural/prop.py | 17 +++++ .../blenderbim/bim/module/structural/ui.py | 38 ++++++++++ .../structural/edit_structural_member_axis.py | 11 +++ 6 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_member_axis.py diff --git a/src/blenderbim/blenderbim/bim/module/aggregate/ui.py b/src/blenderbim/blenderbim/bim/module/aggregate/ui.py index 7e593d3020..474b51c23f 100644 --- a/src/blenderbim/blenderbim/bim/module/aggregate/ui.py +++ b/src/blenderbim/blenderbim/bim/module/aggregate/ui.py @@ -34,7 +34,8 @@ class BIM_PT_aggregate(Panel): if props.is_editing_aggregate: row = self.layout.row(align=True) row.prop(props, "relating_object", text="") - row.operator("bim.assign_object", icon="CHECKMARK", text="").relating_object = props.relating_object.name + if props.relating_object: + row.operator("bim.assign_object", icon="CHECKMARK", text="").relating_object = props.relating_object.name row.operator("bim.disable_editing_aggregate", icon="X", text="") else: row = self.layout.row(align=True) diff --git a/src/blenderbim/blenderbim/bim/module/structural/__init__.py b/src/blenderbim/blenderbim/bim/module/structural/__init__.py index 816b5b374e..a361a238ad 100644 --- a/src/blenderbim/blenderbim/bim/module/structural/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/structural/__init__.py @@ -20,12 +20,16 @@ classes = ( operator.EnableEditingStructuralConnectionCondition, operator.DisableEditingStructuralConnectionCondition, operator.RemoveStructuralConnectionCondition, + operator.EnableEditingStructuralMemberAxis, + operator.DisableEditingStructuralMemberAxis, + operator.EditStructuralMemberAxis, prop.StructuralAnalysisModel, prop.BIMStructuralProperties, prop.BIMObjectStructuralProperties, ui.BIM_PT_structural_analysis_models, ui.BIM_PT_structural_boundary_conditions, ui.BIM_PT_connected_structural_members, + ui.BIM_PT_structural_member, ui.BIM_UL_structural_analysis_models, ) diff --git a/src/blenderbim/blenderbim/bim/module/structural/operator.py b/src/blenderbim/blenderbim/bim/module/structural/operator.py index a997d2e91f..5d735ef84c 100644 --- a/src/blenderbim/blenderbim/bim/module/structural/operator.py +++ b/src/blenderbim/blenderbim/bim/module/structural/operator.py @@ -2,6 +2,8 @@ import bpy import json import ifcopenshell import ifcopenshell.api +from math import degrees +from mathutils import Vector, Matrix from blenderbim.bim.ifc import IfcStore from ifcopenshell.api.structural.data import Data from ifcopenshell.api.context.data import Data as ContextData @@ -363,3 +365,74 @@ class UnassignStructuralAnalysisModel(bpy.types.Operator): ) Data.load(IfcStore.get_file()) return {"FINISHED"} + + +class EnableEditingStructuralMemberAxis(bpy.types.Operator): + bl_idname = "bim.enable_editing_structural_member_axis" + bl_label = "Enable Editing Structural Member Axis" + + def execute(self, context): + obj = bpy.context.active_object + oprops = obj.BIMObjectProperties + 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 + 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.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 DisableEditingStructuralMemberAxis(bpy.types.Operator): + bl_idname = "bim.disable_editing_structural_member_axis" + bl_label = "Disable Editing Structural Member Axis" + + 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 EditStructuralMemberAxis(bpy.types.Operator): + bl_idname = "bim.edit_structural_member_axis" + bl_label = "Edit Structural Member Axis" + + 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_member_axis", + self.file, + structural_member=self.file.by_id(oprops.ifc_definition_id), + axis=z_axis, + ) + bpy.ops.bim.disable_editing_structural_member_axis() + return {"FINISHED"} diff --git a/src/blenderbim/blenderbim/bim/module/structural/prop.py b/src/blenderbim/blenderbim/bim/module/structural/prop.py index f8cc972b87..71709c470d 100644 --- a/src/blenderbim/blenderbim/bim/module/structural/prop.py +++ b/src/blenderbim/blenderbim/bim/module/structural/prop.py @@ -1,4 +1,5 @@ import bpy +from math import radians from blenderbim.bim.prop import StrProperty, Attribute from bpy.types import PropertyGroup from bpy.props import ( @@ -13,6 +14,19 @@ from bpy.props import ( ) +def updateAxisAngle(self, context): + if not self.axis_empty: + return + obj = context.active_object + empty = self.axis_empty + x_axis = obj.data.vertices[1].co - obj.data.vertices[0].co + empty.location = obj.data.vertices[0].co + empty.rotation_mode = "QUATERNION" + empty.rotation_quaternion = x_axis.to_track_quat("X", "Z") + empty.rotation_mode = "XYZ" + empty.rotation_euler[0] = radians(self.axis_angle) + + class StructuralAnalysisModel(PropertyGroup): name: StringProperty(name="Name") ifc_definition_id: IntProperty(name="IFC Definition ID") @@ -33,3 +47,6 @@ class BIMObjectStructuralProperties(PropertyGroup): active_boundary_condition: IntProperty(name="Active Boundary Condition") active_connects_structural_member: IntProperty(name="Active Connects Structural Member") relating_structural_member: PointerProperty(name="Relating Structural Member", type=bpy.types.Object) + is_editing_axis: BoolProperty(name="Is Editing Axis", default=False) + axis_angle: FloatProperty(name="Axis Angle", update=updateAxisAngle) + axis_empty: PointerProperty(name="Axis 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 87aff9b060..b1b51edd4d 100644 --- a/src/blenderbim/blenderbim/bim/module/structural/ui.py +++ b/src/blenderbim/blenderbim/bim/module/structural/ui.py @@ -141,6 +141,44 @@ class BIM_PT_connected_structural_members(Panel): draw_boundary_condition_ui(box, data["AppliedCondition"], data["id"], self.props) +class BIM_PT_structural_member(Panel): + bl_label = "IFC Structural Member" + bl_idname = "BIM_PT_structural_member" + 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("IfcStructuralMember"): + 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("IfcStructuralCurveMember"): + 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") + else: + row = self.layout.row() + row.operator("bim.enable_editing_structural_member_axis", text="Edit Axis", icon="GREASEPENCIL") + else: + row = self.layout.row() + row.label(text="TODO") + + class BIM_PT_structural_analysis_models(Panel): bl_label = "IFC Structural Analysis Models" bl_idname = "BIM_PT_structural_analysis_models" 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 new file mode 100644 index 0000000000..8701699914 --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_member_axis.py @@ -0,0 +1,11 @@ +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"])