pip install matplotlib
pip install matplotlib keyboard
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import keyboard
# 初始化大腿和小腿的旋转角度
thigh_angles = [0, 0, 0] # 分别对应x, y, z轴的旋转角度
calf_angles = [0, 0, 0] # 小腿相对于大腿的旋转角度
foot_angles = [0, 0, 0] # 脚掌相对于小腿的旋转角度
# 创建3D图形
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# 设置3D视图的坐标轴范围
ax.set_xlim(-2, 2)
ax.set_ylim(-2, 2)
ax.set_zlim(-2, 2)
# 绘制大腿、小腿和脚掌的球棍模型(线),起始点为原点
thigh_line, = ax.plot([0, 0], [0, 0], [0, 1], 'ko-', lw=5, label='Thigh')
calf_line, = ax.plot([0, 0], [0, 0], [1, 1.5], 'bo-', lw=2, label='Calf')
foot_line, = ax.plot([0, 0], [0, 0], [1.5, 1.5], 'go-', lw=2, label='Foot')
# 旋转棍子并更新其位置
def update_lines():
# 计算大腿的新端点坐标
thigh_end_point = calculate_end_point(thigh_angles, length=1)
thigh_line.set_data([0, thigh_end_point[0]], [0, thigh_end_point[1]])
thigh_line.set_3d_properties([0, thigh_end_point[2]])
# 计算小腿的新端点坐标,它是相对于大腿绘制的
calf_start_point = thigh_end_point
calf_end_point = calf_start_point + calculate_end_point(calf_angles, length=0.5)
calf_line.set_data([calf_start_point[0], calf_end_point[0]], [calf_start_point[1], calf_end_point[1]])
calf_line.set_3d_properties([calf_start_point[2], calf_end_point[2]])
# 计算脚掌的新端点坐标,它是相对于小腿绘制的
foot_start_point = calf_end_point
foot_end_point = foot_start_point + calculate_end_point(foot_angles, length=0.5)
foot_line.set_data([foot_start_point[0], foot_end_point[0]], [foot_start_point[1], foot_end_point[1]])
foot_line.set_3d_properties([foot_start_point[2], foot_end_point[2]])
# 刷新图形
fig.canvas.draw_idle()
# 计算旋转后的端点坐标
def calculate_end_point(angles, length=1):
R_x = np.array([[1, 0, 0],
[0, np.cos(np.radians(angles[0])), -np.sin(np.radians(angles[0]))],
[0, np.sin(np.radians(angles[0])), np.cos(np.radians(angles[0]))]])
R_y = np.array([[np.cos(np.radians(angles[1])), 0, np.sin(np.radians(angles[1]))],
[0, 1, 0],
[-np.sin(np.radians(angles[1])), 0, np.cos(np.radians(angles[1]))]])
R_z = np.array([[np.cos(np.radians(angles[2])), -np.sin(np.radians(angles[2])), 0],
[np.sin(np.radians(angles[2])), np.cos(np.radians(angles[2])), 0],
[0, 0, 1]])
R = R_x @ R_y @ R_z
return R @ np.array([0, 0, length])
# 通过键盘输入来调整各部位的旋转角度
def on_press(event):
global thigh_angles, calf_angles, foot_angles
if event.event_type == 'down':
if event.name == 'up':
thigh_angles[0] = (thigh_angles[0] + 5) % 360 # 绕x轴旋转
elif event.name == 'down':
thigh_angles[0] = (thigh_angles[0] - 5) % 360 # 绕x轴旋转
elif event.name == 'left':
thigh_angles[1] = (thigh_angles[1] + 5) % 360 # 绕y轴旋转
elif event.name == 'right':
thigh_angles[1] = (thigh_angles[1] - 5) % 360 # 绕y轴旋转
elif event.name == 'page up':
thigh_angles[2] = (thigh_angles[2] + 5) % 360 # 绕z轴旋转
elif event.name == 'page down':
thigh_angles[2] = (thigh_angles[2] - 5) % 360 # 绕z轴旋转
update_lines()
# 监听键盘事件
keyboard.hook(on_press)
# 显示图形
plt.legend()
plt.show()
运行脚本,它将显示一个从原点出发的球棍模型。你可以通过按下“上下左右”键和Page Up/Page Down键来分别绕x轴、y轴和z轴旋转模型。