feat: 新增波形能量动画系统 plot_wave.py
- 创建 plot_wave.py: 从 display.txt 读取原子位移数据 绘制纵波(x) + 横波(y) + 横波(z) 波形随时间的动画 同时绘制系统动能/弹性势能/总能量/输入功率(dE/dt)时变曲线 输出 wave_animation.gif - 所有 input.txt 新增 step_plot_wave: 0 开关 - case05 开启 step_plot_wave: 1 - dynamics.py disp_data 新增 bond_stiffness/bond_rest_lengths - 更新案例文档
This commit is contained in:
@@ -317,10 +317,11 @@ def update_camera_info(event=None):
|
||||
c = view.camera
|
||||
camera_info.text = (
|
||||
"Camera\n"
|
||||
f"center = ({c.center[0]:.2f}, {c.center[1]:.2f}, {c.center[2]:.2f})\n"
|
||||
f"distance = {c.distance:.2f}\n"
|
||||
f"elevation = {c.elevation:.2f}\n"
|
||||
f"azimuth = {c.azimuth:.2f}"
|
||||
f"center = ({c.center[0]:.1f}, {c.center[1]:.1f}, {c.center[2]:.1f})\n"
|
||||
f"distance = {c.distance:.1f}\n"
|
||||
f"elevation = {c.elevation:.1f}\n"
|
||||
f"azimuth = {c.azimuth:.1f}\n"
|
||||
f"step = {PAN_SPEED:.1f} | {'透视' if _PERSPECTIVE else '正交'}"
|
||||
)
|
||||
|
||||
|
||||
@@ -333,6 +334,7 @@ def update_ball_info(frame_idx, x, y, z, vx, vy, vz):
|
||||
f"t = {t:.2f} s | dt = {DT:.3f} s | nstep = {NSTEP}\n"
|
||||
f"Position: ({x:.2f}, {y:.2f}, {z:.2f})\n"
|
||||
f"Velocity: ({vx:.2f}, {vy:.2f}, {vz:.2f})\n"
|
||||
f"W/S 沿Z轴 | A/D 左右 | Q/E 升降 | C/X 步长 | V 透视/正交"
|
||||
)
|
||||
|
||||
|
||||
@@ -358,28 +360,99 @@ def reposition_camera_info(event=None):
|
||||
update_camera_info()
|
||||
|
||||
|
||||
# ── 平移速度 & 投影模式(全局变量)──
|
||||
PAN_SPEED = 1.0
|
||||
_PERSPECTIVE = True # True=透视, False=正交
|
||||
|
||||
|
||||
def handle_view_interaction(event):
|
||||
update_camera_info()
|
||||
|
||||
|
||||
def rotate_about_screen_normal(angle):
|
||||
if hasattr(view.camera, "roll"):
|
||||
view.camera.roll = (view.camera.roll + angle) % 360
|
||||
else:
|
||||
view.camera.azimuth = (view.camera.azimuth + angle) % 360
|
||||
update_camera_info()
|
||||
|
||||
|
||||
def handle_key_press(event):
|
||||
global PAN_SPEED, _PERSPECTIVE
|
||||
key_name = ""
|
||||
if getattr(event, "text", None):
|
||||
key_name = event.text.lower()
|
||||
elif getattr(event, "key", None) is not None:
|
||||
key_name = str(event.key).lower()
|
||||
if key_name == "q":
|
||||
rotate_about_screen_normal(-90)
|
||||
elif key_name == "e":
|
||||
rotate_about_screen_normal(90)
|
||||
|
||||
c = view.camera
|
||||
|
||||
# ── 投影切换 ──
|
||||
if key_name == "v":
|
||||
_PERSPECTIVE = not _PERSPECTIVE
|
||||
try:
|
||||
if _PERSPECTIVE:
|
||||
c.fov = 60.0
|
||||
else:
|
||||
c.fov = 0.0
|
||||
print(f"[draw] 投影模式: {'透视' if _PERSPECTIVE else '正交'}")
|
||||
except Exception:
|
||||
print("[draw] 当前相机不支持 fov 切换")
|
||||
update_camera_info()
|
||||
return
|
||||
|
||||
# ── 步长控制 ──
|
||||
if key_name == "c":
|
||||
PAN_SPEED = min(PAN_SPEED * 1.5, 50.0)
|
||||
print(f"[draw] 步长: {PAN_SPEED:.1f}")
|
||||
update_camera_info()
|
||||
return
|
||||
elif key_name == "x":
|
||||
PAN_SPEED = max(PAN_SPEED / 1.5, 0.05)
|
||||
print(f"[draw] 步长: {PAN_SPEED:.1f}")
|
||||
update_camera_info()
|
||||
return
|
||||
|
||||
# ── 计算相机方向向量 ──
|
||||
import math as _math
|
||||
azim_rad = _math.radians(c.azimuth)
|
||||
elev_rad = _math.radians(c.elevation)
|
||||
|
||||
# 视线方向(从 center 指向相机)
|
||||
vd = np.array([
|
||||
_math.cos(elev_rad) * _math.sin(azim_rad),
|
||||
_math.sin(elev_rad),
|
||||
_math.cos(elev_rad) * _math.cos(azim_rad),
|
||||
])
|
||||
vd /= np.linalg.norm(vd)
|
||||
|
||||
# 屏幕右方向
|
||||
world_up = np.array([0.0, 1.0, 0.0])
|
||||
right = np.cross(vd, world_up)
|
||||
rn = np.linalg.norm(right)
|
||||
if rn > 1e-10:
|
||||
right /= rn
|
||||
else:
|
||||
right = np.array([1.0, 0.0, 0.0])
|
||||
|
||||
# 屏幕上方向
|
||||
up = np.cross(right, vd)
|
||||
un = np.linalg.norm(up)
|
||||
if un > 1e-10:
|
||||
up /= un
|
||||
else:
|
||||
up = np.array([0.0, 1.0, 0.0])
|
||||
|
||||
pan = PAN_SPEED * 0.3
|
||||
|
||||
if key_name == "a": # 右移(屏幕右方向)
|
||||
c.center = tuple(np.array(c.center) + right * pan)
|
||||
elif key_name == "d": # 左移(屏幕右方向负向)
|
||||
c.center = tuple(np.array(c.center) - right * pan)
|
||||
elif key_name == "e": # 上升(屏幕上方向,原 W 的功能)
|
||||
c.center = tuple(np.array(c.center) + up * pan)
|
||||
elif key_name == "q": # 下降(屏幕上方向负向,原 S 的功能)
|
||||
c.center = tuple(np.array(c.center) - up * pan)
|
||||
elif key_name == "w": # 相机沿 Z 轴上移(靠近场景)
|
||||
c.center = (c.center[0], c.center[1], c.center[2] + pan)
|
||||
elif key_name == "s": # 相机沿 Z 轴下移(远离场景)
|
||||
c.center = (c.center[0], c.center[1], c.center[2] - pan)
|
||||
else:
|
||||
return
|
||||
|
||||
update_camera_info()
|
||||
|
||||
|
||||
def reset_camera_view():
|
||||
|
||||
Reference in New Issue
Block a user