前言:

最近在【编程德鲁伊】的【傅里叶级数可视化】章节中,练习了傅里叶级数基础原理的可视化,演示了周期方波曲线,可以分解为一系列正弦波曲线:

这次拿学到的知识做个实验,试试喜闻乐的【用傅里叶级数画画】,并尽可能简单直观的解释一下原理。

自认为简单直观的原理解释

之前练习的可视化,都是在二维空间进行,例如正弦波:

方波(通过傅里叶级数):

图中左半边的圆周(Epicycle)和右半边正弦波/方波的关系:左半边是一个运动点,在一个圆周或多个圆周组合上随着时间t动;

右半边,是将时间t映射到横轴x轴上,纵轴仍是运动点当前的y值保持不变。

也就是说,把时间域换为空间域,就能从一个圆周得到正弦曲线,或者从一系列圆周组合,得到方波曲线。

我们把方波可视化左右两边的运动点轨迹也画出来:

左半边由一系列圆周(Epicycle)组成的轨迹,与右半边的方波(Square)轨迹,其实只是同一个运动点在不同空间里的展现方式而已。

豁然开朗有没有!!!(此处插入打赏掌声!)

为了说的更清楚一些,接下来把空间域从二维换到三维,时间t不再映射到x轴,而是映射到z轴上:

上图从正面看过去,仍是一个圆周,而在三维空间里旋坐标轴,从侧面看过去时,它实际上就是一个正弦曲线。

方波的也一样:

正面的橙色轨迹,换角度,从侧面看,就是方波的曲线。

再次豁然开朗有没有!!!

进一步,根据傅里叶级数原理,为了得到方波(橙色),就要想办法得到组成方波的一系列正弦波(金黄色):

换一个视角,为了得到最终的运动轨迹(橙色),就要想办法得到组成轨迹的一系列Epicycle圆周(金黄色):

而这个橙色的运动轨迹,可以是各种形状,也就是说,无论想画什么图形,只要按照傅里叶级数的原理,找到一系列Epicycle圆周,就可以画出来了!

金猪报喜

傅里叶本尊

怎么样,这样去理解傅里叶级数画画的原理,是不是容易了一些?

接下来要解决的,就是如何为“任意”图案找到对应的一组Epicycle圆周的问题。

从数学上讲,就是求傅里叶级数里每个子项对应的傅里叶系数(a和b):

各项系数a和b都找到后,合起来就可以得到f(x)。

求傅里叶系数的方法有很多,积分、傅里叶变换等。

详细的原理推导,我还没有复习重修,所以对于如何把大象装冰箱的回答,仍然是:

1.打开冰箱门;2.把大象装进去;3.关门。

直接对图案轨迹进行傅里叶变换,即可得到傅里叶系数。

而在计算机程序里,所有的数据都是离散的,所以实际上程序里用的是离散傅里叶变换。

关于这个环节,考资源较多,尤其是用Web前端/JavaScript/p5.js做的不少,列在后面。

本文的配图和动画,是用 Blender + Python 完成:

等等老乡,还没完。

从上图里傅里叶的配色就能看出,我其实原本是打算画 Miku 酱的(初音未来):

然而码到用时方恨不会,关于傅里叶画画这个问题,其实更难的是找到合适的图案轨迹,并不是随便一个图都能轻松画出来的,这也是为什么上文中,我给任意图案的“任意”两字了引

从数学上讲,在一些特定条件的约束下,一个函数才能用傅里叶级数来表达。

而找出这个图案轨迹的过程,复杂度远超用傅里叶级数画轨迹本身。

本文投入的精力仅能画简单的轨迹线,所以Miku就换成了傅里叶他老人家 :

最终效果(三个视角):

绝大部分开源在这里:

https://github.com/avantcontra/coding-druid