Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
c5fa28f89a8a49cc7771f05da6e2a8fe31362577
[graphlib.git] / mandel / mandel.cpp
1 #include <DrawingWindow.h>
2 #include <QApplication>
3 #include <iostream>
4 #include <unistd.h>
5 #include <sys/types.h>
6 #include <sys/wait.h>
7
8 struct parameters {
9     // nombre max d'itérations
10     int maxiter;
11     // zone d'intérêt par défaut
12     double Rmin;
13     double Rmax;
14     double Imin;
15     double Imax;
16     // facteur d'échelle
17     double Rscale;
18     double Iscale;
19 };
20
21 const parameters initial_parameters = {
22     1000,                       // maxiter
23     -2.05,                      // Rmin
24     0.55,                       // Rmax
25     -1.3,                       // Imin
26     1.3,                        // Imax
27     0.0,                        // Rscale
28     0.0,                        // Iscale
29 };
30
31 static inline double sqr(double x)
32 {
33     return x * x;
34 }
35
36 static int check_point(parameters& p, double cr, double ci)
37 {
38     double zr2, zi2;
39     zi2 = sqr(ci);
40     if (sqr(cr + 1) + zi2 < 1.0 / 16.0)
41         return p.maxiter;
42     double x4 = cr - 1.0 / 4.0;
43     double q = sqr(x4) + zi2;
44     if (q * (q + x4) < zi2 / 4.0)
45         return p.maxiter;
46     zr2 = sqr(cr);
47     double zr = cr;
48     double zi = ci;
49     int i;
50     for (i = 0 ; i < p.maxiter && zr2 + zi2 < 4 ; i++) {
51         zi = 2 * zr * zi + ci;
52         zr = zr2 - zi2 + cr;
53         zr2 = sqr(zr);
54         zi2 = sqr(zi);
55     }
56     return i;
57 }
58
59 // int check_point(parameters& p, int x, int y)
60 // {
61 //     double cr = p.Rmin + x * p.Rscale;
62 //     double ci = p.Imax - y * p.Iscale;
63 //     return check_point(p, cr, ci);
64 // }
65
66 static void set_color(DrawingWindow& w, parameters& p, int i)
67 {
68     double rouge, vert, bleu;
69     if (i >= p.maxiter) {
70         rouge = vert = bleu = 0.0;
71     } else {
72         int ii = (p.maxiter - 1 - i) % 96;
73         if (ii < 32) {
74             // vert -> bleu
75             bleu = ii / 32.0;
76             vert = 1.0 - bleu;
77             rouge = 0.0;
78         } else if (ii < 64) {
79             // bleu -> rouge
80             rouge = (ii - 32) / 32.0;
81             bleu = 1.0 - rouge;
82             vert = 0.0;
83         } else {
84             // rouge -> vert
85             vert = (ii - 64) / 32.0;
86             rouge = 1.0 - vert;
87             bleu = 0.0;
88         }
89     }
90     w.setColor(rouge, vert, bleu);
91 }
92
93 // Fonction de dessin de l'ensemble de Madelbrot, dans la zone
94 // spécifiée, et avec la précision souhgaitée.
95 static void do_mandel(DrawingWindow& w, parameters& p)
96 {
97     int x, y;                   // le pixel considéré
98     double cr, ci;              // le complexe correspondant
99
100     int kmax = 4;
101     for (int k = kmax ; k != 0 ; k /= 2) {
102         int kk = 2 * k;
103         for (y = 0 ; y < w.height ; y += k) {
104             ci = p.Imax - y * p.Iscale;
105             cr = p.Rmin;
106             int x0 = 0;
107             int i0 = check_point(p, cr, ci);
108             for (x = k ; x < w.width ; x += k) {
109                 cr = p.Rmin + x * p.Rscale;
110                 if (x % kk != 0 || y % kk != 0 || k == kmax) {
111                     int i = check_point(p, cr, ci);
112                     if (i != i0) {
113                         set_color(w, p, i0);
114                         if (k == 1)
115                             w.drawLine(x0, y, x - 1, y);
116                         else
117                             w.fillRect(x0, y, x - 1, y + k - 1);
118                         i0 = i;
119                         x0 = x;
120                     }
121                 }
122             }
123             set_color(w, p, i0);
124             w.fillRect(x0, y, w.width - 1, y + k - 1);
125         }
126     }
127 }
128     
129 // Fonction de dessin principale, calcule la zone d'intérêt, appelle
130 // do_mandel(), pour dessiner l'ensemle, et permet le zoom.
131 static void mandel(DrawingWindow &w)
132 {
133     parameters p = initial_parameters;
134     while (1) {
135         p.Rscale = (p.Rmax - p.Rmin) / (w.width - 1);
136         p.Iscale = (p.Imax - p.Imin) / (w.height - 1);
137         do_mandel(w, p);
138
139         w.setColor("white");
140         w.drawText(5, 5, "Cliquer sur l'image pour zoomer");
141
142         int x, y;
143         int button;
144         w.waitMousePress(x, y, button);
145
146         // calcul des coordonnées du point cliqué
147         double Tr = p.Rmin + x * p.Rscale;
148         double Ti = p.Imax - y * p.Rscale;
149
150         // calcul de la nouvelle zone d'intérêt :
151         // zoom ×2 en direction du point cliqué
152         const int zoom = 2;
153         double Rmin2 = p.Rmin / zoom;
154         double Rmax2 = p.Rmax / zoom;
155         double Imin2 = p.Imin / zoom;
156         double Imax2 = p.Imax / zoom;
157         double Rshift = Tr - (Rmin2 + Rmax2) / 2;
158         double Ishift = Ti - (Imin2 + Imax2) / 2;
159         Rmin2 += Rshift;
160         Rmax2 += Rshift;
161         Imin2 += Ishift;
162         Imax2 += Ishift;
163
164         // affichage d'un rectangle autour de la nouvelle zone d'intérêt
165         w.setColor("white");
166         w.drawRect((Rmin2 - p.Rmin) / p.Rscale, (p.Imax - Imin2) / p.Iscale,
167                    (Rmax2 - p.Rmin) / p.Rscale, (p.Imax - Imax2) / p.Iscale);
168
169         p.Rmin = Rmin2;
170         p.Rmax = Rmax2;
171         p.Imin = Imin2;
172         p.Imax = Imax2;
173     }
174 }
175
176 int main(int argc, char *argv[])
177 {
178     QApplication app(argc, argv);
179     DrawingWindow win(mandel, 800, 800);
180     win.show();
181     return app.exec();
182 }