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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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()