You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
140 lines
4.5 KiB
140 lines
4.5 KiB
from manim import *
|
|
import numpy as np
|
|
|
|
|
|
class PythagoreanProof(Scene):
|
|
def construct(self):
|
|
self.show_title()
|
|
self.show_triangle()
|
|
self.create_squares()
|
|
self.transform_shapes()
|
|
self.show_final_equation()
|
|
|
|
def show_title(self):
|
|
"""显示标题"""
|
|
title = Text("勾股定理证明", font_size=48)
|
|
title.set_color_by_gradient(BLUE, GREEN)
|
|
self.play(Write(title))
|
|
self.wait(2)
|
|
self.play(title.animate.to_edge(UP))
|
|
self.title = title
|
|
|
|
def show_triangle(self):
|
|
"""创建初始三角形"""
|
|
# 使用三维坐标定义三角形顶点
|
|
self.A = [-2, -1, 0]
|
|
self.B = [2, -1, 0]
|
|
self.C = [2, 2, 0]
|
|
|
|
self.triangle = Polygon(self.A, self.B, self.C,
|
|
color=WHITE, fill_opacity=0.5)
|
|
self.play(Create(self.triangle), run_time=2)
|
|
|
|
# 添加边标签
|
|
self.label_a = MathTex("a").next_to(self.triangle, LEFT)
|
|
self.label_b = MathTex("b").next_to(self.triangle, DOWN)
|
|
self.label_c = MathTex("c", color=YELLOW).next_to(self.triangle, UR)
|
|
self.play(LaggedStart(
|
|
Write(self.label_a),
|
|
Write(self.label_b),
|
|
Write(self.label_c),
|
|
lag_ratio=0.3
|
|
))
|
|
self.wait()
|
|
|
|
def create_squares(self):
|
|
"""创建三个正方形"""
|
|
# 计算正方形边长
|
|
a_length = np.linalg.norm(np.array(self.B) - np.array(self.A))
|
|
b_length = np.linalg.norm(np.array(self.C) - np.array(self.B))
|
|
c_length = np.linalg.norm(np.array(self.C) - np.array(self.A))
|
|
|
|
# 创建正方形并保存为实例属性
|
|
self.square_a = Square(side_length=a_length, color=RED, fill_opacity=0.3)
|
|
self.square_a.next_to(self.triangle, LEFT)
|
|
|
|
self.square_b = Square(side_length=b_length, color=BLUE, fill_opacity=0.3)
|
|
self.square_b.next_to(self.triangle, DOWN)
|
|
|
|
self.square_c = Square(side_length=c_length, color=GREEN, fill_opacity=0.3)
|
|
self.square_c.rotate(np.arctan2(3, 4)).next_to(self.triangle, UR)
|
|
|
|
# 添加面积标签
|
|
self.area_a = MathTex("a^2").next_to(self.square_a, LEFT)
|
|
self.area_b = MathTex("b^2").next_to(self.square_b, DOWN)
|
|
self.area_c = MathTex("c^2").next_to(self.square_c, UR)
|
|
|
|
# 动画序列
|
|
self.play(
|
|
LaggedStart(
|
|
Create(self.square_a),
|
|
Create(self.square_b),
|
|
Create(self.square_c),
|
|
lag_ratio=0.5
|
|
),
|
|
run_time=3
|
|
)
|
|
self.play(
|
|
Write(self.area_a),
|
|
Write(self.area_b),
|
|
Write(self.area_c)
|
|
)
|
|
self.wait(2)
|
|
|
|
def transform_shapes(self):
|
|
"""形状变换动画"""
|
|
# 分解正方形为三角形
|
|
self.triangles = VGroup()
|
|
for _ in range(4):
|
|
tri = Polygon(self.A, self.B, self.C,
|
|
color=RED, fill_opacity=0.3)
|
|
self.triangles.add(tri)
|
|
|
|
# 定义目标位置(三维坐标)
|
|
target_positions = [
|
|
[3, 2, 0], # 右上
|
|
[-3, 2, 0], # 左上
|
|
[3, -3, 0], # 右下
|
|
[-3, -3, 0] # 左下
|
|
]
|
|
|
|
# 创建动画序列
|
|
animations = []
|
|
for i, pos in enumerate(target_positions):
|
|
anim = self.triangles[i].animate.rotate(PI / 2).move_to(pos)
|
|
animations.append(anim)
|
|
|
|
# 执行动画
|
|
self.play(
|
|
Transform(self.square_a, self.triangles),
|
|
*animations,
|
|
run_time=3
|
|
)
|
|
self.wait()
|
|
|
|
# 创建最终正方形
|
|
final_square = Square(side_length=5, color=GOLD, fill_opacity=0.3)
|
|
self.play(Create(final_square))
|
|
self.wait(2)
|
|
|
|
def show_final_equation(self):
|
|
"""显示最终公式"""
|
|
equation = MathTex("a^2 + b^2 = c^2", color=YELLOW).scale(2)
|
|
equation.set_color_by_gradient(RED, BLUE, GREEN)
|
|
|
|
self.play(
|
|
Write(equation),
|
|
Flash(equation, color=YELLOW, line_length=1),
|
|
run_time=2
|
|
)
|
|
self.wait(3)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
config.background_color = "#1a1a1a"
|
|
config.frame_width = 16
|
|
config.frame_height = 9
|
|
config.pixel_width = 1920
|
|
config.pixel_height = 1080
|
|
scene = PythagoreanProof()
|
|
scene.render() |