import java.awt.*; import java.awt.event.*; public class Fractal extends Frame implements ActionListener, MouseListener { private Button zoomIn, zoomOut, exit; private TextField choixNb; private Dessin dessin; private double x1 = -2.5, x2 = 1.5, y1 = -1.5, y2 = 1.5; private int nb = 200; public Fractal() { Panel panneauBas = new Panel(); Panel panneauCentre = new Panel(); setLayout(new BorderLayout()); dessin = new Dessin(); panneauCentre.add(dessin); choixNb = new TextField(Integer.toString(nb), 6); zoomIn = new Button("Zoom in"); zoomOut = new Button("Zoom out"); exit = new Button("Exit"); panneauBas.add(new Label("Nombre d'itérations :")); panneauBas.add(choixNb); panneauBas.add(zoomIn); panneauBas.add(zoomOut); panneauBas.add(exit); this.add("Center", panneauCentre); this.add("South", panneauBas); choixNb.setEditable(true); choixNb.addActionListener(this); zoomIn.addActionListener(this); zoomOut.addActionListener(this); exit.addActionListener(this); dessin.addMouseListener(this); this.pack(); dessin.initialiser(); this.setResizable(false); this.setVisible(true); dessin.calcule(x1, y1, x2, y2, nb); } public static void main(String[] args) { new Fractal(); } public void actionPerformed(ActionEvent e) { if (e.getSource() == choixNb) { try { int n = Integer.parseInt(choixNb.getText()); if (n < 1) n = 1; choixNb.setText(Integer.toString(n)); if (n != nb) { nb = n; dessin.calcule(x1, y1, x2, y2, nb); } } catch(NumberFormatException ex) { choixNb.setText(Integer.toString(nb)); } return; } if (e.getSource() == zoomIn) { double dx = (x2 - x1) / 4.0; double dy = (y2 - y1) / 4.0; x1 += dx; y1 += dy; x2 -= dx; y2 -= dy; dessin.calcule(x1, y1, x2, y2, nb); return; } if (e.getSource() == zoomOut) { double dx = (x2 - x1) / 2.0; double dy = (y2 - y1) / 2.0; x1 -= dx; y1 -= dy; x2 += dx; y2 += dy; dessin.calcule(x1, y1, x2, y2, nb); return; } if (e.getSource() == exit) { dessin.interrompt(); System.exit(0); } } public void mouseClicked(MouseEvent e) { double x = x1 + (x2 - x1) * ((double) e.getX() / (double) dessin.largeur()); double y = y1 + (y2 - y1) * ((double) e.getY() / (double) dessin.hauteur()); double dx = (x1 + x2) / 2.0 - x; double dy = (y1 + y2) / 2.0 - y; x1 -= dx; y1 -= dy; x2 -= dx; y2 -= dy; dessin.calcule(x1, y1, x2, y2, nb); } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mousePressed(MouseEvent e) { } public void mouseReleased(MouseEvent e) { } } class Dessin extends Canvas implements Runnable { private Image sauvegarde = null; private Graphics gSauvegarde, gFenetre; private int largeur, hauteur; private Thread calcul = null; private volatile boolean stop = false; private double x1, x2, y1, y2; private int nbIterations; public void initialiser() { Dimension d = getSize(); largeur = d.width; hauteur = d.height; sauvegarde = createImage(largeur, hauteur); gSauvegarde = sauvegarde.getGraphics(); gFenetre = this.getGraphics(); this.effacer(); } public void paint(Graphics g) { g.drawImage(sauvegarde, 0, 0, this); } public Dimension getMinimumSize() { return new Dimension(400, 300); } public Dimension getPreferredSize() { return getMinimumSize(); } public synchronized void calcule(double x1, double y1, double x2, double y2, int nb) { this.interrompt(); this.effacer(); this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; this.nbIterations = nb; calcul = new Thread(this, "calcul fractal"); calcul.start(); } public synchronized void interrompt() { stop = true; while (calcul != null) { try { wait(); } catch(InterruptedException e) { } } stop = false; } public void run() { Mandelbrot m = new Mandelbrot(nbIterations); double dx = (x2 - x1) / largeur; double dy = (y2 - y1) / hauteur; principal: for (int i = 0; i < largeur; i++) for (int j = 0; j < hauteur; j++) if (stop) break principal; else { Color c = m.couleur(x1 + i * dx, y1 + j * dy); gFenetre.setColor(c); gFenetre.drawLine(i, j, i, j); gSauvegarde.setColor(c); gSauvegarde.drawLine(i, j, i, j); } synchronized(this) { calcul = null; notify(); } } public int largeur() { return largeur; } public int hauteur() { return hauteur; } private void effacer() { gSauvegarde.setColor(Color.black); gSauvegarde.fillRect(0, 0, largeur, hauteur); gFenetre.setColor(Color.black); gFenetre.fillRect(0, 0, largeur, hauteur); } } class Mandelbrot { private int nb; private Color[] couleurs; public Mandelbrot(int nb) { int i; float c; float dc = (float) 2.0 / (float) nb; this.nb = nb; couleurs = new Color[nb + 1]; couleurs[0] = Color.black; for (i = 1, c = (float) 0.0; i <= nb / 2; i++, c += dc) couleurs[i] = new Color( (float) 0.0, c, (float) 1.0 - c); for (c = (float) 0.0; i <= nb; i++, c += dc) couleurs[i] = new Color( (float) c, (float) 1.0 - c, (float) 0.0); } public Color couleur(double x, double y) { double x1 = 0.0, y1 = 0.0, x2, y2; for (int i = 0; i < nb; i++) { if (x1 * x1 + y1 * y1 > 4) return couleurs[i + 1]; x2 = x1 * x1 - y1 * y1 + x; y2 = 2.0 * x1 * y1 + y; x1 = x2; y1 = y2; } return couleurs[0]; } }