
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.
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;
}
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:
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;
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;
}
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();
}
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;
}
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();
}
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);
});
}
javac JuliaFractal.java
java JuliaFractal
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!