图形学的分支:分形
分形,简单的来说就是自相似所产生的漂亮图形,能无穷放大并且保持性质不变最简单的例子是旋涡:
不过说到分形,先要从Mandelbrot Set说起
曼德布洛特集合(Mandelbrot set)是在复平面上组成分形的点的集合。
Mandelbrot集合由复二次多项式f(z)=z^2+c来定义。
其中c是一个复常数。对于每一个c,从z=0开始对f(z)进行迭代
序列 (0, f(0), f(f(0)), f(f(f(0))), .......)的值或者延伸到无限大,或者只停留在有限半径的圆盘内。
曼德布洛特集合就是使以上序列不延伸至无限大的所有c点的集合。
从数学上来讲,曼德布洛特集合是一个复数的集合。一个给定的复数c或者属于曼德布洛特集合M,或者不是。
最后,根据常数c令多项式的敛散性不同,在平面上用不同的颜色标注,便可以以形象的方式把这个集合绘画出来
曼德布洛特集:
此图如果把它的局部放大,你会发现它是自相似的,以下是放大过程:
好了,现在我们也来用C来画出这个集合。
首先,我们要定义复数:
typedef struct COMPLEX
{
double re; //实部
double im; //虚部
} COMPLEX;
然后,我们只需要用到加法和乘法:
COMPLEX mul (const COMPLEX a, const COMPLEX b)
{
COMPLEX c;
c.re = a.re * b.re - a.im * b.im;
c.im = a.im * b.re + a.re * b.im;
return c;
}
COMPLEX add (const COMPLEX a, const COMPLEX b)
{
COMPLEX c;
c.re = a.re + b.re;
c.im = a.im + b.im;
return c;
}
复数定义好了以后,我们要开始写计算部分了
我们假设输出窗口大小是640 * 480
那么就需要一个二重循环:
int x, y;
for(y=0; y<480; y++)
{
for(x=0; x<640; x++)
{
// 这里为计算部分
}
}
然后,你的(x,y)要映射到一个实数,比如你x的范围为-2.0到2.0
那么任意x实际对应的实数是 -2.0 + (2.0 - (-2.0)) / 640 * x
所以这个二重循环里面补上映射计算后的代码为:
int x, y;
for(y=0; y<480; y++)
{
for(x=0; x<640; x++)
{
COMPLEX c;
c.re = -2.0 + (2.0 - (-2.0)) / 640 * x;
c.im = -1.5 + (1.5 - (-1.5)) / 480 * y;
// 这里开始为计算部分
}
}
这样,我们就算出了所需要的c,然后,根据公式,我们写一个函数来迭代,返回迭代结果:
int f(COMPLEX c)
{
COMPLEX z = {0, 0}; //初始化为0
int maxcalc = 100; //最大迭代次数
while (--maxcalc)
{
z = mul(z, z);
z = add(z, c);
if ( z.re*z.re + z.im*z.im > 4.0 ) break; //其模超过4,肯定发散,跳出
}
return maxcalc>0; //如果maxcalc>0说明没迭代完就越了界,否则就在集合内
}
最后,剩下的事情就简单了,只要补充上我们的主循环体:
int x, y;
for(y=0; y<480; y++)
{
for(x=0; x<640; x++)
{
COMPLEX c;
c.re = -2.0 + (2.0 - (-2.0)) / 640 * x;
c.im = -1.5 + (1.5 - (-1.5)) / 480 * y;
if (f(c)) putpixel(x, y, BLACK);
else putpixel(x, y, WHITE);
}
}
好了,最简单的显示版本做好了,
以下为完整源代码(如果你要编译测试,请直接下载附件中整个工程的压缩包):
MandelbrotDemo.rar
(212.97 KB)
#include "graphics.h"
//定义复数结构
typedef struct COMPLEX
{
double re; //实部
double im; //虚部
} COMPLEX;
//定义复数乘法
COMPLEX mul (const COMPLEX a, const COMPLEX b)
{
COMPLEX c;
c.re = a.re * b.re - a.im * b.im;
c.im = a.im * b.re + a.re * b.im;
return c;
}
//定义复数加法
COMPLEX add (const COMPLEX a, const COMPLEX b)
{
COMPLEX c;
c.re = a.re + b.re;
c.im = a.im + b.im;
return c;
}
int f(COMPLEX c)
{
COMPLEX z = {0, 0}; //初始化为0
int maxcalc = 100; //最大迭代次数
while (--maxcalc)
{
z = mul(z, z);
z = add(z, c);
if ( z.re*z.re + z.im*z.im > 4.0 ) break; //其模超过4,肯定发散,跳出
}
return maxcalc>0; //如果maxcalc>0说明没迭代完就越了界,否则就在集合内
}
int main()
{
initgraph(640, 480);
{
int x, y;
for(y=0; y<480; y++)
{
for(x=0; x<640; x++)
{
COMPLEX c;
c.re = -2.0 + (2.0 - (-2.0)) / 640 * x;
c.im = -1.5 + (1.5 - (-1.5)) / 480 * y;
if (f(c)) putpixel(x, y, BLACK);
else putpixel(x, y, WHITE);
}
}
}
getch();
closegraph();
return 0;
}
未完待续,匆回复。。。