143 lines
3.2 KiB
Python
143 lines
3.2 KiB
Python
import numpy as np
|
|
import matplotlib.pyplot as plt
|
|
from mpl_toolkits.mplot3d import Axes3D
|
|
from matplotlib.animation import FuncAnimation
|
|
from matplotlib.widgets import Button
|
|
|
|
cube_points = np.array([
|
|
[-1, -1, -1],
|
|
[-1, -1, 1],
|
|
[-1, 1, -1],
|
|
[-1, 1, 1],
|
|
[ 1, -1, -1],
|
|
[ 1, -1, 1],
|
|
[ 1, 1, -1],
|
|
[ 1, 1, 1]
|
|
])
|
|
|
|
edges = [
|
|
(0, 1), (0, 2), (0, 4),
|
|
(1, 3), (1, 5),
|
|
(2, 3), (2, 6),
|
|
(3, 7),
|
|
(4, 5), (4, 6),
|
|
(5, 7),
|
|
(6, 7)
|
|
]
|
|
|
|
def rotation_y(theta):
|
|
return np.array([
|
|
[np.cos(theta), 0, np.sin(theta)],
|
|
[0, 1, 0], # 0,1,0
|
|
[-np.sin(theta), 0, np.cos(theta)]
|
|
])
|
|
|
|
|
|
def rotation_z(theta):
|
|
return np.array([
|
|
[np.cos(theta), -np.sin(theta), 0],
|
|
[np.sin(theta), np.cos(theta), 0],
|
|
[0, 0, 1]
|
|
])
|
|
|
|
|
|
fig = plt.figure(figsize=(8, 6))
|
|
ax = fig.add_subplot(111, projection='3d')
|
|
ax.set_xlim(-2, 2)
|
|
ax.set_ylim(-2, 2)
|
|
ax.set_zlim(-2, 2)
|
|
ax.set_box_aspect([1, 1, 1])
|
|
ax.set_title("Matrixmultiplikation", pad=20)
|
|
|
|
lines = [ax.plot([], [], [], color='red')[0] for _ in edges]
|
|
text = ax.text2D(1.02, 0.5, "", transform=ax.transAxes,
|
|
fontsize=10, color='black', family='monospace', va='center')
|
|
|
|
paused = False
|
|
highlight = False
|
|
points_scat = None
|
|
labels = []
|
|
|
|
|
|
def update(frame):
|
|
global points_scat, labels
|
|
|
|
if paused:
|
|
return lines + [text]
|
|
|
|
theta = np.radians(frame)
|
|
R_y = rotation_y(theta)
|
|
R_z = rotation_z(theta * 0.7)
|
|
R = R_y @ R_z
|
|
|
|
rotated = cube_points @ R.T
|
|
|
|
# Update edges
|
|
for line, (i1, i2) in zip(lines, edges):
|
|
p1, p2 = rotated[i1], rotated[i2]
|
|
line.set_data([p1[0], p2[0]], [p1[1], p2[1]])
|
|
line.set_3d_properties([p1[2], p2[2]])
|
|
|
|
# Update rotation matrices display
|
|
matrix_str_y = "\n".join(
|
|
["[" + " ".join(f"{val:+.2f}" for val in row) + "]" for row in R_y]
|
|
)
|
|
matrix_str_z = "\n".join(
|
|
["[" + " ".join(f"{val:+.2f}" for val in row) + "]" for row in R_z]
|
|
)
|
|
matrix_str_R = "\n".join(
|
|
["[" + " ".join(f"{val:+.2f}" for val in row) + "]" for row in R]
|
|
)
|
|
|
|
text.set_text(
|
|
f"θ = {np.degrees(theta):6.2f}°\n"
|
|
f"sin(θ) = {np.sin(theta): .3f}\n"
|
|
f"cos(θ) = {np.cos(theta): .3f}\n\n"
|
|
f"R_y(θ):\n{matrix_str_y}\n\n"
|
|
f"R_z(0.7θ):\n{matrix_str_z}\n\n"
|
|
f"R = R_y · R_z:\n{matrix_str_R}"
|
|
)
|
|
|
|
# Always show vertex points and labels
|
|
if points_scat is None:
|
|
points_scat = ax.scatter([], [], [], color='blue', s=40)
|
|
|
|
points_scat._offsets3d = (
|
|
rotated[:, 0], rotated[:, 1], rotated[:, 2]
|
|
)
|
|
|
|
for label in labels:
|
|
label.remove()
|
|
labels.clear()
|
|
|
|
for i, p in enumerate(rotated):
|
|
labels.append(ax.text(p[0], p[1], p[2], f"P{i}",
|
|
color='black', fontsize=8))
|
|
|
|
return lines + [text]
|
|
|
|
|
|
|
|
axpause = plt.axes([0.4, 0.02, 0.3, 0.05])
|
|
bpause = Button(axpause, 'Pause / Resume')
|
|
|
|
|
|
def toggle_pause(event):
|
|
global paused
|
|
paused = not paused
|
|
|
|
|
|
def toggle_highlight(event):
|
|
global highlight
|
|
highlight = not highlight
|
|
|
|
|
|
bpause.on_clicked(toggle_pause)
|
|
|
|
ani = FuncAnimation(
|
|
fig, update, frames=np.arange(0, 360, 2),
|
|
interval=50, blit=False
|
|
)
|
|
|
|
plt.show()
|