Download
pfuentes69
/FractalViewer
/TMandelbrot.cp
(View History)
pfp First commit | Latest amendment: 1 on 2022-08-26 |
1 | /***** |
2 | * TMandelbrot.cp |
3 | * |
4 | * The window methods to draw a Mandelbrot set |
5 | * |
6 | *****/ |
7 | |
8 | #include <Packages.h> // for NumToString prototype |
9 | #include "TFractalViewerWindow.h" |
10 | #include "TMandelbrot.h" |
11 | #include <stdlib.h> |
12 | |
13 | |
14 | /**** |
15 | * TFractalViewerWindow constructor |
16 | * |
17 | * Create a bullseye window. This constructor relies |
18 | * on the TWindow constructor to place the window in |
19 | * in attractive place. Then it appends a number to the |
20 | * window title. |
21 | * |
22 | ****/ |
23 | |
24 | |
25 | TMandelbrot::TMandelbrot(void) |
26 | { |
27 | // Set the width, and show the window. |
28 | PrepareStyles(); |
29 | SetStyle(1); |
30 | SetDrawMode(2); |
31 | // Set the default plane |
32 | DefaultPlane(); |
33 | |
34 | Show(); |
35 | } |
36 | |
37 | |
38 | /**** |
39 | * Hit |
40 | * |
41 | * Handle a mouse down in the window. |
42 | * Bullseye window just force a refresh. |
43 | * |
44 | ****/ |
45 | |
46 | void TMandelbrot::DefaultPlane() |
47 | { |
48 | pWidth = 3.0; |
49 | pHeigth = 3.0; |
50 | pCX = -0.6; |
51 | pCY = 0.0; |
52 | } |
53 | |
54 | |
55 | void TMandelbrot::Hit(Point where) |
56 | { |
57 | Point mouse; |
58 | double sCX, sCY, tX, tY, hX, hY; |
59 | Rect drawingRect; |
60 | |
61 | // Recalculate center |
62 | GlobalToLocal(&where); |
63 | hX = where.h; // - sLeft; |
64 | hY = where.v; // - sTop; |
65 | |
66 | sCX = sWidth / 2.0; |
67 | sCY = sHeigth / 2.0; |
68 | tX = sCX - hX; |
69 | tY = hY - sCY; |
70 | pCX = pCX - pWidth * tX / (double)sWidth; |
71 | pCY = pCY - pHeigth * tY / (double)sHeigth; |
72 | RefreshWindow(false); // preserve the scroll bars |
73 | } |
74 | |
75 | |
76 | /**** |
77 | * DrawShape methods |
78 | * |
79 | * These are the DrawShape methods for |
80 | * TBullWindow: does nothing |
81 | * TCircleBull: Circles |
82 | * TSquareBull: Squares |
83 | * TPlasma: "Triangles" |
84 | * |
85 | * All the DrawShape methods take a drawingRect |
86 | * as a parameter. The pen width |
87 | * is already set to the appropriate width. |
88 | * |
89 | ****/ |
90 | |
91 | int TMandelbrot::Mandelbrot(double real, double imag, short maxiterations) { |
92 | double zReal = real; |
93 | double zImag = imag; |
94 | |
95 | for (int i = 0; i < maxiterations; ++i) { |
96 | double r2 = zReal * zReal; |
97 | double i2 = zImag * zImag; |
98 | if (r2 + i2 > 8.0) |
99 | return i; |
100 | zImag = 2.0 * zReal * zImag + imag; |
101 | zReal = r2 - i2 + real; |
102 | } |
103 | return maxiterations; |
104 | } |
105 | |
106 | |
107 | void TMandelbrot::DrawShape(Rect *drawingRect) |
108 | { |
109 | RGBColor colPix; |
110 | short maxiterations; |
111 | |
112 | switch (drawMode) { |
113 | case 1: |
114 | maxiterations = 20; |
115 | break; |
116 | case 2: |
117 | maxiterations = 100; |
118 | break; |
119 | case 3: |
120 | maxiterations = 200; |
121 | break; |
122 | } |
123 | |
124 | short st = GetStyle() - 1; |
125 | |
126 | sWidth = drawingRect->right - drawingRect->left + 1; |
127 | sHeigth = drawingRect->bottom - drawingRect->top + 1; |
128 | |
129 | pHeigth = (double)sHeigth * pWidth / (double)sWidth; |
130 | |
131 | double x_start = pCX - pWidth / 2.0; |
132 | double x_fin = x_start + pWidth; |
133 | double y_start = pCY - pHeigth / 2.0; |
134 | double y_fin = y_start + pHeigth; |
135 | |
136 | double dx = (x_fin - x_start)/(sWidth - 1); |
137 | double dy = (y_fin - y_start)/(sHeigth - 1); |
138 | |
139 | for (int i = 0; i < sHeigth; i++) { |
140 | for (int j = 0; j < sWidth; j++) { |
141 | double x = x_start + j*dx; // current real value |
142 | double y = y_fin - i*dy; // current imaginary value |
143 | |
144 | int value = Mandelbrot(x, y, maxiterations); |
145 | if (value == maxiterations) { |
146 | colPix.red = 0; |
147 | colPix.green = 0; |
148 | colPix.blue = 0; |
149 | } |
150 | else { |
151 | value = 255 * value / maxiterations; |
152 | colPix = spec[st][value % 255]; |
153 | } |
154 | SetCPixel(j, i, &colPix); |
155 | } |
156 | } |
157 | |
158 | } |
159 | |
160 | |
161 | |
162 | // |
163 | // PREPARE STYLES METHODS |
164 | // |
165 | |
166 | void TMandelbrot::PrepareStyles() |
167 | { |
168 | short ci; |
169 | // Style 1 |
170 | for(ci=0; ci < 256; ci++) { |
171 | spec[0][ci].red = 65536 - ci * 256; |
172 | spec[0][ci].green = 65536 - ci * 256; |
173 | spec[0][ci].blue = 65536 - ci * 256; |
174 | } |
175 | // Style 2 |
176 | for(ci=0; ci < 256; ci++) { |
177 | spec[1][ci].red = ci * 256; |
178 | spec[1][ci].green = ci * 256; |
179 | spec[1][ci].blue = ci * 256; |
180 | } |
181 | // Style 2 |
182 | for(ci=0; ci < 256; ci++) { |
183 | spec[2][ci].red = 65535 - ci * 256; |
184 | spec[2][ci].green = 32768 + ci * 128; |
185 | spec[2][ci].blue = ci * 256; |
186 | } |
187 | // Style 2 |
188 | for(ci=0; ci < 256; ci++) { |
189 | spec[3][ci].red = ci * 256; |
190 | spec[3][ci].green = 32768 + ci * 128; |
191 | spec[3][ci].blue = 65535 - ci * 256; |
192 | } |
193 | // Style 2 |
194 | for(ci=0; ci < 256; ci++) { |
195 | spec[4][ci].red = 32768 - ci * 128; |
196 | spec[4][ci].green = ci * 256; |
197 | spec[4][ci].blue = 65535 - ci * 256; |
198 | } |
199 | } |
200 | |
201 | |
202 | // |
203 | // ZOOM CONTENT |
204 | // |
205 | |
206 | |
207 | void TMandelbrot::ZoomContent(short z) |
208 | { |
209 | switch (z) { |
210 | case -1: |
211 | pWidth = pWidth * 1.333; |
212 | pHeigth = pHeigth * 1.333; |
213 | break; |
214 | case 1: |
215 | pWidth = pWidth * 0.666; |
216 | pHeigth = pHeigth * 0.666; |
217 | break; |
218 | break; |
219 | default: |
220 | DefaultPlane(); |
221 | break; |
222 | } |
223 | |
224 | RefreshWindow(false); // preserve the scroll bars |
225 | } |