From bcbd8d88046b022f22b7b868efab5ca724045057 Mon Sep 17 00:00:00 2001 From: giersch Date: Fri, 22 Jan 2010 13:52:42 +0000 Subject: [PATCH] Cleanup --- mandel/mandel.cpp | 200 ++++++++++++++++++++++++++++------------------ 1 file changed, 122 insertions(+), 78 deletions(-) diff --git a/mandel/mandel.cpp b/mandel/mandel.cpp index 07d5a63..8c525ee 100644 --- a/mandel/mandel.cpp +++ b/mandel/mandel.cpp @@ -1,87 +1,133 @@ #include #include #include +#include +#include +#include + +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. -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 - 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) { - // 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) { - 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"); @@ -91,16 +137,16 @@ void mandel(DrawingWindow &w) 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; - 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; @@ -109,16 +155,14 @@ void mandel(DrawingWindow &w) 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.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; } } -- 2.20.1