5

マンデルブロ セット フラクタル ビューアを作成し始めています。フラクタルのズームインに関しては、多くの問題があります。ズームしようとすると、視聴者は中心に近づきます。私はこのジレンマを理解するためにできる限りのことをしました。フラクタルを拡大すると、フラクタルの中心ではなく、画面の中心が拡大されるようにするにはどうすればよいですか?

import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import java.awt.event.*;



public class Mandelbrot extends JFrame implements ActionListener {

    private JPanel ctrlPanel;
    private JPanel btnPanel;
    private int numIter = 50;
    private double zoom = 130;
    private double zoomIncrease = 100;
    private int colorIter = 20;
    private BufferedImage I;
    private double zx, zy, cx, cy, temp;
    private int xMove, yMove = 0;
    private JButton[] ctrlBtns = new JButton[9];
    private Color themeColor = new Color(150,180,200);

    public Mandelbrot() {
        super("Mandelbrot Set");
        setBounds(100, 100, 800, 600);
        setResizable(false);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        plotPoints();

        Container contentPane = getContentPane();

        contentPane.setLayout(null);




        ctrlPanel = new JPanel();
        ctrlPanel.setBounds(600,0,200,600);
        ctrlPanel.setBackground(themeColor);
        ctrlPanel.setLayout(null);

        btnPanel = new JPanel();
        btnPanel.setBounds(0,200,200,200);
        btnPanel.setLayout(new GridLayout(3,3));
        btnPanel.setBackground(themeColor);

        ctrlBtns[1] = new JButton("up");
        ctrlBtns[7] = new JButton("down");
        ctrlBtns[3] = new JButton ("left");
        ctrlBtns[5] = new JButton("right");
        ctrlBtns[2] = new JButton("+");
        ctrlBtns[0] = new JButton("-");
        ctrlBtns[8] = new JButton(">");
        ctrlBtns[6] = new JButton("<");
        ctrlBtns[4] = new JButton();

        contentPane.add(ctrlPanel);
        contentPane.add(new imgPanel());
        ctrlPanel.add(btnPanel);

        for (int x = 0; x<ctrlBtns.length;x++){
            btnPanel.add(ctrlBtns[x]);
            ctrlBtns[x].addActionListener(this);
        }

        validate();

    }

    public class imgPanel extends JPanel{
        public imgPanel(){
            setBounds(0,0,600,600);

        }

        @Override
        public void paint (Graphics g){
            super.paint(g);
            g.drawImage(I, 0, 0, this);
        }
    }

    public void plotPoints(){
        I = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
        for (int y = 0; y < getHeight(); y++) {
            for (int x = 0; x < getWidth(); x++) {
                zx = zy = 0;
                cx = (x - 320+xMove) / zoom;
                cy = (y - 290+yMove) / zoom;
                int iter = numIter;
                while (zx * zx + zy * zy < 4 && iter > 0) {
                    temp = zx * zx - zy * zy + cx;
                    zy = 2 * zx * zy + cy;
                    zx = temp;
                    iter--;
                }
                I.setRGB(x, y, iter | (iter << colorIter));
            }
        }
    }

    public void actionPerformed(ActionEvent ae){
        String event = ae.getActionCommand();

        switch (event){
        case "up":
            yMove-=100;
            break;
        case "down":
            yMove+=100;
            break;
        case "left":
            xMove-=100;
            break;
        case "right":
            xMove+=100;
            break;
        case "+":
            zoom+=zoomIncrease;
            zoomIncrease+=100;
            break;
        case "-":
            zoom-=zoomIncrease;
            zoomIncrease-=100;
            break;
        case ">":
            colorIter++;
            break;
        case "<":
            colorIter--;
            break;
        }



        plotPoints();
        validate();
        repaint();
    }




    public static void main(String[] args) {
        new Mandelbrot().setVisible(true);
    }
}
4

2 に答える 2

5

マンデルブロ集合は、自然座標を持つ数学的平面に存在します。「ビューポート」座標を使用して BufferedImage I でこれを「表示」します。それはすべて、これらの間のマッピングにあります。ビューポート座標を x および y としてラベル付けし、マンデルブロ空間への「実際の」座標を cx および cy としてラベル付けしました。これらは式です:

        cx = (x - 320+xMove) / zoom;
        cy = (y - 290+yMove) / zoom;

特定の「実際の」スポットをズームインおよびズームアウトするには、ズームするときのディスプレイスメントの量を一定にする必要があります。問題は、変位量がズーム量によってスケーリングされていることです。cx と cy はマンデルブロ平面の実際の座標であり、x & y はビューポート座標であることを思い出してください。したがって、ビューポートの中央を見ると、ズームを変更するときに cx と cy を一定に保つ必要があります。

私の推測では、次のようなものが必要です。

    cx = ((x - 320) / zoom) + xMove;
    cy = ((y - 290) / zoom) + yMove;

これにより、マンデルブロ平面の「動き」がズーム量に依存しなくなります。320 と 290 はビューポート サイズに関連しており、ビューポートの中央にゼロが表示されると想定しています。

キーストロークで xMove と yMoveが変化する量を固定量 (100) ではなく、ズーム レベルに応じた量にする必要があります。大きく拡大すると、キーストロークごとに実際のマンデルブロ平面での移動量を小さくしたいと思うでしょう。

于 2012-12-31T15:57:26.027 に答える
2

拡大するたびに水平方向または垂直方向のシフトを追加することで、この問題を解決できました。

したがって、代わりに:

case "+": //zooming in
zoom+=zoomIncrease;
zoomIncrease+=100;
break;

私は今持っています

case "+":
initialZoom = zoom;
zoom+=zoomIncrease;
zoomIncrease*=2;
xMove*=2;
yMove*=2;
break;

これは基本的に、x 軸と y 軸上の動きにズームが増加した係数 (2) を掛けることによって、描画された画像を再配置します。

于 2013-01-02T02:47:19.467 に答える