2012-12-31 35 views
5

我開始製作一個mandelbrot集分形瀏覽器。當涉及到放大分形時,我遇到了很多問題。如果您嘗試縮放,觀衆只需關閉中間位置即可。我盡我所能去了解這種困境。如何放大我的分形,以便在放大時放大屏幕的中心而不是分形的中心?放大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; 

這基本上是通過將其在x和y軸上的移動乘以縮放倍數(這是兩個)的因子重新定位已繪製的圖像。

+0

當你有機會時,請[接受](http://meta.stackexchange.com/a/65088/155831)答案。很高興你把事情解決了。 :) –

+2

通過縮放乘以xMove,以便以後可以通過縮放進行分割,基本上可以工作,但它似乎是一個過度複雜的方法。實際上,結果在數學上不正確:縮放從130開始,zoomIncrease從100開始,當你將它們加在一起時,它不會達到精確的兩倍,所以加倍xMove不會是完全正確的。請記住,在所有編碼中,簡單總是更好。通過消除zoomIncrease並簡單地使用'zoom * = 2;'來簡化並使其在數學上正確 – AgilePro

5

Mandelbrot集存在於具有自然座標的數學平面中。您使用「視圖端口」座標使用BufferedImage「查看」這個視圖。這些都是在這些映射之間。您已將視口座標標記爲x和y,並將Mandelbrot空間中的「真實」座標標記爲cx和cy。這些都是公式:

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

爲了放大和縮小特定的「真實」點的,你希望你的位移量是當你放大不變。問題是位移量正在縮放量。記住cx和cy是Mandelbrot平面中的真實座標,y是視口座標。因此,在查看視口的中部時,當您更改縮放時,您希望cx保持不變。

我的猜測是,你想要的東西,如:

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

這將使在曼德爾布羅平面的「運動」保持獨立的變焦量。我假設320和290與視口大小相關,並在視口中間給出一個零。

你會想上一個按鍵XMOVE & yMove偏移變化到不是一個固定的量(100),而是取決於縮放級別的金額。當你放大很多時,你想讓真正的Mandelbrot平面上的移動量在每次擊鍵時都較小。