利用函数来画任意图形
最近我们经常看到像鸟叔,初音之类的通过函数图像来画出来,看上去十分神奇的样子,wolframalpha这里有大量的通过函数图像来画人物的例子,大家可以去围观,而且最上面我这几个字也是我用函数图像画出来的,今天我们就说说这是怎么做到的。
首先我画的图形的函数是这个样子的:
如果像我们这里只用cos和sin的话,我们可以画出任意我们想画的闭合曲线,至于其他图像那样包含很多闭合曲线的是用了step function的技巧,这里我就暂时不说了,也就说我这里是说明如何画出任意的闭合曲线的。当然了也就是说只要你能一笔画的东西都可以,线当然是可以交叉或者重合的。
因为我们是要画闭合曲线,并且注意到我们的函数最后是x(t)和y(t)这种形式,所以也就是说,我们可以把x和y分别当作是周期函数来对待,说道周期函数当然就是想到傅里叶级数了,因为傅里叶级数可以逼近任意的周期函数。所以这里我们就要用到DFT离散傅立叶变换。
我们这里就要用到离散傅里叶变换和逆变换的公式:
也就是说我们可以把我们想要画的图形画出来,然后依次找出我们要连接的这些点,这些点就是x[n],带入到上面的第一个公式,我们可以得到x[k],于是再调用第二个公式也就是离散傅里叶的逆变换,最后利用欧拉公式把e^ix=cosx+isinx展开,就能得到我们最后的函数形式了。
按照这个思路实现的python代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
import
math
N
=
int
(
raw_input
())
f
=
[]
for
i
in
range
(N):
(x, y)
=
map
(
float
,
raw_input
().split())
f.append(
complex
(x, y))
F
=
[]
for
i
in
range
(N):
ang
=
-
2
*
1j
*
math.pi
*
i
/
N
r
=
0
for
j
in
range
(N):
r
+
=
(math.e
*
*
(ang
*
j))
*
f[j]
F.append(r)
print
"set parametric"
print
"set samples"
, N
+
1
print
"x(t)="
,
for
i
in
range
(N):
ang
=
2
*
math.pi
*
i
/
N
if
i >
0
:
print
"+"
,
print
F[i].real
/
N,
"*cos("
, ang,
"*t)-"
,
print
F[i].imag
/
N,
"*sin("
, ang,
"*t)"
,
print
print
"y(t)="
,
for
i
in
range
(N):
ang
=
2
*
math.pi
*
i
/
N
if
i >
0
:
print
"+"
,
print
F[i].imag
/
N,
"*cos("
, ang,
"*t)+"
,
print
F[i].real
/
N,
"*sin("
, ang,
"*t)"
,
print
print
"plot [t=0:"
, N,
"] x(t), y(t)"
print
"pause 60"
|
也可以在这里看代码,把代码存成dft.py然后运行python dft.py输入点的个数以及点的位置,运行程序就可以看到生成的函数了,把结果输入到gnuplotli就可以看到函数图像了。
比如我生成的那个函数图像的输入是这个样子的:
可以把输入文件保存到input.txt,然后运行cat input.txt | python dft.py | gnuplot就可以看到绘制好的函数了。
也就是说只要把你要画的东西的点描绘出来,输入到程序中就可以生成不可思议的函数了!
参考资料:
http://mathematica.stackexchange.com/questions/17704/how-to-create-new-person-curve
http://tieba.baidu.com/p/2156093774
http://www.quora.com/Mathematics/How-is-the-Gangnam-Style-mathematical-plot-made
原文链接:isnowfy