《编程导论(Java)·9.2.3 案例:M集》

分形理论(fractal theory)的奠基人曼德布罗特(Mandelbrot)发现了著名的Mandelbrot set,简称M集。M集可能是最复杂的数学对象,是分形、混沌领域的一种国际标志。


M集涉及到一些复数操作,包括复数乘法mul(Complex)、加法plus(Complex)和求模mod() (复数到坐标原点的距离)。由复数Complex类封装。

package API.graphics.fractal;
/**
 * Complex.java.
 * 提供M集所需要的复数功能,不完整的复数类。
 * @author yqj2065
 */
public class Complex{
    private final double x,y;//c = x + y *i即real + i* imaginary
    /**
     * 构造复数对象z = x +y *i
     * @param x 实部/real
     * @param y 虚部/imaginary
     */
    Complex(double x,double y) {
        this.x =x;   this.y =y;
    }
    Complex(){ this(0,0); }
    
    /**
     *复数乘法。Complex multiplication
     *
     */
    public Complex mul(Complex a){
        double newx =this.x*a.x-this.y*a.y;
        double newy =2*this.x*a.y;
        return new Complex(newx,newy);
    }
    public Complex plus(Complex a){
        double newx=this.x +a.x;
        double newy=this.y +a.y;
        return new Complex(newx,newy);
    }
	/**
	 * 求模。该复数到坐标原点的距离
	 * @return  |z|   z = x + i*y 
	 */
    public double mod(){ 
        return (x!=0 || y!=0) ? Math.sqrt( x*x + y*y):0d;
    }
}

M集定义:复平面上给定一个初始的复数Z0(通常令Z0为(0,0)点),对于任一复常数C,按照迭代公式:Zn+1 =Zn2+C

如果n趋向于无穷时,Zn+1有界,则称C属于Mandelbrot集。

书中提供了API.graphics.fractal.MSet。作为对《9.2.2 渲染引擎Graphics2D》的补充,添加了MandelbrotSet(在JFrame上绘制)和改进的MandelbrotSet2+DrawFrame。


1.JApplet中绘制

渲染(Rendering) /绘制,是在输出设备如屏幕或打印机上显示(display)几何形状、文本和图像的处理过程。 渲染引擎(Graphics和Graphics2D)完成渲染工作。
通常不必创建渲染引擎对象。
在组件/Component上面绘制图形时, paint(Graphics)、update(Graphics)的形参就是渲染引擎,各种组件如Applet、JApplet、Frame在改写这些方法时有现成的渲染引擎可用;JComponent提供了方法paintComponent(Graphics)。

package API.graphics.fractal;
import java.awt.*;
import javax.swing.*;
public class MSet extends JApplet{
    private int width=400,height =400;//复平面窗口分辨率width*height,即复平面的实际点数;
    //研究表明,M集处于复平面的较小区间中,x取[-2.25 ,0.75],y取[-1.5,1.5]
    private final double xMin=-2.25 , yMin=-1.5, xMax= 0.75 , yMax=1.5; 
    double xUnit= (xMax-xMin)/width; //绘图窗口中两个复数点的x间距
    double yUnit= (yMax-yMin)/height;
    int R = 10;//逃逸半径
    int N = 100;//迭代次数。


    @Override public void init(){
        this.resize(width,height);         
    }
    @Override public void paint(Graphics g){
        //复平面上逐点绘制
        for(int i=0;i<width;i++){
            for( int j=0;j<height;j++){
                double r  = xMin+ i* xUnit;//real
                double im = yMin+ j* yUnit;//imaginary
                int color = 10*iterate(r,im);
                if(color!=0) g.setColor(new Color(color));
                else g.setColor(Color.yellow);//表示该数属于M集。
                g.drawLine(i,j,i,j);
            }
        }//end for
    }
    
    /**
     * 迭代.Z(n+1) = Z(n)*Z(n) + c
     * 本来可以返回一个boolean值,为了设置绘制的颜色,返回迭代的次数。
     */
    private int iterate(double real, double imaginary){
        Complex c = new Complex(real,imaginary);//复常数C
        Complex z = new Complex(0.0,0.0);//z0
        for(int i =1; ; i++){
            z =(z.mul(z)).plus(c);//z*z
            if (z.mod() > R ) return i; //
            if (i > N ) return  0;
        }
    }
}

2.JFrame中绘制

对于自定义的普通方法或main,可以使用java.awt.Component的方法public Graphics getGraphics()获得渲染引擎。但是通常使用BufferedImage进行绘制。

package API.graphics.fractal;
import java.awt.*;
import javax.swing.*;
import java.awt.image.BufferedImage;
public class MandelbrotSet{
    private int width=400,height =400;//同上
    int N = 100;//迭代次数。
    
    public static void main(String[] args)  {
        MandelbrotSet m = new MandelbrotSet();
        JFrame frame=new JFrame();
        frame.setLayout(new FlowLayout());
        BufferedImage image=new BufferedImage(m.width,m.height,BufferedImage.TYPE_INT_ARGB);
        Graphics g=image.getGraphics();
        for(int i=0;i<m.width;i++){
            //同上
        }
        g.dispose();
        JLabel label=new JLabel(new ImageIcon(image));
        frame.add(label);
        frame.setTitle("Graphics");
        frame.setSize(m.width,m.height);
        frame.setVisible(true);
    }
    private int iterate(double real, double imaginary){
       //同上
    }
}

3.工具的雏形

MandelbrotSet以及其他绘图程序,都将使用BufferedImage,而import javax.swing.*;不是MandelbrotSet希望使用的。

package API.graphics.fractal;
import java.awt.*;
import javax.swing.*;
import java.awt.image.BufferedImage;

/**
 * 工具的雏形
 * 
 * @author (yqj2065) 
 * @version (0.1)
 */
public class DrawFrame{
    public static JFrame frame=new JFrame();
    public static void setSize(int width,int height){
        frame.setSize(width,height);
    }
    
    public static void draw(BufferedImage image){
        frame.setLayout(new FlowLayout());
        JLabel label=new JLabel(new ImageIcon(image));
        frame.add(label);
        frame.setTitle("Graphics");
        frame.setVisible(true);
    }
}
MandelbrotSet2对于MandelbrotSet的main方法进行了修改:

    public static void main(String[] args)  {
        MandelbrotSet2 m = new MandelbrotSet2();
        DrawFrame d =new DrawFrame();
        BufferedImage image=new BufferedImage(m.width,m.height,BufferedImage.TYPE_INT_ARGB);
        Graphics g=image.getGraphics();
        for(int i=0;i<m.width;i++){
            //
        }
        g.dispose();
        d.setSize(m.width,m.height);
        d.draw(image);
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值