2012-12-31 34 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平面上的移动量在每次击键时都较小。