Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Cleanup
authorgiersch <giersch>
Fri, 22 Jan 2010 13:52:42 +0000 (13:52 +0000)
committergiersch <giersch>
Fri, 22 Jan 2010 13:52:42 +0000 (13:52 +0000)
mandel/mandel.cpp

index 07d5a63..8c525ee 100644 (file)
 #include <DrawingWindow.h>
 #include <QApplication>
 #include <iostream>
 #include <DrawingWindow.h>
 #include <QApplication>
 #include <iostream>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+struct 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;
+};
+
+const parameters initial_parameters = {
+    1000,                       // maxiter
+    -2.05,                      // Rmin
+    0.55,                       // Rmax
+    -1.3,                       // Imin
+    1.3,                        // Imax
+    0.0,                        // Rscale
+    0.0,                        // Iscale
+};
+
+int check_point(parameters& p, double cr, double ci)
+{
+    double zr = 0.0;
+    double zi = 0.0;
+    double zr2 = 0.0;
+    double zi2 = 0.0;
+    int i;
+    for (i = 0 ; zr2 + zi2 < 4 && i < p.maxiter; i++) {
+        zi = 2 * zr * zi + ci;
+        zr = zr2 - zi2 + cr;
+        zr2 = zr * zr;
+        zi2 = zi * zi;
+    }
+    return i;
+}
+
+// int check_point(parameters& p, int x, int y)
+// {
+//     double cr = p.Rmin + x * p.Rscale;
+//     double ci = p.Imax - y * p.Iscale;
+//     return check_point(p, cr, ci);
+// }
+
+void set_color(DrawingWindow& w, parameters& p, int i)
+{
+    double rouge, vert, bleu;
+    if (i >= p.maxiter) {
+        rouge = vert = bleu = 0.0;
+    } else {
+        int ii = (p.maxiter - 1 - i) % 96;
+        if (ii < 32) {
+            // vert -> bleu
+            bleu = ii / 32.0;
+            vert = 1.0 - bleu;
+            rouge = 0.0;
+        } else if (ii < 64) {
+            // bleu -> rouge
+            rouge = (ii - 32) / 32.0;
+            bleu = 1.0 - rouge;
+            vert = 0.0;
+        } else {
+            // rouge -> vert
+            vert = (ii - 64) / 32.0;
+            rouge = 1.0 - vert;
+            bleu = 0.0;
+        }
+    }
+    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.
 
 // Fonction de dessin de l'ensemble de Madelbrot, dans la zone
 // spécifiée, et avec la précision souhgaitée.
-void do_mandel(DrawingWindow &w,
-               double Rmin, double Rmax, double Imin, double Imax,
-               int maxiter)
+void do_mandel(DrawingWindow& w, parameters& p)
 {
     int x, y;                   // le pixel considéré
     double cr, ci;              // le complexe correspondant
 {
     int x, y;                   // le pixel considéré
     double cr, ci;              // le complexe correspondant
-    double zr, zi;              // pour calculer la suite
-    double zr2, zi2;            // zr^2 et zi^2
-    double pr, pi;              // taille d'un pixel
-    double rouge, vert, bleu;
-    int i;
+    int iprev = -1;
 
 
-    pr = (Rmax - Rmin) / (w.width - 1);
-    pi = (Imax - Imin) / (w.height - 1);
-    
-    cr = Rmin;
-    for (x = 0; x < w.width; x++) {
-        ci = Imax;
-        for (y = 0; y < w.height; y++) {
-            // z_0 = 0
-            zr = zi = 0.0;
-            zr2 = zi2 = 0.0;
-            for (i = 0; zr2 + zi2 < 4 && i < maxiter; i++) {
-                // on calcule le z suivant
-                zi = 2 * zr * zi + ci;
-                zr = zr2 - zi2 + cr;
-                zr2 = zr * zr;
-                zi2 = zi * zi;
-            }
-            if (i >= maxiter) {
-                rouge = vert = bleu = 0.0;
-            } else {
-                // on est sorti trop tôt du for(...): on affiche le
-                // pixel d'un couleur en fonction de i
-                int ii = (maxiter - 1 - i) % 96;
-                if (ii < 32) {
-                    // vert -> bleu
-                    bleu = ii / 32.0;
-                    vert = 1.0 - bleu;
-                    rouge = 0.0;
-                } else if (ii < 64) {
-                    // bleu -> rouge
-                    rouge = (ii - 32) / 32.0;
-                    bleu = 1.0 - rouge;
-                    vert = 0.0;
-                } else {
-                    // rouge -> vert
-                    vert = (ii - 64) / 32.0;
-                    rouge = 1.0 - vert;
-                    bleu = 0.0;
+    int kmax = 16;
+    for (int k = kmax ; k != 0 ; k /= 2) {
+        int kk = 2 * k;
+        double ar = k * p.Rscale;
+        double ai = k * p.Iscale;
+        cr = p.Rmin;
+        for (x = 0 ; x < w.width ; x += k) {
+            ci = p.Imax;
+            for (y = 0 ; y < w.height ; y += k) {
+                if (x % kk != 0 || y % kk != 0 || k == kmax) {
+                    int i = check_point(p, cr, ci);
+                    if (i != iprev) {
+                        set_color(w, p, i);
+                        iprev = 1;
+                    }
+                    if (k > 2) {
+                        w.fillRect(x, y, x + k - 1, y + k - 1);
+                    } else {
+                        w.drawPoint(x, y);
+                        if (k == 2) {
+                            w.drawPoint(x + 1, y);
+                            w.drawPoint(x, y + 1);
+                            w.drawPoint(x + 1, y + 1);
+                        }
+                    }
                 }
                 }
+                ci -= ai;
             }
             }
-            w.setColor(rouge, vert, bleu);
-            w.drawPoint(x, y);
-
-            ci -= pi;
+            cr += ar;
         }
         }
-        cr += pr;
     }
 }
     }
 }
-
+    
 // Fonction de dessin principale, calcule la zone d'intérêt, appelle
 // do_mandel(), pour dessiner l'ensemle, et permet le zoom.
 void mandel(DrawingWindow &w)
 {
 // Fonction de dessin principale, calcule la zone d'intérêt, appelle
 // do_mandel(), pour dessiner l'ensemle, et permet le zoom.
 void mandel(DrawingWindow &w)
 {
-    // nombre max d'itérations
-    int maxiter = 500;
-    // zone d'intérêt par défaut
-    double Rmin = -2.05;
-    double Rmax = 0.55;
-    double Imin = -1.3;
-    double Imax = 1.3;
-    // cible du zoom
-    double Tr;
-    double Ti;
-
+    parameters p = initial_parameters;
     while (1) {
     while (1) {
-        do_mandel(w, Rmin, Rmax, Imin, Imax, maxiter);
+        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, 5, "Cliquer sur l'image pour zoomer");
 
         w.setColor("white");
         w.drawText(5, 5, "Cliquer sur l'image pour zoomer");
@@ -91,16 +137,16 @@ void mandel(DrawingWindow &w)
         w.waitMousePress(x, y, button);
 
         // calcul des coordonnées du point cliqué
         w.waitMousePress(x, y, button);
 
         // calcul des coordonnées du point cliqué
-        Tr = Rmin + x * (Rmax - Rmin) / (w.width - 1);
-        Ti = Imax - y * (Imax - Imin) / (w.height - 1);
+        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é
         const int zoom = 2;
 
         // calcul de la nouvelle zone d'intérêt :
         // zoom ×2 en direction du point cliqué
         const int zoom = 2;
-        double Rmin2 = Rmin / zoom;
-        double Rmax2 = Rmax / zoom;
-        double Imin2 = Imin / zoom;
-        double Imax2 = Imax / zoom;
+        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;
         double Rshift = Tr - (Rmin2 + Rmax2) / 2;
         double Ishift = Ti - (Imin2 + Imax2) / 2;
         Rmin2 += Rshift;
@@ -109,16 +155,14 @@ void mandel(DrawingWindow &w)
         Imax2 += Ishift;
 
         // affichage d'un rectangle autour de la nouvelle zone d'intérêt
         Imax2 += Ishift;
 
         // affichage d'un rectangle autour de la nouvelle zone d'intérêt
-        double x_factor = (w.width - 1) / (Rmax - Rmin);
-        double y_factor = (w.height - 1) / (Imax - Imin);
         w.setColor("white");
         w.setColor("white");
-        w.drawRect((Rmin2 - Rmin) * x_factor, (Imax - Imin2) * y_factor,
-                   (Rmax2 - Rmin) * x_factor, (Imax - Imax2) * y_factor);
+        w.drawRect((Rmin2 - p.Rmin) / p.Rscale, (p.Imax - Imin2) / p.Iscale,
+                   (Rmax2 - p.Rmin) / p.Rscale, (p.Imax - Imax2) / p.Iscale);
 
 
-        Rmin = Rmin2;
-        Rmax = Rmax2;
-        Imin = Imin2;
-        Imax = Imax2;
+        p.Rmin = Rmin2;
+        p.Rmax = Rmax2;
+        p.Imin = Imin2;
+        p.Imax = Imax2;
     }
 }
 
     }
 }