FEM: Addition of "half cycle" animation (#24129)
* Animation of Results - addition of half cycle * Delete src/Mod/Fem/Gui/Resources/ui/ResultShow.ui * Delete src/Mod/Fem/femtaskpanels/task_result_mechanical.py * Delete src/Mod/Fem/femviewprovider/view_result_mechanical.py * Add files via upload * Add files via upload * Add files via upload * Update view_result_mechanical.py * Update task_result_mechanical.py * Update task_result_mechanical.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Delete user_guide_animate.txt * Delete results.png --------- Co-authored-by: mac-the-bike <mac-the-bike@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
@@ -60,7 +60,7 @@
|
||||
<item row="1" column="1">
|
||||
<widget class="QRadioButton" name="rb_vm_stress">
|
||||
<property name="text">
|
||||
<string>von Mises Stress</string>
|
||||
<string>von Mises stress</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -495,9 +495,9 @@
|
||||
<widget class="QPushButton" name="startButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<x>230</x>
|
||||
<y>130</y>
|
||||
<width>435</width>
|
||||
<width>200</width>
|
||||
<height>25</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -508,6 +508,35 @@
|
||||
<string>Start Animation</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QRadioButton" name="rb_full_cycle">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>130</y>
|
||||
<width>91</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string> Full cycle</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QRadioButton" name="rb_half_cycle">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>120</x>
|
||||
<y>130</y>
|
||||
<width>101</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Half cycle</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
# * Copyright (c) 2015 Qingfeng Xia <qingfeng.xia()eng.ox.ac.uk> *
|
||||
# * Copyright (c) 2016 Bernd Hahnebach <bernd@bimstatik.org> *
|
||||
# * Copyright (c) 2024 PMcB *
|
||||
# * Copyright (c) 2025 PMcB *
|
||||
# * *
|
||||
# * This file is part of the FreeCAD CAx development system. *
|
||||
# * *
|
||||
@@ -266,6 +267,11 @@ class _TaskPanel:
|
||||
self.result_widget.steps.setValue(FreeCAD.FEM_dialog["animate"][0])
|
||||
self.result_widget.loops.setValue(FreeCAD.FEM_dialog["animate"][1])
|
||||
self.result_widget.framerate.setValue(FreeCAD.FEM_dialog["animate"][2])
|
||||
if FreeCAD.FEM_dialog["animate"][3]:
|
||||
self.result_widget.rb_full_cycle.setChecked(True)
|
||||
else:
|
||||
self.result_widget.rb_half_cycle.setChecked(True)
|
||||
self.result_widget.sb_displacement_factor.setValue(FreeCAD.FEM_dialog["animate"][4])
|
||||
except Exception:
|
||||
self.restore_initial_result_dialog()
|
||||
|
||||
@@ -284,7 +290,7 @@ class _TaskPanel:
|
||||
"show_disp": True, # False,
|
||||
"disp_factor": 5.0,
|
||||
"disp_factor_max": 100.0,
|
||||
"animate": [-1, -1, -1, -1], # steps, loops, rate, indicator (not used)
|
||||
"animate": [-1, -1, -1, -1, -1, -1, -1], # steps, loops, rate, cycle type
|
||||
}
|
||||
self.result_widget.sb_displacement_factor_max.setValue(100.0) # init non standard values
|
||||
|
||||
@@ -315,7 +321,7 @@ class _TaskPanel:
|
||||
"Uabs",
|
||||
self.result_obj.DisplacementLengths,
|
||||
"mm",
|
||||
translate("FEM", "Displacement Magnitude"),
|
||||
translate("FEM", "Displacement magnitude"),
|
||||
)
|
||||
else:
|
||||
self.result_widget.rb_none.setChecked(True)
|
||||
@@ -351,7 +357,7 @@ class _TaskPanel:
|
||||
"Sabs",
|
||||
self.result_obj.vonMises,
|
||||
"MPa",
|
||||
translate("FEM", "von Mises Stress"),
|
||||
translate("FEM", "von Mises stress"),
|
||||
)
|
||||
else:
|
||||
self.result_widget.rb_none.setChecked(True)
|
||||
@@ -363,7 +369,7 @@ class _TaskPanel:
|
||||
"MaxShear",
|
||||
self.result_obj.MaxShear,
|
||||
"MPa",
|
||||
translate("FEM", "Max Shear Stress"),
|
||||
translate("FEM", "Maximum shear stress (Tresca)"),
|
||||
)
|
||||
else:
|
||||
self.result_widget.rb_none.setChecked(True)
|
||||
@@ -375,7 +381,7 @@ class _TaskPanel:
|
||||
"MaxPrin",
|
||||
self.result_obj.PrincipalMax,
|
||||
"MPa",
|
||||
translate("FEM", "Max Principal Stress"),
|
||||
translate("FEM", "Maximum principal stress"),
|
||||
)
|
||||
else:
|
||||
self.result_widget.rb_none.setChecked(True)
|
||||
@@ -399,7 +405,7 @@ class _TaskPanel:
|
||||
"MFlow",
|
||||
self.result_obj.MassFlowRate,
|
||||
"kg/s",
|
||||
translate("FEM", "Mass Flow Rate"),
|
||||
translate("FEM", "Mass flow rate"),
|
||||
)
|
||||
else:
|
||||
self.result_widget.rb_none.setChecked(True)
|
||||
@@ -411,7 +417,7 @@ class _TaskPanel:
|
||||
"NPress",
|
||||
self.result_obj.NetworkPressure,
|
||||
"MPa",
|
||||
translate("FEM", "Network Pressure"),
|
||||
translate("FEM", "Network pressure"),
|
||||
)
|
||||
else:
|
||||
self.result_widget.rb_none.setChecked(True)
|
||||
@@ -423,7 +429,7 @@ class _TaskPanel:
|
||||
"MinPrin",
|
||||
self.result_obj.PrincipalMin,
|
||||
"MPa",
|
||||
translate("FEM", "Min Principal Stress"),
|
||||
translate("FEM", "Minimum principal stress"),
|
||||
)
|
||||
else:
|
||||
self.result_widget.rb_none.setChecked(True)
|
||||
@@ -435,7 +441,7 @@ class _TaskPanel:
|
||||
"Peeq",
|
||||
self.result_obj.Peeq,
|
||||
"",
|
||||
translate("FEM", "Equivalent Plastic Strain"),
|
||||
translate("FEM", "Equivalent plastic strain"),
|
||||
)
|
||||
else:
|
||||
self.result_widget.rb_none.setChecked(True)
|
||||
@@ -787,8 +793,14 @@ class _TaskPanel:
|
||||
FreeCAD.FEM_dialog["animate"][0] = self.result_widget.steps.value()
|
||||
FreeCAD.FEM_dialog["animate"][1] = self.result_widget.loops.value()
|
||||
FreeCAD.FEM_dialog["animate"][2] = self.result_widget.framerate.value()
|
||||
FreeCAD.FEM_dialog["animate"][3] = self.result_widget.rb_full_cycle.isChecked()
|
||||
try:
|
||||
FreeCAD.FEM_dialog["animate"][4] = self.result_widget.sb_displacement_factor.value()
|
||||
except:
|
||||
FreeCAD.FEM_dialog["animate"][4] = 1
|
||||
|
||||
# animation start
|
||||
|
||||
def animate_displacement(self):
|
||||
if "result_obj" in FreeCAD.FEM_dialog:
|
||||
if FreeCAD.FEM_dialog["result_obj"] != self.result_obj:
|
||||
@@ -806,22 +818,44 @@ class _TaskPanel:
|
||||
steps_per_cycle = int(self.result_widget.steps.value())
|
||||
number_cycles = int(self.result_widget.loops.value())
|
||||
|
||||
inc = math.pi / steps_per_cycle * 2.0
|
||||
sinc = inc = math.pi / steps_per_cycle * 2.0
|
||||
self.set_label(self.result_obj.Label, self.results_name)
|
||||
|
||||
done = False
|
||||
for lo in range(0, number_cycles):
|
||||
for st in range(0, steps_per_cycle):
|
||||
# for lo in range(0, number_cycles):
|
||||
loops = max(1, number_cycles) * steps_per_cycle + 1
|
||||
st = 0
|
||||
for loop in range(0, loops):
|
||||
if self.result_widget.rb_half_cycle.isChecked():
|
||||
if number_cycles > 0: # 0 -> 1 -> 0, repeated
|
||||
inc = sinc / 2
|
||||
else:
|
||||
inc = sinc / 4
|
||||
# full cycle
|
||||
if self.result_widget.rb_full_cycle.isChecked():
|
||||
self.mesh_obj.ViewObject.applyDisplacement(
|
||||
math.sin(st * inc) * self.hsb_displacement_factor
|
||||
)
|
||||
FreeCADGui.updateGui()
|
||||
if not self.startAnimate:
|
||||
done = True
|
||||
break
|
||||
time.sleep(1.0 / frame_rate) # modify the time here
|
||||
if done:
|
||||
elif self.result_widget.rb_half_cycle.isChecked():
|
||||
# half cycle
|
||||
if number_cycles > 0: # 0 -> 1 -> 0, repeated
|
||||
self.mesh_obj.ViewObject.applyDisplacement(
|
||||
abs(math.sin(st * inc)) * self.hsb_displacement_factor
|
||||
)
|
||||
elif number_cycles <= 0: # 0 -> 1, once
|
||||
self.mesh_obj.ViewObject.applyDisplacement(
|
||||
abs(math.sin(st * inc)) * self.hsb_displacement_factor
|
||||
)
|
||||
else:
|
||||
print("No cycle type selected")
|
||||
FreeCADGui.updateGui()
|
||||
if not self.startAnimate:
|
||||
done = True
|
||||
break
|
||||
time.sleep(1.0 / frame_rate) # modify the time here
|
||||
st += 1
|
||||
# if done:
|
||||
# break
|
||||
try:
|
||||
self.result_widget.startButton.setText("Start Animation")
|
||||
except:
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
# * Copyright (c) 2015 Qingfeng Xia <qingfeng.xia()eng.ox.ac.uk> *
|
||||
# * Copyright (c) 2016 Bernd Hahnebach <bernd@bimstatik.org> *
|
||||
# * Copyright (c) 2024 PMcB *
|
||||
# * Copyright (c) 2025 PMcB *
|
||||
# * *
|
||||
# * This file is part of the FreeCAD CAx development system. *
|
||||
# * *
|
||||
@@ -44,6 +45,8 @@ class VPResultMechanical(view_base_femconstraint.VPBaseFemConstraint):
|
||||
"""
|
||||
|
||||
def setEdit(self, vobj, mode=0):
|
||||
# is mesh visible
|
||||
self.visibility = self.Object.Mesh.ViewObject.Visibility
|
||||
return view_base_femconstraint.VPBaseFemConstraint.setEdit(
|
||||
self,
|
||||
vobj,
|
||||
@@ -51,12 +54,11 @@ class VPResultMechanical(view_base_femconstraint.VPBaseFemConstraint):
|
||||
task_result_mechanical._TaskPanel,
|
||||
)
|
||||
|
||||
# overwrite unsetEdit, hide result mesh object on task panel exit
|
||||
def unsetEdit(self, vobj, mode=0):
|
||||
FreeCADGui.Control.closeDialog()
|
||||
# hide the mesh after result viewing is finished, but do not reset the coloring
|
||||
# change this to not hide - PMcB
|
||||
# self.Object.Mesh.ViewObject.hide()
|
||||
# hide the mesh if it was not visible
|
||||
if not self.visibility:
|
||||
self.Object.Mesh.ViewObject.hide()
|
||||
return True
|
||||
|
||||
def claimChildren(self):
|
||||
|
||||
Reference in New Issue
Block a user