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.

116 lines
4.3 KiB

6 months ago
from manim import *
class PythagoreanProof(Scene):
def construct(self):
# 场景1问题引入
# 创建直角三角形
tri = Polygon([-2, -1, 0], [1, -1, 0], [-2, 2, 0], color=WHITE)
labels = VGroup(
Tex("a", color=RED).next_to(tri.get_vertices()[1], DOWN),
Tex("b", color=BLUE).next_to(tri.get_vertices()[2], LEFT),
Tex("c", color=GREEN).next_to(tri.get_midpoint(), UR, buff=0.3)
)
self.play(Create(tri), run_time=2)
self.play(Write(labels), run_time=1.5)
# 显示平方表达式
equation = VGroup(
Tex("a^2 + b^2 = ?", color=RED_B).shift(UP * 2),
Tex("c^2 = ?", color=GREEN_B).shift(DOWN * 2)
)
arrows = VGroup(
Arrow(equation[0].get_bottom(), labels[0].get_center() + DOWN * 0.5, color=RED),
Arrow(equation[0].get_bottom(), labels[1].get_center() + LEFT * 0.5, color=BLUE),
Arrow(equation[1].get_top(), labels[2].get_center() + UR * 0.3, color=GREEN)
)
self.play(Write(equation), run_time=1.5)
self.play(LaggedStart(*[GrowArrow(a) for a in arrows]), run_time=2)
self.wait(1)
# 场景2构造辅助图形
# 创建三个正方形
square_a = Square(side_length=2, color=RED).next_to(tri, LEFT, buff=0)
square_b = Square(side_length=3, color=BLUE).next_to(tri, DOWN, buff=0)
square_c = Square(side_length=np.sqrt(13), color=GREEN).rotate(np.arctan(3 / 2)).next_to(tri, UR, buff=0)
for s, t in zip([square_a, square_b, square_c], ["a^2", "b^2", "c^2"]):
s.set_fill(opacity=0.2)
self.play(Create(s), Write(Tex(t).move_to(s.get_center())), run_time=1.5)
# 镜头聚焦
self.play(
self.camera.frame.animate.set_width(square_a.width * 3).move_to(VGroup(square_a, square_b)),
run_time=2
)
# 场景3图形重组动画
# 切割正方形为三角形
triangles = VGroup()
for square in [square_a, square_b]:
points = square.get_vertices()
tri1 = Polygon(points[0], points[1], points[3], color=RED if square == square_a else BLUE)
tri2 = Polygon(points[1], points[2], points[3], color=RED if square == square_a else BLUE)
triangles.add(tri1, tri2)
# 动画重组
self.play(LaggedStart(*[tri.animate.rotate(PI / 2).shift(UR * 2) for tri in triangles]),
run_time=3, rate_func=smooth)
# 拼合新正方形
new_square = Square(color=GREEN).surround(triangles)
self.play(Transform(VGroup(triangles), new_square), run_time=2)
# 场景4面积等价证明
# 并排对比
original = VGroup(tri.copy(), square_a.copy(), square_b.copy()).scale(0.5).to_edge(LEFT)
transformed = VGroup(new_square.copy(), square_c.copy()).scale(0.5).to_edge(RIGHT)
self.play(
FadeOut(arrows),
Transform(VGroup(tri, square_a, square_b), original),
Transform(VGroup(triangles, square_c), transformed),
run_time=2
)
# 显示等式
final_eq = Tex(r"a^2 + b^2 = c^2", color=YELLOW).scale(2)
self.play(
Write(final_eq),
final_eq.animate.shift(UP * 1.5),
self.camera.frame.animate.move_to(final_eq),
run_time=2
)
# 粒子特效
self.add(final_eq)
self.play(
final_eq.animate.scale(1.5).set_color_by_gradient(RED, BLUE, GREEN),
rate_func=there_and_back,
run_time=3
)
# 三维旋转需启用ThreeDScene
self.play(
final_eq.animate.rotate(30 * DEGREES, axis=UP),
run_time=2,
rate_func=smooth
)
self.wait(3)
if __name__ == "__main__":
config = {
"quality": "high_quality",
"preview": True,
"media_dir": "./output",
"pixel_height": 1080,
"pixel_width": 1920,
"background_color": "#333333", # 深色背景
"format": "png" # 解决部分系统渲染问题
}
with tempconfig(config):
scene = PythagoreanProof()
scene.render()