Samouczek - jak zakodować ten interaktywny fraktal Julii w Javie:

Wprowadzenie

Ten samouczek przeprowadzi Cię przez tworzenie interaktywnego wizualizatora fraktala Julii w Java AWT, z możliwością powiększania poprzez klikanie na obrazie.

Pobierz pełny kod tutaj: JuliaFractal.java lub wykonaj poniższe kroki.

Krok 1: Podstawowa konfiguracja

Zacznij od stworzenia klasy, która dziedziczy po JPanel i implementuje MouseListener:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;

public class JuliaFractal extends JPanel implements MouseListener {
    private static final int WIDTH = 800;
    private static final int HEIGHT = 800;
    private static final int MAX_ITER = 256;
    
    private BufferedImage img;
}

Krok 2: Definiowanie stałych fraktala Julii

Fraktal Julii jest zdefiniowany przez stałą zespoloną c = cRe + cIm*i:

private double cRe = -0.7;
private double cIm = 0.27015;

Różne wartości c tworzą zupełnie różne fraktale. Wypróbuj te wartości:

Krok 3: Definiowanie okna widoku

Te zmienne określają, która część płaszczyzny zespolonej jest widoczna:

private double minRe = -1.5;
private double maxRe = 1.5;
private double minIm = -1.5;
private double maxIm = 1.5;

Krok 4: Algorytm fraktala Julii

Główna funkcja oblicza, czy punkt zespolony należy do zbioru Julii:

private int julia(double zRe, double zIm) {
    int n = 0;
    while (n < MAX_ITER) {
        double zRe2 = zRe * zRe;
        double zIm2 = zIm * zIm;
        
        // Jeśli punkt ucieka do nieskończoności
        if (zRe2 + zIm2 > 4.0) break;
        
        // Formuła: z = z² + c
        double newRe = zRe2 - zIm2 + cRe;
        double newIm = 2 * zRe * zIm + cIm;
        
        zRe = newRe;
        zIm = newIm;
        n++;
    }
    return n;
}
Jak to działa:

Krok 5: Renderowanie fraktala

Ta funkcja przechodzi przez każdy piksel obrazu:

private void renderFractal() {
    double reRange = maxRe - minRe;
    double imRange = maxIm - minIm;
    
    for (int y = 0; y < HEIGHT; y++) {
        for (int x = 0; x < WIDTH; x++) {
            // Konwersja współrzędnych piksela na współrzędne zespolone
            double re = minRe + (x * reRange) / WIDTH;
            double im = minIm + (y * imRange) / HEIGHT;
            
            int iter = julia(re, im);
            int color = getColor(iter);
            img.setRGB(x, y, color);
        }
    }
    repaint();
}

Krok 6: Kolorowanie fraktala

Ta funkcja przekształca liczbę iteracji w kolor:

private int getColor(int iter) {
    if (iter == MAX_ITER) return 0x000000; // Czarny dla zbioru
    
    double t = (double) iter / MAX_ITER;
    
    // Wielomiany Bernsteina dla płynnych gradientów
    int r = (int) (9 * (1 - t) * t * t * t * 255);
    int g = (int) (15 * (1 - t) * (1 - t) * t * t * 255);
    int b = (int) (8.5 * (1 - t) * (1 - t) * (1 - t) * t * 255);
    
    return (r << 16) | (g << 8) | b;
}

Krok 7: Implementacja interaktywnego powiększania

Gdy użytkownik kliknie, przeliczamy okno widoku:

@Override
public void mouseClicked(MouseEvent e) {
    double reRange = maxRe - minRe;
    double imRange = maxIm - minIm;
    
    // Konwersja kliknięcia na współrzędne zespolone
    double clickRe = minRe + (e.getX() * reRange) / WIDTH;
    double clickIm = minIm + (e.getY() * imRange) / HEIGHT;
    
    // Powiększenie o 50%
    double zoomFactor = 0.5;
    double newReRange = reRange * zoomFactor;
    double newImRange = imRange * zoomFactor;
    
    // Wyśrodkowanie na klikniętym punkcie
    minRe = clickRe - newReRange / 2;
    maxRe = clickRe + newReRange / 2;
    minIm = clickIm - newImRange / 2;
    maxIm = clickIm + newImRange / 2;
    
    renderFractal();
}

Krok 8: Tworzenie interfejsu graficznego

public JuliaFractal() {
    setPreferredSize(new Dimension(WIDTH, HEIGHT));
    addMouseListener(this);
    img = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
    renderFractal();
}

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.drawImage(img, 0, 0, null);
}

public static void main(String[] args) {
    SwingUtilities.invokeLater(() -> {
        JFrame frame = new JFrame("Fraktal Julii - Kliknij aby powiększyć");
        JuliaFractal fractal = new JuliaFractal();
        frame.add(fractal);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    });
}

Możliwe ulepszenia

  1. Dodaj przycisk resetowania aby wrócić do początkowego widoku
  2. Umożliw pomniejszanie za pomocą prawego przycisku myszy
  3. Dodaj wskaźnik ładowania dla długich obliczeń
  4. Wielowątkowość aby przyspieszyć renderowanie
  5. Wybór różnych wartości c aby eksplorować inne fraktale
  6. Zapisywanie obrazów aby uchwycić swoje odkrycia

Kompilacja i uruchomienie

javac JuliaFractal.java
java JuliaFractal

Podsumowanie

Masz teraz działający wizualizator fraktala Julii! Fraktale Julii ujawniają nieskończenie złożone i samopodobne struktury. Każde powiększenie odsłania nowe fascynujące szczegóły. Baw się dobrze eksplorując!