2012-12-31 11 views
5

Ich fange an, ein Mandelbrot Set Fraktal Viewer zu machen. Ich habe viele Probleme, wenn es darum geht, das Fraktal zu vergrößern. Wenn Sie versuchen, zu zoomen, wird der Viewer nur in der Mitte angezeigt. Ich habe so viel wie möglich getan, um dieses Dilemma zu verstehen. Wie kann ich mein Fraktal so vergrößern, dass beim Zoomen in die Mitte des Bildschirms und nicht in die Mitte des Fraktals gezoomt wird?Zoom auf Mandelbrot setzen Fraktal in 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); 
    } 
} 

Antwort

2

konnte ich dieses Problem beheben, indem eine zusätzliche horizontale oder vertikale Verschiebung jedesmal, wenn ich gezoomt mit

daher statt mit:.

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

ich jetzt

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

Dies verlagert das Bild, das gezeichnet wurde, durch Multiplizieren seiner Bewegung auf der x- und y-Achse um den Faktor, dass der Zoom vergrößert wurde (was zwei ist).

+0

Bitte [akzeptieren] (http://meta.stackexchange.com/a/65088/155831) die Antwort, wenn Sie eine Chance haben. Ich bin froh, dass du es sortiert hast. :) –

+2

Multiplizieren der xMove mit Zoom, so dass Sie später durch Zoom teilen können, wird im Wesentlichen funktionieren, aber es scheint wie ein übermäßig komplizierter Weg, es zu tun. Eigentlich ist das Ergebnis nicht mathematisch korrekt: Zoom beginnt bei 130, und ZoomInkrement bei 100, und wenn Sie diese zusammen addieren, ist es keine exakte Verdoppelung, also ist die Verdopplung des xMove nicht genau richtig. Denken Sie daran, dass bei allem Codieren einfach immer besser ist. Vereinfachen und mathematisch korrigieren, indem Sie zoomIncrease entfernen und einfach 'zoom * = 2;' verwenden – AgilePro

5

Die Mandelbrot-Menge existiert in einer mathematischen Ebene mit natürlichen Koordinaten. Sie "sehen" dies mit einem BufferedImage I unter Verwendung von "View Port" -Koordinaten. Es ist alles in der Zuordnung zwischen diesen. Sie haben die Koordinaten des Ansichtsfensters als x und y und die "echten" Koordinaten als cx und cy im Mandelbrot-Raum angegeben. Dies sind die Formeln:

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

Um zu vergrößern und aus einem bestimmten „echten“ Spot, Sie wollen, dass die Höhe Ihrer Verschiebung konstant zu sein, wie Sie vergrößern oder verkleinern. Das Problem ist, dass der Verschiebungsbetrag um den Zoombetrag skaliert wird. Denken Sie daran, dass cx und cy die echten Koordinaten in der Mandelbrot-Ebene und x & y die Koordinaten des Ansichtsfensters sind. Wenn Sie also die Mitte des Ansichtsfensters betrachten, während Sie den Zoom ändern, möchten Sie, dass cx & cy konstant bleibt.

Meine Vermutung ist, dass Sie etwas wollen, wie:

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

Dies wird die „Bewegung“ in der Ebene Mandelbrots machen bleiben unabhängig von Zoom-Betrag. Ich gehe davon aus, dass die 320 und 290 mit der Größe des Darstellungsbereichs in Beziehung stehen und gibt Ihnen eine Null in der Mitte des Darstellungsbereichs.

Sie werden den Betrag, den xMove & yMove Änderung auf Knopfdruck wollen, nicht einen festen Betrag (100), sondern eine Menge zu sein, die auf Zoomstufe abhängt. Wenn Sie viel hineinzoomen, möchten Sie, dass die Bewegungsmenge in der echten Mandelbrot-Ebene bei jedem Tastendruck kleiner ist.