2012-12-31 27 views
5

マンデルブロセットフラクタルビューアを作成し始めました。私は、フラクタルを拡大する際には、多くの問題を抱えています。ズームしようとすると、ビューアは中央で閉じるだけです。私はこのジレンマを理解するためにできるだけ多くのことをしました。ズームすると、フラクタルの中心ではなく、画面の中心を拡大するような方法でフラクタルを拡大するにはどうすればよいですか?MandelbrotをJavaで拡大表示

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); 
    } 
} 

答えて

2

私は、追加の水平または垂直シフトに私がズームインするたびに持っていることによって、この問題を解決することができました

そのため、代わりに有していると:。

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

私は今

case "+": 
initialZoom = zoom; 
zoom+=zoomIncrease; 
zoomIncrease*=2; 
xMove*=2; 
yMove*=2; 
break; 
を持っています

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

+0

あなたがチャンスを取ったときに、答えを受け入れてください(http://meta.stackexchange.com/a/65088/155831)。あなたがそれを整理してうれしいです。 :) –

+2

ズームでxMoveを掛け合わせることで、後でズームで分けることができますが、基本的には動作しますが、それを行うにはあまりにも複雑な方法のようです。実際には、結果は数学的に正しいわけではありません。ズームは130で開始し、zoomIncreaseは100で始まり、それらを一緒に追加すると正確な倍増にならないため、xMoveを倍増させることは正確ではありません。すべてのコーディングで、シンプルさが常に優れていることを忘れないでください。 zoomIncreaseを削除して、単純に 'zoom * = 2;'を使うだけで、これを数学的に単純化して修正することができます。 – AgilePro

5

マンデルブロセットは、自然座標系を持つ数学的平面に存在します。 「ビューポート」座標を使用してBufferedImage Iでこれを「表示」します。これらの間のマッピングにはすべてがあります。ビューポート座標をxとyとラベルし、 "実"座標をマンデルブロ空間にcxとcyとラベルしました。これらは公式です:特定の「本当の」スポットのズームインとズームアウトするためには

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

、あなたはズームとあなたの変位量が一定になるようにしたいです。問題は、ズレ量がズーム量によってスケーリングされていることです。 cxとcyはマンデルブロ平面の実際の座標で、x &はビューポートの座標です。したがって、ビューポートの中央を見ると、ズームを変更するときに、cx & cyを一定のままにします。

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

これはマンデルブロ面での「動き」を行いますが、ズーム量の独立性を維持:

私の推測では、あなたのような何かをしたいということです。私は、320と290がビューポートのサイズに関連しており、ビューポートの中央にゼロを与えていると仮定しています。

あなたは、キーストロークのxMove & yMove 変更が一定量(100)ではなく、ズームレベルに依存する量ではない量を必要としています。たくさんズームインすると、実際のマンデルブロ平面での移動量を各キーストロークで小さくする必要があります。

関連する問題