fourier_series.py
1# -*- coding: utf-8 -*-2from manim import *3import numpy as np4 5class FourierSeriesVisualization(Scene):6 def construct(self):7 # 设置默认字体8 Text.set_default(font="SimSun")9 10 # 标题11 title = Text("傅立叶级数逼近").scale(0.8)12 title.to_edge(UP, buff=0.3)13 self.play(Write(title))14 self.wait(1)15 16 # 创建坐标系17 axes = Axes(18 x_range=[-4, 4, 1],19 y_range=[-2, 2, 1],20 axis_config={"include_tip": True},21 x_length=10,22 y_length=623 ).scale(0.8)24 axes.shift(DOWN * 0.5 + LEFT * 3) # 更多的左移25 26 # 添加坐标轴标签27 x_label = Text("x").scale(0.6)28 y_label = Text("y").scale(0.6)29 x_label.next_to(axes.x_axis, RIGHT)30 y_label.next_to(axes.y_axis, UP)31 32 axes_group = VGroup(axes, x_label, y_label)33 self.play(Create(axes_group))34 35 # 先显示原函数表达式36 function_text = VGroup(37 Text("原函数:", font="SimSun").scale(0.5),38 MathTex(39 r"f(x) = \begin{cases} 1, & 0 \leq x < \pi \\ -1, & -\pi \leq x < 0 \end{cases}"40 ).scale(0.5)41 ).arrange(RIGHT, buff=0.3)42 function_text.to_corner(UL, buff=0.8)43 self.play(Write(function_text))44 self.wait(1)45 46 # 定义方波函数47 def square_wave(x):48 return np.where(np.sin(x) >= 0, 1, -1) # 恢复原来的方波函数定义49 50 # 定义傅立叶级数部分和函数51 def get_fourier_series(x, n):52 result = 053 for k in range(1, n+1, 2):54 result += 4/(k*np.pi) * np.sin(k*x)55 return result56 57 # 显示原函数图像58 original = axes.plot(59 square_wave,60 color=BLUE,61 x_range=[-4, 4, 0.01] # 移除discontinuities和dt参数62 )63 original_label = Text("原函数", font="SimSun", color=BLUE).scale(0.5)64 original_label.next_to(original.point_from_proportion(0.8), UP)65 66 self.play(67 Create(original),68 Write(original_label)69 )70 self.wait(1)71 72 # 显示傅立叶级数表达式73 final_series = VGroup(74 Text("傅立叶级数展开:", font="SimSun").scale(0.5),75 MathTex(76 r"f(x) = \frac{4}{\pi} \sum_{n=1,3,5,\cdots}^{\infty} \frac{\sin(nx)}{n}"77 ).scale(0.5)78 ).arrange(RIGHT, buff=0.3)79 final_series.to_corner(UR, buff=0.8)80 self.play(Write(final_series))81 self.wait(1)82 83 # 显示部分和表达式84 fourier_terms = VGroup(85 MathTex(r"S_1(x) = \frac{4}{\pi} \sin(x)", color=RED),86 MathTex(r"S_3(x) = \frac{4}{\pi} (\sin(x) + \frac{1}{3}\sin(3x))", color=GREEN),87 MathTex(r"S_5(x) = \frac{4}{\pi} (\sin(x) + \frac{1}{3}\sin(3x) + \frac{1}{5}\sin(5x))", color=YELLOW),88 MathTex(r"S_9(x) = \frac{4}{\pi} (\sin(x) + \frac{1}{3}\sin(3x) + \cdots + \frac{1}{9}\sin(9x))", color=PURPLE),89 MathTex(r"S_{15}(x) = \frac{4}{\pi} (\sin(x) + \frac{1}{3}\sin(3x) + \cdots + \frac{1}{15}\sin(15x))", color=WHITE),90 MathTex(r"S_{23}(x) = \frac{4}{\pi} (\sin(x) + \frac{1}{3}\sin(3x) + \cdots + \frac{1}{23}\sin(23x))", color=ORANGE)91 ).scale(0.4).arrange(DOWN, aligned_edge=LEFT, buff=0.2)92 93 # 调整部分和位置到右上角,并向右移动更多以避免重叠94 fourier_terms.next_to(final_series, DOWN, buff=0.3)95 fourier_terms.shift(RIGHT * 1) # 向右移动更多以避免重叠96 97 # 绘制不同阶数的傅立叶级数98 colors = [RED, GREEN, YELLOW, PURPLE, WHITE, ORANGE]99 approximations = []100 labels = []101 102 for i, n in enumerate([1, 3, 5, 9, 15, 23]):103 # 绘制第n项逼近104 approx = axes.plot(105 lambda x: get_fourier_series(x, n),106 color=colors[i],107 x_range=[-4, 4, 0.01]108 )109 approximations.append(approx)110 111 # 添加标签112 label = MathTex(f"n = {n}", color=colors[i]).scale(0.5)113 label.next_to(approx.point_from_proportion(0.6), UP + RIGHT) # 向右偏移114 labels.append(label)115 116 if i == 0:117 self.play(118 Create(approx),119 Write(label),120 Write(fourier_terms[0]) # 显示第一项121 )122 else:123 self.play(124 ReplacementTransform(approximations[i-1], approx),125 ReplacementTransform(labels[i-1], label),126 Write(fourier_terms[i]) # 显示新的展开式127 )128 self.wait(0.5)129 130 # 添加说明文字131 explanation = Text(132 "随着项数增加,傅立叶级数逐渐逼近原函数",133 font="SimSun"134 ).scale(0.5)135 explanation.next_to(axes, DOWN, buff=0.5)136 137 self.play(Write(explanation))138 self.wait(2)139 140def main():141 scene = FourierSeriesVisualization()142 scene.render()143 144if __name__ == "__main__":145 main() 讲解
这个视频围绕「傅立叶级数逼近」展开。画面把问题、图像和公式放在同一条理解路径中,让抽象关系先被看见。
开头先建立问题背景和主要对象,让观察从标题、坐标或第一组关系进入。
画面中出现的文字「傅立叶级数逼近」给出视觉入口。随后画面通过对象创建、移动、淡入淡出和高亮,把抽象命题拆成可以跟随的步骤。
随后出现更具体的图像或公式提示,动画会把局部对象和整体结论联系起来。这里可以重点观察变量、曲线、区域或向量如何随镜头推进而变化。
核心公式可以写成:
这类公式可以和画面中的符号一一对应。
观察路径
观察路径可以分三步:先锁定「傅立叶级数逼近」中的核心对象,尤其留意傅立叶级数、函数逼近、波形叠加之间的联系;再跟随画面中变量、图像或向量的变化;最后回到公式或结论,判断局部变化如何支撑整体关系。
本页可以从傅立叶级数、函数逼近、波形叠加这些概念进入,继续沿相邻问题观察同一类数学结构。