Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add MoreEx/Mandel.
authorArnaud Giersch <arnaud.giersch@free.fr>
Tue, 14 Oct 2014 20:37:06 +0000 (22:37 +0200)
committerArnaud Giersch <arnaud.giersch@free.fr>
Tue, 14 Oct 2014 20:49:03 +0000 (22:49 +0200)
MoreEx/Mandel.java [new file with mode: 0644]

diff --git a/MoreEx/Mandel.java b/MoreEx/Mandel.java
new file mode 100644 (file)
index 0000000..62fc174
--- /dev/null
@@ -0,0 +1,156 @@
+class Mandel {
+
+    static class Parameters {
+        // nombre max d'itérations
+        int maxiter;
+        // zone d'intérêt par défaut
+        double Rmin;
+        double Rmax;
+        double Imin;
+        double Imax;
+        // facteur d'échelle
+        double Rscale;
+        double Iscale;
+    }
+
+    static final Parameters initial_parameters;
+    static {
+        initial_parameters = new Parameters();
+        initial_parameters.maxiter = 1000;
+        initial_parameters.Rmin    = -2.05;
+        initial_parameters.Rmax    = 0.55;
+        initial_parameters.Imin    = -1.3;
+        initial_parameters.Imax    = 1.3;
+        initial_parameters.Rscale  = 0.0;
+        initial_parameters.Iscale  = 0.0;
+    }
+
+    static double sqr(double x)
+    {
+        return x * x;
+    }
+
+    static int check_point(Parameters p, double cr, double ci)
+    {
+        double zr2, zi2;
+        zi2 = sqr(ci);
+        if (sqr(cr + 1) + zi2 < 1.0 / 16.0)
+            return p.maxiter;
+        double x4 = cr - 1.0 / 4.0;
+        double q = sqr(x4) + zi2;
+        if (q * (q + x4) < zi2 / 4.0)
+            return p.maxiter;
+        zr2 = sqr(cr);
+        double zr = cr;
+        double zi = ci;
+        int i;
+        for (i = 0 ; i < p.maxiter && zr2 + zi2 < 4 ; i++) {
+            zi = 2 * zr * zi + ci;
+            zr = zr2 - zi2 + cr;
+            zr2 = sqr(zr);
+            zi2 = sqr(zi);
+        }
+        return i;
+    }
+
+    static void set_color(DrawingWindow w, Parameters p, int i)
+    {
+        float rouge, vert, bleu;
+        if (i >= p.maxiter) {
+            rouge = vert = bleu = 0.0f;
+        } else {
+            int ii = (p.maxiter - 1 - i) % 96;
+            if (ii < 32) {
+                // vert -> bleu
+                bleu = ii / 32.0f;
+                vert = 1.0f - bleu;
+                rouge = 0.0f;
+            } else if (ii < 64) {
+                // bleu -> rouge
+                rouge = (ii - 32) / 32.0f;
+                bleu = 1.0f - rouge;
+                vert = 0.0f;
+            } else {
+                // rouge -> vert
+                vert = (ii - 64) / 32.0f;
+                rouge = 1.0f - vert;
+                bleu = 0.0f;
+            }
+        }
+        w.setColor(rouge, vert, bleu);
+    }
+
+    // Fonction de dessin de l'ensemble de Madelbrot, dans la zone
+    // spécifiée, et avec la précision souhgaitée.
+    static void do_mandel(DrawingWindow w, Parameters p)
+    {
+        int x, y;                   // le pixel considéré
+        double cr, ci;              // le complexe correspondant
+        for (y = 0 ; y < w.height ; y++) {
+            ci = p.Imax - y * p.Iscale;
+            cr = p.Rmin;
+            int x0 = 0;
+            int i0 = check_point(p, cr, ci);
+            for (x = 1 ; x < w.width ; x++) {
+                cr = p.Rmin + x * p.Rscale;
+                int i = check_point(p, cr, ci);
+                if (i != i0) {
+                    set_color(w, p, i0);
+                    w.drawLine(x0, y, x - 1, y);
+                    i0 = i;
+                    x0 = x;
+                }
+            }
+            set_color(w, p, i0);
+            w.drawLine(x0, y, w.width - 1, y);
+        }
+    }
+
+    // Fonction de dessin principale, calcule la zone d'intérêt, appelle
+    // do_mandel(), pour dessiner l'ensemble, et permet le zoom.
+    static void mandel(DrawingWindow w)
+    {
+        Parameters p = initial_parameters;
+        while (true) {
+            p.Rscale = (p.Rmax - p.Rmin) / (w.width - 1);
+            p.Iscale = (p.Imax - p.Imin) / (w.height - 1);
+            do_mandel(w, p);
+            w.setColor("white");
+            w.drawText(5, 15, "Cliquer sur l'image pour zoomer");
+            w.waitMousePress();
+            int x = w.getMouseX();
+            int y = w.getMouseY();
+            // calcul des coordonnées du point cliqué
+            double Tr = p.Rmin + x * p.Rscale;
+            double Ti = p.Imax - y * p.Rscale;
+            // calcul de la nouvelle zone d'intérêt :
+            // zoom ×2 en direction du point cliqué
+            final int zoom = 2;
+            double Rmin2 = p.Rmin / zoom;
+            double Rmax2 = p.Rmax / zoom;
+            double Imin2 = p.Imin / zoom;
+            double Imax2 = p.Imax / zoom;
+            double Rshift = Tr - (Rmin2 + Rmax2) / 2;
+            double Ishift = Ti - (Imin2 + Imax2) / 2;
+            Rmin2 += Rshift;
+            Rmax2 += Rshift;
+            Imin2 += Ishift;
+            Imax2 += Ishift;
+            // affichage d'un rectangle autour de la nouvelle zone d'intérêt
+            w.setColor("white");
+            w.drawRect((int)Math.round((Rmin2 - p.Rmin) / p.Rscale),
+                       (int)Math.round((p.Imax - Imin2) / p.Iscale),
+                       (int)Math.round((Rmax2 - p.Rmin) / p.Rscale),
+                       (int)Math.round((p.Imax - Imax2) / p.Iscale));
+            p.Rmin = Rmin2;
+            p.Rmax = Rmax2;
+            p.Imin = Imin2;
+            p.Imax = Imax2;
+        }
+    }
+
+    public static void main(String[] args) {
+        DrawingWindow w = new DrawingWindow("Mandelbrot' set", 800, 800);
+        mandel(w);
+    }
+}