2012-12-31 10 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; 

это в основном перемещает изображение, которое было нарисовано путем умножения его движения по осям x и y на коэффициент увеличения (который равен двум).

+0

Просьба [принять] (http://meta.stackexchange.com/a/65088/155831) ответ, когда вы получаете шанс. Рад, что вы его отсортировали. :) –

+2

Умножение xMove на зум, так что вы позже можете разделить на зум, по существу будет работать, но это кажется слишком сложным способом сделать это. Фактически результат не является математически корректным: масштаб начинается с 130, а zoomIncrease начинается со 100, и когда вы добавляете их вместе, это не означает точное удвоение, поэтому удвоение xMove будет не совсем корректным. Помните, что во всех кодировках просто всегда лучше. Упростите и сделайте это математически правильным, исключив zoomIncrease и просто используйте 'zoom * = 2;' – AgilePro

5

Множество Мандельброта существует в математической плоскости с естественными координатами. Вы «рассматриваете» это с помощью BufferedImage I, использующего координаты «view port». Это все в сопоставлении между ними. Вы обозначили координаты вида в виде 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), а скорее сумму, которая зависит от уровня масштабирования. Когда вы увеличиваете масштаб, вы хотите, чтобы количество движения в реальной плоскости Мандельброта было меньше для каждого нажатия клавиши.