From 75ed4dcdd8eb42cd93d81bab255d9db6b20013e3 Mon Sep 17 00:00:00 2001 From: Jesusbill Date: Wed, 12 May 2021 17:43:07 +0200 Subject: [PATCH] you can now edit a structural connection coordinate system --- .../bim/module/structural/__init__.py | 10 +-- .../bim/module/structural/operator.py | 73 ++++++++++--------- .../blenderbim/bim/module/structural/ui.py | 16 ++-- .../ifcopenshell/api/structural/data.py | 52 +++++++++---- .../edit_structural_connection_cs.py | 23 ++++++ .../edit_structural_item_connection_cs.py | 12 --- 6 files changed, 114 insertions(+), 72 deletions(-) create mode 100644 src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_connection_cs.py delete mode 100644 src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_item_connection_cs.py diff --git a/src/blenderbim/blenderbim/bim/module/structural/__init__.py b/src/blenderbim/blenderbim/bim/module/structural/__init__.py index 20e5e28500..769a9497be 100644 --- a/src/blenderbim/blenderbim/bim/module/structural/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/structural/__init__.py @@ -23,9 +23,9 @@ classes = ( operator.EnableEditingStructuralItemAxis, operator.DisableEditingStructuralItemAxis, operator.EditStructuralItemAxis, - operator.EnableEditingStructuralItemConnectionCS, - operator.DisableEditingStructuralItemConnectionCS, - operator.EditStructuralItemConnectionCS, + operator.EnableEditingStructuralConnectionCS, + operator.DisableEditingStructuralConnectionCS, + operator.EditStructuralConnectionCS, operator.AddStructuralLoadCase, operator.EditStructuralLoadCase, operator.RemoveStructuralLoadCase, @@ -41,10 +41,10 @@ classes = ( 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_PT_structural_connection, + ui.BIM_PT_structural_boundary_conditions, + ui.BIM_PT_connected_structural_members, ui.BIM_UL_structural_analysis_models, ui.BIM_UL_structural_activities, 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 845f023b1f..420968768b 100644 --- a/src/blenderbim/blenderbim/bim/module/structural/operator.py +++ b/src/blenderbim/blenderbim/bim/module/structural/operator.py @@ -441,8 +441,8 @@ class EditStructuralItemAxis(bpy.types.Operator): return {"FINISHED"} -class EnableEditingStructuralItemConnectionCS(bpy.types.Operator): - bl_idname = "bim.enable_editing_structural_item_connection_cs" +class EnableEditingStructuralConnectionCS(bpy.types.Operator): + bl_idname = "bim.enable_editing_structural_connection_cs" bl_label = "Enable Editing Structural Item Connection CS" def execute(self, context): @@ -452,65 +452,72 @@ class EnableEditingStructuralItemConnectionCS(bpy.types.Operator): 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") + empty.location = location - props.axis_angle = degrees(empty.rotation_euler[0]) - props.axis_empty = empty + if item.ConditionCoordinateSystem is not None: + z_axis = Vector(item.ConditionCoordinateSystem.Axis.DirectionRatios).normalized() @ obj.matrix_world if item.ConditionCoordinateSystem.Axis else None + x_axis = Vector(item.ConditionCoordinateSystem.RefDirection.DirectionRatios).normalized() @ obj.matrix_world if item.ConditionCoordinateSystem.RefDirection else None + + if z_axis: + y_axis = (z_axis.cross(x_axis)).normalized() + x_axis = (y_axis.cross(z_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), + ) + ) + + + props.ccs_x_angle = degrees(empty.rotation_euler[0]) + props.ccs_y_angle = degrees(empty.rotation_euler[1]) + props.ccs_z_angle = degrees(empty.rotation_euler[2]) + props.ccs_empty = empty context.scene.collection.objects.link(empty) - props.is_editing_axis = True + props.is_editing_connection_cs = 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" +class DisableEditingStructuralConnectionCS(bpy.types.Operator): + bl_idname = "bim.disable_editing_structural_connection_cs" + bl_label = "Disable Editing Structural 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) + props.is_editing_connection_cs = False + if props.ccs_empty: + bpy.data.objects.remove(props.ccs_empty) return {"FINISHED"} -class EditStructuralItemConnectionCS(bpy.types.Operator): - bl_idname = "bim.edit_structural_item_connection_cs" - bl_label = "Edit Structural Item Connection CS" +class EditStructuralConnectionCS(bpy.types.Operator): + bl_idname = "bim.edit_structural_connection_cs" + bl_label = "Edit Structural 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() + relative_matrix = props.ccs_empty.matrix_world @ obj.matrix_world.inverted() + x_axis = relative_matrix.col[0][0:3] z_axis = relative_matrix.col[2][0:3] self.file = IfcStore.get_file() ifcopenshell.api.run( - "structural.edit_structural_item_connection_cs", + "structural.edit_structural_connection_cs", self.file, structural_item=self.file.by_id(oprops.ifc_definition_id), axis=z_axis, + ref_direction=x_axis, ) - bpy.ops.bim.disable_editing_structural_item_axis() + bpy.ops.bim.disable_editing_structural_connection_cs() return {"FINISHED"} diff --git a/src/blenderbim/blenderbim/bim/module/structural/ui.py b/src/blenderbim/blenderbim/bim/module/structural/ui.py index 0aa44036f8..e8d2080816 100644 --- a/src/blenderbim/blenderbim/bim/module/structural/ui.py +++ b/src/blenderbim/blenderbim/bim/module/structural/ui.py @@ -66,6 +66,7 @@ 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" @classmethod def poll(cls, context): @@ -95,6 +96,7 @@ 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" @classmethod def poll(cls, context): @@ -218,15 +220,17 @@ class BIM_PT_structural_connection(Panel): 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.operator("bim.edit_structural_connection_cs", text="", icon="CHECKMARK") + row.operator("bim.disable_editing_structural_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") + row.prop(self.props, "ccs_x_angle", text="X Angle") + row = self.layout.row(align=True) + row.prop(self.props, "ccs_y_angle", text="Y Angle") + row = self.layout.row(align=True) + row.prop(self.props, "ccs_z_angle", text="Z Angle") else: row = self.layout.row() - row.operator("bim.enable_editing_structural_item_connection_cs", text="Edit Connection CS", icon="GREASEPENCIL") + row.operator("bim.enable_editing_structural_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/data.py b/src/ifcopenshell-python/ifcopenshell/api/structural/data.py index 68b4344a6f..653694e808 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/structural/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/structural/data.py @@ -63,7 +63,6 @@ class Data: cls.products.setdefault(product.id(), []).append(model.id()) data = model.get_info() del data["OwnerHistory"] - del data["OrientationOf2DPlane"] loaded_by = [] for load_group in model.LoadedBy or []: @@ -75,6 +74,7 @@ class Data: has_results.append(result_group.id()) data["HasResults"] = has_results + data["OrientationOf2DPlane"] = model.OrientationOf2DPlane.id() if model.OrientationOf2DPlane else None data["SharedPlacement"] = model.SharedPlacement.id() if model.SharedPlacement else None cls.structural_analysis_models[model.id()] = data @@ -142,22 +142,31 @@ class Data: @classmethod def load_structural_connection(cls, product_id): - # cls.connections = {} cls.boundary_conditions = {} cls.connects_structural_members = {} connection = cls._file.by_id(product_id) - connection_data = {"AppliedCondition": None, "ConnectsStructuralMembers": []} + data = connection.get_info() + del data["OwnerHistory"] + + data["ObjectPlacement"] = data["ObjectPlacement"].id() if data["ObjectPlacement"] is not None else None + data["Representation"] = data["Representation"].id() if data["Representation"] is not None else None + if connection.is_a("IfcStructuralCurveConnection"): + data["Axis"] = data["Axis"].id() if data["Axis"] is not None else None + if connection.is_a("IfcStructuralPointConnection"): + data["ConditionCoordinateSystem"] = data["ConditionCoordinateSystem"].id() if data["ConditionCoordinateSystem"] is not None else None + + data["ConnectsStructuralMembers"] = [] if connection.AppliedCondition: cls.load_boundary_condition(connection.AppliedCondition) - connection_data["AppliedCondition"] = connection.AppliedCondition.id() + data["AppliedCondition"] = connection.AppliedCondition.id() for rel in connection.ConnectsStructuralMembers or []: cls.load_connects_structural_member(rel) - connection_data["ConnectsStructuralMembers"].append(rel.id()) + data["ConnectsStructuralMembers"].append(rel.id()) - cls.connections[connection.id()] = connection_data + cls.connections[connection.id()] = data @classmethod def load_boundary_condition(cls, boundary_condition): @@ -177,7 +186,7 @@ class Data: del rel_data["ConditionCoordinateSystem"] # TODO: consider orientation if rel.is_a("IfcRelConnectsWithEccentricity"): - rel_data["ConnectionConstraint"] = rel.ConnectionConstraint # TODO + rel_data["ConnectionConstraint"] = rel.ConnectionConstraint.id() # TODO if rel.AppliedCondition: cls.load_boundary_condition(rel.AppliedCondition) @@ -187,12 +196,7 @@ class Data: @classmethod def load_applied_load(cls, applied_load): - data = applied_load.get_info() - for key, value in data.items(): - if not value or key in ["Name", "type", "id"]: - continue - data[key] = value.wrappedValue - cls.applied_loads[applied_load.id()] = data + cls.applied_loads[applied_load.id()] = applied_load.get_info() @classmethod def load_connects_structural_activity(cls, rel): @@ -210,12 +214,28 @@ class Data: @classmethod def load_structural_member(cls, product_id): cls.connects_structural_activities = {} + cls.connects_structural_members = {} member = cls._file.by_id(product_id) - member_data = {"ConnectsStructuralActivities": []} + data = member.get_info() + + del data["OwnerHistory"] + + data["ObjectPlacement"] = data["ObjectPlacement"].id() if data["ObjectPlacement"] is not None else None + data["Representation"] = data["Representation"].id() if data["Representation"] is not None else None + if member.is_a("IfcStructuralCurveMember"): + data["Axis"] = data["Axis"].id() if data["Axis"] is not None else None + + data["ConnectsStructuralActivities"] = [] + data["ConnectedBy"] = [] for activity in member.AssignedStructuralActivity or []: cls.load_connects_structural_activity(activity) - member_data["ConnectsStructuralActivities"].append(activity.id()) + data["ConnectsStructuralActivities"].append(activity.id()) - cls.members[member.id()] = member_data + for rel in member.ConnectedBy or []: + cls.load_connects_structural_member(rel) + data["ConnectedBy"].append(rel.id()) + + + cls.members[member.id()] = data \ No newline at end of file diff --git a/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_connection_cs.py b/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_connection_cs.py new file mode 100644 index 0000000000..f466bbbe92 --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_connection_cs.py @@ -0,0 +1,23 @@ +class Usecase: + def __init__(self, file, **settings): + self.file = file + self.settings = {"structural_item": None, "axis": [0.0, 0.0, 1.0], "ref_direction": [1.0, 0.0, 0.0]} + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + if self.settings["structural_item"].ConditionCoordinateSystem is None: + point = self.file.createIfcCartesianPoint((0.0, 0.0, 0.0)) + ccs = self.file.createIfcAxis2Placement3D(point, None, None) + self.settings["structural_item"].ConditionCoordinateSystem = ccs + print(ccs) + + ccs = self.settings["structural_item"].ConditionCoordinateSystem + print("use case") + print(ccs) + if ccs.Axis and len(self.file.get_inverse(ccs.Axis)) == 1: + self.file.remove(ccs.Axis) + ccs.Axis = self.file.createIfcDirection(self.settings["axis"]) + if ccs.RefDirection and len(self.file.get_inverse(ccs.RefDirection)) == 1: + self.file.remove(ccs.RefDirection) + ccs.RefDirection = self.file.createIfcDirection(self.settings["ref_direction"]) \ No newline at end of file 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 deleted file mode 100644 index 60be7a633c..0000000000 --- a/src/ifcopenshell-python/ifcopenshell/api/structural/edit_structural_item_connection_cs.py +++ /dev/null @@ -1,12 +0,0 @@ -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"])