2012-12-31 11 views
5

Zaczynam tworzyć fraktalową przeglądarkę mandelbrot. Mam dużo problemów, jeśli chodzi o powiększanie fraktali. Jeśli spróbujesz powiększyć, widz będzie po prostu zbliżał się do środka. Zrobiłem tyle, ile mogłem, aby zrozumieć ten dylemat. Jak mogę powiększyć mój fraktal w taki sposób, że gdy powiększę, powiększy on środek ekranu, a nie środek fraktali?Powiększanie fraktali zestawu Mandelbrota w Javie

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

Odpowiedz

2

udało mi się rozwiązać ten problem poprzez dodatkowe przesunięcie poziome lub pionowe każdym razem powiększony w

Dlatego zamiast:.

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

będę teraz mieć

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

to zasadniczo przesuwa obraz, który został narysowany przez pomnożenie jego ruchu na osiach x i y przez współczynnik powiększenia powiększenia (który wynosi dwa).

+0

Proszę [zaakceptuj] (http://meta.stackexchange.com/a/65088/155831) odpowiedź, gdy masz szansę. Cieszę się, że rozwiązałeś problem. :) –

+2

Pomnożenie xMove przez zoom, aby później można było dzielić za pomocą zoomu, zasadniczo działa, ale wydaje się, że jest to zbyt skomplikowany sposób. W rzeczywistości wynik nie jest poprawny matematycznie: zoom zaczyna się od 130, a zoomIncrease zaczyna się od 100, a po dodaniu ich razem nie oznacza to dokładnego podwojenia, więc podwojenie xMove nie będzie dokładnie poprawne. Pamiętaj, że przy całym kodowaniu proste jest zawsze lepsze. Uprość i popraw to matematycznie, eliminując zoom Powiększenie i po prostu użyj 'zoom * = 2;' – AgilePro

5

Zestaw Mandelbrota istnieje w płaszczyźnie matematycznej o naturalnych współrzędnych. Możesz "zobaczyć" to za pomocą BufferedImage I, używając współrzędnych "view port". Wszystko odbywa się w odwzorowaniu między nimi. Określiłeś współrzędne rzutni jako xiy, a "rzeczywiste" współrzędne w przestrzeni Mandelbrota jako cx i cy. Są to wzory:

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

W celu przybliżania i oddalania od konkretnego „prawdziwego” miejscu, chcesz kwota swojej wyporności być stała, jak powiększyć. Problem polega na tym, że wielkość przemieszczenia jest skalowana przez wielkość powiększenia. Pamiętaj cx i cy są prawdziwymi współrzędnymi w płaszczyźnie Mandelbrota, a x & y są współrzędnymi rzutni. Tak więc, patrząc na środek ekranu, zmieniając powiększenie, chcesz, aby cx & cy pozostało stałe.

Domyślam się, że chcesz coś takiego:

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

To sprawi, że „ruch” w płaszczyźnie Mandelbrota pozostają niezależne od ilości ogniskowych. Zakładam, że 320 i 290 jest związane z rozmiarem ekranu i daje zero w środku rzutni.

Będziesz chciał kwotę, xMove & yMove zmiana na naciśnięcie klawisza, aby nie być ustaloną kwotę (100), ale raczej ilość, która zależy od poziomu powiększenia. Kiedy powiększysz dużo, chcesz, aby ruch w prawdziwej płaszczyźnie Mandelbrota był mniejszy dla każdego naciśnięcia klawisza.