0 说明
希望大家都有所收获,能手执傅里叶画笔,写了这篇文稿,由于时间和精力有限采用文本形式
个人对傅里叶级数展开的绘图与原理的简单理解,希望能有所收获
文稿写的可能不够完善,比较粗糙,欢迎批评指正
拜读了 3Blue1Brown 和 [OUTDATED] ManimCairo tutorial - Fourier Scene - YouTube 视频相关大佬给出的相关程序,是基于 ManimCairo,我对其进行了简单的适配,适配到社区版的 ManimCE
原程序:
https://gitlab.com/zavden/manim-backup/-/raw/master/fourier.py
svg文件:music_svg - Google 云端硬盘
适配后的程序(含原程序):
https://github.com/JermainLiu/Manim_Fourier
链接到:
当傅里叶拿起画笔——manim_fourier 程序分享、、、哔哩哔哩bilibili
1 傅里叶级数展开
1.1 狄利赫里条件
对于周期信号:
(1) 在一个周期内,如果有间断点,则间断点的数目应该为有限个;
(2) 在一个周期内,极大值和极小值的数目应是有限个;
(3) 在一个周期内,信号是绝对可积的。
1.2 傅里叶级数展开
满足狄利赫里条件的周期函数可以展开成傅里叶级数形式
对于有限区间(时域有限)函数(信号)可以通过周期延拓得到周期函数,展开为傅里叶级数
周期为$T_1$函数 $f(t)$展开成傅里叶级数指数形式,如下
\begin{align}
f(t) & = \sum_{n=-\infty}^{\infty} {F_n e^{jnw_1t}} \quad 其中 \, w_1 = \frac{2\pi}{T_1} \, 为基波频率 \\
& = \sum_{n=-\infty}^{\infty} {F_n e^{jw_nt}} \quad 其中 \, w_n =nw_1 为 \, n 次谐波频率
\end{align}
$$
傅里叶级数系数 $F_n$ 计算公式:
F_n = \frac{1}{T_1} \int_{T_1}{f(t)e^{-jw_n t}} \, {\rm d}t
$$
当 $T_1 = 1 $ 时,
\left\{
\begin{array}{c}
f(t) = \sum_{n=-\infty}^{\infty} {F_n e^{jn2\pi t}} \\
F_n = \int_{0}^{1}{f(t)e^{-jn2\pi t}} \, {\rm d}t
\end{array}
\right.
$$
2 复数系引入
当我们把一个矢量图像放到直角坐标系中,点 $(x,y)$ 的轨迹显然无法写出显性函数 $y=f(x) $
然而我们可以想象一下,我们自己描图的时候怎样进行的,定义第一笔为时刻 $t = 0$,笔尖落在了开头位置,随着时刻的变化,笔尖的位置不断变化,最终在 $t=1$ 时笔尖落地到轨迹的末端,于是我们得到一个映射
t \overset{\quad f \quad }{\to} (x_t, y_t) \quad t \in [0,1]
$$
也即点的位置是 $t$ 的一元函数,那么我们需要一种方式来表达点的位置关系,于是我们引入复数系来解决这个问题
通过下列欧拉公式将点的直角坐标与复数坐标联系
x(t)+jy(t) = r(t)e^{j\theta(t)} = r(t)\cdot\cos(\theta(t))+jr(t)\cdot\sin(\theta(t))
$$
其中
r(t) \, 表示点到原点的距离,\theta(t) \, 表示该点的向量与实轴的夹角
$$
于是我们有了复数函数
f(t) = r(t)e^{j\theta(t)} \quad t \in [0,1]
$$
那么我们将 $f(t)$ 进行周期 $T_1=1$ 延拓,便可将 $f(t)$ 展开成傅里叶级数,可求得傅里叶级数系数 $F_n$
\begin{align}
f(t) & = \sum_{n=-\infty}^{\infty} {F_n e^{jn\pi t}} \\
& = \cdots + F_{-n}e^{-jw_nt} + \cdots + F_{-2}e^{-jw_2t}+F_{-1}e^{-jw_1t}+ F_0 + F_{1}e^{jw_1t} + F_{2}e^{jw_2t} + \cdots + F_{n}e^{jw_nt} + \cdots
\end{align}
$$
我们分别看各个分量的情况,以 $n=2, \; F_2e^{jw_2t}$为例
F_2e^{jw_2t} = re^{j\theta}e^{jw_2t}=re^{j(\theta + w_2t)}
$$
其中傅里叶级数的系数 $F_2=re^{j\theta}$ 为一个复数的定值,$e^{jw_2t}$ 只改变整体的相位,而不改变幅度,于是随着 $t$ 的连续变化,整体向量将会绕着自身的起点进行旋转
两个向量相加,三个相加,四个相加......相当于将向量进行首位依次相接
而把 $n=0$ 作为第一个向量,其相位始终为0,故是固定不动的
3 傅里叶展开系数的求解
在之前我们已经介绍了傅里叶级数展开系数为
F_n = \int_{0}^{1}{f(t)e^{-jw_n t}} \, {\rm d}t \quad 当 T_1 = 1时
$$
定积分定义,函数在区间 $[0,1]$ 上的积分为
\int_{0}^{1}{h(t)} \, {\rm d}t = \lim_{m\to \infty}{\sum_{i=0}^{m-1}{h(\frac{i}{m}) \, \frac{1}{m}}}
$$
故
\begin{align}
F_n & = \lim_{m\to \infty}{\sum_{i=0}^{m-1}{f(\frac{i}{m}) \; e^{-jw_n \frac{i}{m}} \, \frac{1}{m}}} \\
& \approx \sum_{i=0}^{m-1}{f(\frac{i}{m}) \; e^{-jw_n \frac{i}{m}} \, \frac{1}{m}} \\
& = \sum_{i=0}^{m-1}{f(i\Delta{t}) \; e^{-jw_n\Delta{t} } \, }\quad 其中\, \Delta{t}=\frac{1}{m}
\end{align}
$$
取 $m=10000$ ,对 $f(t)$ 在 $t\in [0,1]$ 进行均匀采样取值,根据上式进行计算近似得到 $F_n$ ,我们取有限次谐波频率,带入到傅里叶级数展开式中得到 $f(t)$ 的近似值
4 程序中一些参数
当 $T_1 = 1 $ 时,
\left\{
\begin{array}{c}
f(t) = \sum_{n=-\infty}^{\infty} {F_n e^{jn2\pi t}} \\
F_n = \int_{0}^{1}{f(t)e^{-jn2\pi t}} \, {\rm d}t
\end{array}
\right.
$$
n_vectors
:取谐波频率的个数,决定傅里叶级数中的 $n$ ,取 $n\in [\frac{-n\_vectors}{2}, \frac{n\_vectors}{2}]$ 的整数
slow_factor
:速度因子,决定绘制一周的时间为 $\frac{1}{slow\_factor}$
start_drawn
:是否需要提前绘制好路径
interpolate_config
:默认值为 $[0,1]$ ,设置当前傅里叶画笔点与之前路径线的粗细比例,渐变设置
n_cycles 、 run_time
:均用于设置运行的时间,分别表示 绘制图像的周数和运行时间,其默认值分别为 None
和 10
,在适配的程序中,设置了 n_cycles
取较高的优先级,同时设置时,采用 n_cycles
wait_before_start
:绘制前的等待时间
center_point
:设置绘图的向量第一个向量的起点位置