前言:
首先先简单介绍一下Mandelbrot集,该集被曼德布罗特教授称之为“魔鬼的聚合物”,也被大家称之为“上帝的指纹”。之所以这么称呼,我想是该集合本身的自相似性及其图像复杂度。然而,如此复杂的图像也只不过是通过一个简单的公式(Z^2 = Z^2 + c)来完成的,当然当年曼德布罗特教授发现这个公式是不容易的。我刚开始接触Mandelbrot集的时候并没有注意到其简单性,只是觉得图像蛮漂亮的,就开始着手了。当时也没有注意到其子集Julia集,最后才发现Julia集与Mandelbrot集是一个公式来的,只是它们的初始条件不同而已。Julia集中,复数c是固定,确切的说是它不随复平面上的坐标变化而变化。而Mandelbrot集中的c是随坐标值改变而改变的。
MandelBrot vs Julia:
下面就切入正题了,刚在前言里也说过Julia集是Mandelbrot集的子集,这也就是说如果把Madelbrot集画出来,再画Julia集就简单多了。Mandelbrot集的图像是一个3:2(这个可以研究一下公式)的图,为了使图像好看些可以按这个比例把它放大,比如说把这个它画在一个600x400的框架中,缩放比例也就是1/200。下面主要是初始化Z^2 = Z^2 + c,c = new Complex((double)x * rate - 2.0,(double)y * rate - 1.0);z = c;然后就是进行公式转化了,即Z^2 = Z^2 + c,直达达到迭代次数或者复数z的模长大于2采跳出循环。迭代次数其实就是放大比例,次数越多放大效果越好,看的也越精细,也会体现出它的自相似。之所以要以模长为2为界限,这个就需要自己研究一下公式了。跳出循环时,如果达到迭代次数就是Mandelbrot集里的,不然就不是了。这样我们就可也找出框架里的点那些是Mandelbrot集里的,那些不是了,说到这里Mandelbrot集也就差不多出来了。下面给出一小段关于画Mandelbrot的代码:
for (int x = 0; x < 600; x++) {
for (int y = 0; y < 400; y++) {
interation = 0;
c = new Complex((double)x * rate - 2.0,(double)y * rate - 1.0);
z = c.add(new Complex(0.0,0.0));
//计算模长
length = Math.sqrt(z.re * z.re + z.im * z.im);
//判断是否在set内
while (length <= 2 && interation < maxInteration) {
//Mandelbrot集
z = z.multiply(z);
z = z.add(c);
//计算模长
length = Math.sqrt(z.re * z.re + z.im * z.im);
interation++;
}
//如果在set内
if (interation == maxInteration) {
g.setColor(Color.BLACK);
g.drawLine(x, y + 5, x, y + 5);
}else {//如果不在set内
g.setColor(advocate(interation));
g.drawLine(x, y + 5, x, y + 5);
}
}
}
相信画Mandelbrot集已经很简单了,下面开始画Julia集了。
刚才也说过如果已经画出Mandelbrot集,那么Julia集就不用费吹灰之力了。给窗体添加一个鼠标监听器,获取坐标,然后根据坐标就可以得到c了,即c = new Complex((double)x * rate - 2.0,(double)y * rate - 1.0);,然后就是跟画Mandelbrot集相同的步骤了,这里就不多说了,只给出相应的代码了。
public void mouseMoved(MouseEvent e){
x1 = e.getX();
y1 = e.getY();
//System.out.println("x1的值:" + x1 + "y1的值:" + y1);
c1 = new Complex((double)x1 * rate - 2.0,(double)y1 * rate - 1.04);
for (int x = 0; x < 600; x++) {
for (int y = 0; y < heigth; y++) {
interation = 0;
z1 = new Complex((double)x * rate - 1.5,(double)y
* rate - 1.05);
//计算模长
length = Math.sqrt(z1.re * z1.re + z1.im * z1.im);
//判断是否在set内
while (length <= 2 && interation < maxInteration) {
//Mandelbrot集
z1 = z1.multiply(z1);
z1 = z1.add(c1);
//计算模长
length = Math.sqrt(z1.re * z1.re + z1.im
* z1.im);
interation++;
}
//如果在set内
if (interation == maxInteration) {
g.setColor(Color.BLACK);
g.drawLine(x + 605, y, x + 605, y);
}else {//如果不在set内
g.setColor(advocate(interation));
g.drawLine(x + 605, y, x + 605, y);
}
}
}
}
下面给张图片:
其实Mandelbrot集可以进行无限放大,放大思想:①选中的区域调整比例为3:2,上下左右缩放一下就可以;
②然后就是把坐标轴改变位置,即把原点移到选中区域中的分叉点上;
③接下来当然是调整缩放比例了,如果不调整的话,也就不是放大了,其实根本也放不大。原先的1/200(3.0/640.0)也就变成(tox - fromx)/ 640.0。tox是选中区域右边横坐标,fromx也就是选中区域左边坐标了。
PS:附件中有.jar文件,可以看看效果,只是Julia集的色彩配的不怎么好