很漂亮是吧~不过很遗憾这不是我做的,但本人还是有画比较简单的两个集合的图形,有待指教改进。不过在此之前应该先简单介绍一下这两个集合,Mandelbrot集是通过迭代方程Zn+1=(Zn)^2+Zc,其中数Zc=0,Zn是一个复数。我们定义Mandelbrot集是所有复数Zc的集合,这样当n趋于无穷时Zn是有限的,如果超过2, Zn不会是有限的。例如我们想要的颜色像素(-1,0.5),以Zc = -1 +0.5i和Z0= 0开始,则有:
Z1 = Z0^2+Zc = -1+0.5i;
Z2 = Z1^2+Zc = -0.25-0.5i;
Z3 = Z2^2+Zc = -1.1875+0.75i;
Z4 = Z3^2+Zc = -0.1529344-1.28125i;
Z5 = Z42+Zc = -2.61839+0.890381i;
``````
我们停在这里因为大小| Z5| = 2.76564> 2。我们得出这样的结论:这一点是无界的且迭代次数为5。然后我们再次重复整个过程的每个像素。而Julia集和Mandelbrot集是非常相似的因为所用的迭代方程为同一个Zn+1=(Zn)^2+Zc。然而,不同于上述的根据不同的Zc值绘制像素,我们假设Zc的所有像素是给定的常数,我们绘制不同的 。因此,这有无限的Julia集主要取决于你选择的Zc的取值。例如,我们想要的颜色像素(-1,0.5)的Julia集使用常数Zc = -1.125+0.25i,我们开始以Z0=-1+0.5i;
Z1 = Z02+Zc = -0.375-0.75i;
Z2 = Z12+Zc = -1.54688-0.8125i;
Z3 = Z22+Zc = -0.60767+2.26367i;
``````
我们停在这里,因为大小| Z3 | = 2.34381> 2。我们得出结论,这一点上是无限的和迭代n=3的基础上的像素.
以上的论断我们假设z=x+yi,可得两个集合均要求x^2+y^2<2^2,且对于Julia 集,固定Zc值,把复平面指定区域内的复数点作为初值Z0代入后,迭代过程Zn+1=Zn^2+Zc终止时的迭代次数;对于Mandelbrot 集,它表示固定Z0 值,把复平面指定区域内的复数点作为μ值代入后,迭代过程Zn+1=Zn^2+Zc终止时的迭代次数。写得比较简单,就一个JFrame界面和一个ActionListner监听器,界面部分就不拿出来了,下面是Julia集监听器部分代码
import java.awt.Color; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JFrame; /** * 监听器 * @author suer * */ public class CJuliadrawListener implements ActionListener { double p, q; //Zc=p+qi,p,q的值自己给定 Graphics g; JFrame jf; private final int MAX=255;//颜色数值的最大值 public CJuliadrawListener(Graphics g,JFrame jf){ this.g=g; this.jf=jf; } public void actionPerformed(ActionEvent e){ String s=e.getActionCommand(); if(s.equals("p=-0.65175;q=0.41850")){ paint(g,-0.65175,0.41850); }else if(s.equals("p=-0.46;q=0.57")){ paint(g,-0.46,0.57); }else if(s.equals("p=-0.8;q=0.156")){ paint(g,-0.8,0.156); }else if(s.equals("p=-0.835;q=-0.2321")){ paint(g,-0.835,-0.2321); }else if(s.equals("p=0.285;q=0.01")){ paint(g,0.285,0.01); }else if(s.equals("p=-0.70176;q=-0.3842")){ paint(g,-0.70176,-0.3842); } } /** * julia集的实部和虚部值的范围 * @param x0:初始的实部值 * @param y0:初始的虚部值 * @return:循环的参数 */ public int cjulia(double x0,double y0){ double xk,yk; int i; for (i=0;i<100;i++) { xk=x0*x0-y0*y0+p; yk=2*x0*y0+q; if (xk*xk+yk*yk>4) return i; x0=xk; y0=yk; } return i; } /** * 由迭代产生的0.0到1.0的颜色值的方法 * @param x0:初始的实部值 * @param y0:初始的虚部值 * @param p:Zc的实部值 * @param q:Zc的虚部值 * @return:颜色参数 */ private float punktfarbe(double x0, double y0,double p,double q){ double xk=0, yk=0; int j = 0; while((j<MAX)&&(yk*yk+xk*xk< 4.0)){ xk=x0*x0-y0*y0 + p; yk=2.0*x0*y0 + q; j++; x0=xk; y0=yk; } return (float)j/(float)MAX; } /** * 绘制julia集的方法 * @param g:画布 * @param p:Zc的实部值 * @param q:Zc的虚部值 */ public void paint (Graphics g,double p,double q) { double reZ, imZ, ze0=0.0038; //double reZ, imZ, ze0=0.0055; int x, y; imZ=-1.5; for (y=0;y<700;y++) { reZ=-1.5; for (x=0;x<700;x++) { if (cjulia(reZ,imZ)==100) { // float s=punktfarbe(reZ,imZ,p,q); // float b=1.0f-s*s; // g.setColor(Color.getHSBColor(1,s,b)); // float h=punktfarbe(reZ,imZ,p,q); // float b=1.0f-h*h; // g.setColor(Color.getHSBColor(h,1,b)); // float b=punktfarbe(reZ,imZ,p,q); // float h=1.0f-b*b; // g.setColor(Color.getHSBColor(h,1,b)); float h=punktfarbe(reZ,imZ,p,q); float s=1.0f-h*h; g.setColor(Color.getHSBColor(h,s,1)); g.drawLine(x+75,y,x+75,y); } reZ=reZ+ze0; } imZ=imZ+ze0; } } }
下面是Mandelbrot集的MouseListener监听器部分的代码
import java.awt.Color; import java.awt.Graphics; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import javax.swing.JFrame; public class MandelbrotListener implements MouseListener { private static final double max=1.5;//最大值 private static final double min=-1.5; //最小值 private static final int Colors=25; //颜色数 及增长数 private Graphics g; private JFrame jf; public MandelbrotListener(Graphics g,JFrame jf){ this.g=g; this.jf=jf; } public void mouseClicked(MouseEvent e){} public void mousePressed(MouseEvent e){} public void mouseReleased(MouseEvent e){ drawMandel(g); } public void mouseEntered(MouseEvent e){} public void mouseExited(MouseEvent e){} public Color[] getColors(){return colors;} /** * 颜色设置,rgb的值按colors的数值增长 */ private void makeColors(){ int maxRGB=255,r=0,g=0,b=0; colors=new Color[Colors+1]; for(int i=0;i<Colors;i++){ colors[i]=new Color(r,g,b); r+=Colors; if(r>maxRGB){ r=0;g+=Colors; if(g>maxRGB){ g=0; b+=Colors; } if(b>maxRGB) b=0; } } colors[Colors]=Color.white; } private static Color[] colors; /** * 画mandelbrot集的方法,mandelbrot集要注意xstep,ystep,即发散的速度 * @param g:画布 */ private void drawMandel(Graphics g){ double xstep,ystep,x,y; //xstep,ystep是x,y值每次增加的大小 int i,j,iteration,k=0; double xk,yk,xh,yh,real,imag;; xstep=0.0025;ystep=0.0035; for(y=min,j=0;y<=max;y+=ystep,j++){ for(x=min,i=0;x<=max;x+=xstep,i++){ xk=x; yk=y; xh=yh=0.0; for(iteration=0;iteration<Colors;iteration++){ real=xk+xh; imag=yk+yh; xh=real*real-imag*imag; yh=2*real*imag; if(xh*xh+yh*yh>4) break; } makeColors(); g.setColor(colors[iteration]); g.fillRect(i,j,1,1); } } } }
最后要说的是,分形不是几个集合就能代表的,而是一门学问,分形理论的应用也不是局限在画出漂亮的图形而是囊括了很多方面,从大分子到宇宙星系,从自然科学到社会科学,凡是具有自相似性的现象就有分形存在。分形有在物理学中的应用,比如在准晶态的扩散、薄膜的研究、高能粒子碰撞中的阵发现象等,在化学中的应用,例如多相催化体系、宏观化学动力学等,又如植物中树、枝、叶、茎、花、草、蕨、花椰菜等是自然界中最先被认知具有分形维数的物体,材料制备和材料断裂行为等研究,以及用于解释和分析复杂的天文、水文、地质、地理等领域。此外在经济管理学、计算机图形学、复杂产品的分形设计、有限元网格划分的递推模型、制造决策映射建模等方面也有应用。