圣诞长假,把玩了一下分形绘图。我的初衷是想找点简单好玩漂亮的东西,以后用来哄骗小女儿学习数学和计算机。于是我找到了Kojo,一个用Scala来模拟Logo语言的小玩具,让我想起了小时候玩分形绘图的零星记忆。然后在网上东找西寻,终于让我找到了Apophysis 7X这个好东东。结果一发不可收拾,耗进去好几天。下面是这几天的一些学习心得。
什么是分形绘图
跑去网上某百科查“分形”,如果不是搞数学的话,基本上会不知所云。什么“分数维”,“混沌吸引子”之类的概念只能把你的小脑瓜变成大脑瓜。好在我们这些搞业余艺术的人不用去扯这些技术细节,其实只要知道,分形绘图就是“递归的几何”,就够了。如果你还想了解一些细节,可以继续阅读本节。如果你只想尽快开始作画,完全可以跳过本文。
下面用Kojo和一个经典的分形雪花图(Von Koch曲线)来说明什么是分形图案。
首先去 http://www.kogics.net/kojo-download 下载一个Kojo并安装。顺带一提,如果想哄小孩子学编程,这应该是个好东东,现在已经很难找到做得这么细致的Logo语言实现了,虽然是用Scala仿的。
Ok,现在运行Kojo,把下面代码复制到Script Editor中:
def lines(count: Int, length: Int) {
if (count == 1) forward(length) //前进length步
else {
lines(count-1, length)
left(60) //左转60度
lines(count-1, length)
right(120) //右转120度
lines(count-1, length)
left(60) //左转60度
lines(count-1, length)
}
}
clear() //清屏
setPenThickness(1) //画笔宽度设为1
setPenColor(color(128, 128, 128)) //设置画笔颜色
setAnimationDelay(300) //海龟每个动作的延迟(让我们这些小朋友可以看得清)
visible() //显示小海龟
right(90) //右转90度
//修改下面这行
lines(2, 5)
invisible() //隐藏小海龟
这段代码是什么意思呢?我们看到Turtle Canvas上有一只小海龟,这段程序就是用来控制这只小海龟移动进行作画的(嗯,很幼稚,小孩子的玩具嘛)
其中的lines是个递归函数,如果count是1的时候,就画一段长度为length的直线。如果大于1,则分别递归调用自己4次,分别转3次弯。
现在来看count=2时的结果:
这个图案由4条直线加3个转弯组成。
count=3时 ( 把line(2, 5)这行改成line(3, 5) )
可以看出,这个图案是4个count=2时的图案再加3次转弯组成。
同理,count=4时,得到这个图案:
如此类推,通过对简单的图形进行递归,就能构造出非常复杂的图案来。这种图形的局部其实就是整体的一个复制,可能再加上一些变换,例如在这个简单的例子中,每个局部都稍微比整体简单(count少1)。用术语来说,叫做“自相似”。而这种带有“自相似”性质的图案,就是所谓的分形图案了。
最后,我们来完成这个例子:
把原来程序中的line(2, 5)改为
lines(5, 5)
right(120)
lines(5, 5)
right(120)
lines(5, 5)
也就是,转两个弯,把3段lines(5,5)图像串起来,运行就得到了传说中雪花
附完整脚本:
def lines(count: Int, length: Int) {
if (count == 1) forward(length)
else {
lines(count-1, length)
left(60)
lines(count-1, length)
right(120)
lines(count-1, length)
left(60)
lines(count-1, length)
}
}
clear()
visible()
setPenThickness(1) //设定画笔宽度
setPenColor(color(128, 128, 128)) //设定画笔颜色
setAnimationDelay(300) //设定动画延迟(让你看到小海龟在跑)
right(90)
//修改此处
lines(5, 5)
right(120)
lines(5, 5)
right(120)
lines(5, 5)
invisible() //隐藏海龟
最后简单看一下另一段脚本 (Kojo自带示例):
def tree(distance: Double) {
if (distance > 4) {
setPenThickness(distance/7)
setPenColor(color(distance.toInt, math.abs(255-distance*3).toInt, 125))
forward(distance)
right(25)
tree(distance*0.8-2)
left(45)
tree(distance-10)
right(20)
back(distance)
}
}
clear()
invisible()
setAnimationDelay(10)
penUp()
back(200)
penDown()
tree(90)
运行结果是:
而这棵分形树是由多个
组成的。
当然,本文说的都是一些哄小孩用的简单例子,但也基本上说明了什么是分形图。下一篇开始就开始动真格了。
下一篇
分形绘图简介(二) Apophysis 7X登场