Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
* Made *sleep() methods static.
[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 int check_point(parameters& p, double cr, double ci)
32 {
33     double zr = 0.0;
34     double zi = 0.0;
35     double zr2 = 0.0;
36     double zi2 = 0.0;
37     int i;
38     for (i = 0 ; zr2 + zi2 < 4 && i < p.maxiter; i++) {
39         zi = 2 * zr * zi + ci;
40         zr = zr2 - zi2 + cr;
41         zr2 = zr * zr;
42         zi2 = zi * zi;
43     }
44     return i;
45 }
46
47 // int check_point(parameters& p, int x, int y)
48 // {
49 //     double cr = p.Rmin + x * p.Rscale;
50 //     double ci = p.Imax - y * p.Iscale;
51 //     return check_point(p, cr, ci);
52 // }
53
54 void set_color(DrawingWindow& w, parameters& p, int i)
55 {
56     double rouge, vert, bleu;
57     if (i >= p.maxiter) {
58         rouge = vert = bleu = 0.0;
59     } else {
60         int ii = (p.maxiter - 1 - i) % 96;
61         if (ii < 32) {
62             // vert -> bleu
63             bleu = ii / 32.0;
64             vert = 1.0 - bleu;
65             rouge = 0.0;
66         } else if (ii < 64) {
67             // bleu -> rouge
68             rouge = (ii - 32) / 32.0;
69             bleu = 1.0 - rouge;
70             vert = 0.0;
71         } else {
72             // rouge -> vert
73             vert = (ii - 64) / 32.0;
74             rouge = 1.0 - vert;
75             bleu = 0.0;
76         }
77     }
78     w.setColor(rouge, vert, bleu);
79 }
80
81 // Fonction de dessin de l'ensemble de Madelbrot, dans la zone
82 // spécifiée, et avec la précision souhgaitée.
83 void do_mandel(DrawingWindow& w, parameters& p)
84 {
85     int x, y;                   // le pixel considéré
86     double cr, ci;              // le complexe correspondant
87     int iprev = -1;
88
89     int kmax = 16;
90     for (int k = kmax ; k != 0 ; k /= 2) {
91         int kk = 2 * k;
92         double ar = k * p.Rscale;
93         double ai = k * p.Iscale;
94         cr = p.Rmin;
95         for (x = 0 ; x < w.width ; x += k) {
96             ci = p.Imax;
97             for (y = 0 ; y < w.height ; y += k) {
98                 if (x % kk != 0 || y % kk != 0 || k == kmax) {
99                     int i = check_point(p, cr, ci);
100                     if (i != iprev) {
101                         set_color(w, p, i);
102                         iprev = 1;
103                     }
104                     if (k > 2) {
105                         w.fillRect(x, y, x + k - 1, y + k - 1);
106                     } else {
107                         w.drawPoint(x, y);
108                         if (k == 2) {
109                             w.drawPoint(x + 1, y);
110                             w.drawPoint(x, y + 1);
111                             w.drawPoint(x + 1, y + 1);
112                         }
113                     }
114                 }
115                 ci -= ai;
116             }
117             cr += ar;
118         }
119     }
120 }
121     
122 // Fonction de dessin principale, calcule la zone d'intérêt, appelle
123 // do_mandel(), pour dessiner l'ensemle, et permet le zoom.
124 void mandel(DrawingWindow &w)
125 {
126     parameters p = initial_parameters;
127     while (1) {
128         p.Rscale = (p.Rmax - p.Rmin) / (w.width - 1);
129         p.Iscale = (p.Imax - p.Imin) / (w.height - 1);
130         do_mandel(w, p);
131
132         w.setColor("white");
133         w.drawText(5, 5, "Cliquer sur l'image pour zoomer");
134
135         int x, y;
136         int button;
137         w.waitMousePress(x, y, button);
138
139         // calcul des coordonnées du point cliqué
140         double Tr = p.Rmin + x * p.Rscale;
141         double Ti = p.Imax - y * p.Rscale;
142
143         // calcul de la nouvelle zone d'intérêt :
144         // zoom ×2 en direction du point cliqué
145         const int zoom = 2;
146         double Rmin2 = p.Rmin / zoom;
147         double Rmax2 = p.Rmax / zoom;
148         double Imin2 = p.Imin / zoom;
149         double Imax2 = p.Imax / zoom;
150         double Rshift = Tr - (Rmin2 + Rmax2) / 2;
151         double Ishift = Ti - (Imin2 + Imax2) / 2;
152         Rmin2 += Rshift;
153         Rmax2 += Rshift;
154         Imin2 += Ishift;
155         Imax2 += Ishift;
156
157         // affichage d'un rectangle autour de la nouvelle zone d'intérêt
158         w.setColor("white");
159         w.drawRect((Rmin2 - p.Rmin) / p.Rscale, (p.Imax - Imin2) / p.Iscale,
160                    (Rmax2 - p.Rmin) / p.Rscale, (p.Imax - Imax2) / p.Iscale);
161
162         p.Rmin = Rmin2;
163         p.Rmax = Rmax2;
164         p.Imin = Imin2;
165         p.Imax = Imax2;
166     }
167 }
168
169 int main(int argc, char *argv[])
170 {
171     QApplication app(argc, argv);
172     DrawingWindow win(mandel, 800, 800);
173     win.show();
174     return app.exec();
175 }