前言:
最近在【编程德鲁伊】的【傅里叶级数可视化】章节中,练习了傅里叶级数基础原理的可视化,演示了周期方波曲线,可以分解为一系列正弦波曲线:
这次拿学到的知识做个实验,试试喜闻乐见的【用傅里叶级数画画】,并尽可能简单直观的解释一下原理。
自认为简单直观的原理解释
之前练习的可视化,都是在二维空间进行,例如正弦波:
方波(通过傅里叶级数):
图中左半边的圆周(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