Фрактал
Материал из Department of Theoretical and Applied Mechanics
Программа позволяет строить фрактальные и простые структуры при заданных начальных условиях: координат "x" и "y" исходной точки, от которой будут высчитываться координаты остальных, и коэффициентах, участвующих в расчетах. Или же расчет новых точек можно задать с помощью задания угла поворота исходной
Код программы
Код программы на языке JavaScript:
1 window.addEventListener('load',main,false);
2 function main () {
3 var x; var y;
4 var x_fix , y_fix;
5 var ctx = cnv.getContext('2d');
6 var h = cnv.height;
7 var w = cnv.width;
8 var scale = 1000;
9 var a_11; var a_12; var a_21; var a_22;
10 var numb1; var numb2; var decim;
11 var interv;
12 a_11 = 1;
13 a_12 = 1;
14 a_21 = 1;
15 a_22 = 1;
16 var N = 200000;
17 var angle = 0;
18 var way;
19 var clear;
20 var butt = document.getElementById('addButton');
21 X = []; // массив начальных иксов
22 Y = []; // массив начальных игриков
23 var move = false;
24 var x_min = 0; var y_min = 0;
25 var x_max = 1; var y_max = 1;
26 var x_move; var y_move;
27 var x_oldmin = 0;
28 var x_oldmax = 1000;
29 var y_oldmin = 0;
30 var y_oldmax = 1000;
31 var numberof;
32 var z = 1;
33 var RGB = [];
34 var z2 = 1;
35 var iterations = document.getElementById('number_it');
36
37 iterations.onchange = function () {
38 N = document.getElementById('number_it').value;
39 }
40
41 a11_ch.onchange = function() {
42 ctx.clearRect(0,0,w,h);
43 a_11 = document.getElementById('a11_ch').value;
44 document.getElementById('a11').value = a_11;
45 control();
46 x = x_fix;
47 y = y_fix;
48 }
49 a12_ch.onchange = function() {
50 ctx.clearRect(0,0,w,h);
51 a_12 = document.getElementById('a12_ch').value;
52 document.getElementById('a12').value = a_12;
53 control();
54 x = x_fix;
55 y = y_fix;
56 }
57 a21_ch.onchange = function() {
58 ctx.clearRect(0,0,w,h);
59 a_21 = document.getElementById('a21_ch').value;
60 document.getElementById('a21').value = a_21;
61 control();
62 x = x_fix;
63 y = y_fix;
64 }
65 a22_ch.onchange = function() {
66 ctx.clearRect(0,0,w,h);
67 a_22 = document.getElementById('a22_ch').value;
68 document.getElementById('a22').value = a_22;
69 control();
70 x = x_fix;
71 y = y_fix;
72 }
73
74 butt.onclick = function () {
75 r = Math.floor(Math.random()*256);
76 g = Math.floor(Math.random()*256);
77 b = Math.floor(Math.random()*256);
78 RGB.push(r);
79 RGB.push(g);
80 RGB.push(b);
81 ctx.fillStyle = "rgb("+
82 r+","+
83 g+","+
84 b+")";
85 }
86 a11.onchange = function() {
87 a_11 = parseFloat(document.getElementById('a11').value);
88 document.getElementById('angle_rad').value = 0;
89 document.getElementById('num').value = 0;
90 angle = 0;
91 }
92 a12.onchange = function() {
93 a_12 = parseFloat(document.getElementById('a12').value);
94 document.getElementById('angle_rad').value = 0;
95 document.getElementById('num').value = 0;
96 angle = 0;
97 }
98 a21.onchange = function() {
99 a_21 = parseFloat(document.getElementById('a21').value);
100 document.getElementById('angle_rad').value = 0;
101 document.getElementById('num').value = 0;
102 angle = 0;
103 }
104 a22.onchange = function() {
105 a_22 = parseFloat(document.getElementById('a22').value);
106 document.getElementById('angle_rad').value = 0;
107 document.getElementById('num').value = 0;
108 angle = 0;
109 }
110
111 angle_rad.onchange = function() {
112 angle = parseFloat(document.getElementById('angle_rad').value);
113 document.getElementById('num').value = 0;
114 }
115
116 cnv.onmousedown = function() {
117 var zoom = document.getElementById('zoom_check');
118 if (!zoom.checked) {
119 var rect = cnv.getBoundingClientRect();
120 if (z != 1) {
121 z2 = x_max - x_min;
122 x = x_min + (event.clientX - rect.left)*z2/scale;
123 y = y_min + (event.clientY - rect.top)*z2/scale;
124 } else {
125 x = (event.clientX - rect.left)/scale;
126 y = (event.clientY - rect.top)/scale;
127 }
128 x_fix = x;
129 y_fix = y;
130 clear = document.getElementsByName('clear_rect');
131 if (clear[1].checked == true) {
132 r = Math.floor(Math.random()*256);
133 g = Math.floor(Math.random()*256);
134 b = Math.floor(Math.random()*256);
135 RGB.push(r);
136 RGB.push(g);
137 RGB.push(b);
138 ctx.fillStyle = "rgb("+
139 r+","+
140 g+","+
141 b+")";
142 } else {
143 ctx.clearRect(0,0,w,h);
144 X = [];
145 Y = [];
146 ctx.beginPath();
147 ctx.arc(x*scale,y*scale,3,0,2*Math.PI);
148 ctx.strokeStyle = 'blue';
149 ctx.stroke();
150 }
151 X.push(x);
152 Y.push(y);
153
154 if (angle != 0) {
155 a_11 = Math.cos(angle);
156 a_22 = a_11;
157 a_12 = Math.sin(angle);
158 a_21 = -a_12;
159 document.getElementById('a11').value = a_11;
160 document.getElementById('a12').value = a_12;
161 document.getElementById('a21').value = a_21;
162 document.getElementById('a22').value = a_22;
163 document.getElementById('a11_ch').value = a_11;
164 document.getElementById('a12_ch').value = a_12;
165 document.getElementById('a21_ch').value = a_21;
166 document.getElementById('a22_ch').value = a_22;
167 }
168
169 control();
170 } else {
171 var rect = cnv.getBoundingClientRect();
172 z2 = x_max - x_min;
173 x_oldmin = x_min*scale;
174 y_oldmin = y_min*scale;
175 x_oldmax = x_max*scale;
176 y_oldmax = y_max*scale;
177 x_min = (event.clientX - rect.left)*z2 + x_oldmin;
178 y_min = (event.clientY - rect.top)*z2 + y_oldmin;
179 x_relativemin = event.clientX - rect.left;
180 y_relativemin = event.clientY - rect.top;
181 ctx.beginPath();
182 ctx.rect(event.clientX - rect.left,event.clientY - rect.top,1,1);
183 ctx.fillStyle = 'blue';
184 ctx.fill();
185 move = true;
186 }
187
188
189 }
190
191 cnv.onmousemove = function () {
192 if (move) {
193 var rect = cnv.getBoundingClientRect();
194 y_move = (event.clientY - rect.top);
195 x_move = (y_move-y_relativemin) + x_relativemin;
196 ctx.beginPath();
197 ctx.arc(x_move,y_move,3,0,2*Math.PI);
198 ctx.fill();
199 }
200 }
201
202 cnv.onmouseup = function () {
203 zoom = document.getElementById('zoom_check');
204 if (zoom.checked) {
205 x_relativemax = x_move;
206 y_relativemax = y_move;
207 if (y_move < y_min) {
208 y_max = y_min;
209 y_min = y_move*z2 + y_oldmin;
210 x_max = x_min;
211 x_min = x_move*z2 + x_oldmin;
212 } else {
213 y_max = y_move*z2 + y_oldmin;
214 x_max = x_move*z2 + x_oldmin;
215 }
216 x_min = x_min/scale;
217 y_min = y_min/scale;
218 x_max = x_max/scale;
219 y_max = y_max/scale;
220
221 z = z*scale/(x_relativemax - x_relativemin);
222 ctx.clearRect(0,0,w,h);
223 move = false;
224 control();
225 }
226 }
227
228 function Func (numb) {
229 decim = parseFloat(numb) - Math.floor(numb);
230 return(decim);
231 }
232
233 function coord() {
234 zoom = document.getElementById('zoom_check');
235 way = document.getElementsByName('ways');
236 if (way[0].checked == true) {
237 numb1 = a_11*x+a_12*y;
238 numb2 = a_21*x+a_22*y;
239 x = Func(numb1);
240 y = Func(numb2);
241 }
242 if (way[1].checked == true) {
243 numb1 = a_11*x+a_12*y;
244 x = Func(numb1);
245 numb2 = a_21*x+a_22*y;
246 y = Func(numb2);
247 }
248 }
249 function draw() {
250 zoom = document.getElementById('zoom_check');
251 if (zoom.checked) {
252 if ((x>x_min)&&(x<x_max)&&(y>y_min)&&(y<y_max)) {
253 ctx.beginPath();
254 ctx.rect((x-x_min)*z*scale,(y-y_min)*z*scale,1,1);
255 ctx.fill();
256 }
257 } else {
258 if (z != 1) {
259 if ((x>x_min)&&(x<x_max)&&(y>y_min)&&(y<y_max)) {
260 ctx.beginPath();
261 ctx.rect((x-x_min)*z*scale,(y-y_min)*z*scale,1,1);
262 ctx.fill();
263 }
264 } else {
265 ctx.beginPath();
266 ctx.rect(x*scale,y*scale,1,1);
267 ctx.fill();
268
269 }
270 }
271 }
272
273 function control () {
274 zoom = document.getElementById('zoom_check');
275 if (zoom.checked) {
276 numberof = X.length;
277 for (m = 0; m<numberof; m++) {
278 x = X[m];
279 y = Y[m];
280 r = Number(RGB[m*3]);
281 g = Number(RGB[m*3+1]);
282 b = Number(RGB[m*3+2]);
283 ctx.fillStyle = "rgb("+r+","+g+","+b+")";
284 for (j = 0;j<=N; j++){
285 coord();
286 draw();
287 }
288 }
289 } else {
290 for (j = 0;j<=N; j++){
291 coord();
292 draw();
293 }
294 }
295 }
296
297 function set_exp(N_exp) {
298 var k = Number(N_exp);
299 ctx.clearRect(0,0,w,h);
300 X = [];
301 Y = [];
302 RGB = [];
303 if (N_exp == 1) { document.getElementsByName('ways')[1].checked = true; x = 0.34; y = 0.31; angle = 0; a_11 = 1; a_12 = 0.5; a_21 = -0.5; a_22 = 1; }
304 if (N_exp == 2) { document.getElementsByName('ways')[0].checked = true; x = 1/4; y = 1/4; angle = 0; a_11 = 1; a_12 = 0.01; a_21 = 0.01; a_22 = -1; }
305 if (N_exp == 3) { document.getElementsByName('ways')[0].checked = true; x = 1/2; y = 1/2; angle = 0; a_11 = 1; a_12 = 0.32; a_21 = 0.32; a_22 = -1; }
306 if (N_exp == 4) { document.getElementsByName('ways')[0].checked = true; x = 1/2; y = 1/2; angle = 0; a_11 = 0.9; a_12 = 0.1; a_21 = -0.1; a_22 = 1.2; }
307 if (N_exp == 5) { document.getElementsByName('ways')[1].checked = true; x = 1/4; y = 1/4; angle = 3; a_11 = Math.cos(angle); a_12 = Math.sin(angle); a_21 = -a_12; a_22 = a_11; }
308 if (N_exp == 6) { document.getElementsByName('ways')[0].checked = true; x = 1/2; y = 1/2; angle = 0; a_11 = 1; a_12 = 1.5; a_21 = 0.01; a_22 = -1; }
309 if (N_exp == 7) { document.getElementsByName('ways')[0].checked = true; x = 1/2; y = 1/2; angle = 0; a_11 = 1; a_12 = 0.1296; a_21 = -0.1296; a_22 = 1; }
310 if (N_exp == 8) { document.getElementsByName('ways')[0].checked = true; x = 1/4; y = 1/4; angle = 0; a_11 = -0.05; a_12 = -0.95; a_21 = 1.1; a_22 = 0.65; }
311 x_fix = x; y_fix = y;
312 if (N_exp) {
313
314 a11.value = a_11; a11_ch.value = a_11; angle_rad.value = angle; X.push(x); Y.push(y);
315 a12.value = a_12; a12_ch.value = a_12; X.push(x); Y.push(y);
316 a21.value = a_21; a21_ch.value = a_21;
317 a_22.value = a_22; a22_ch.value = a_22;
318 }
319 r = Math.floor(Math.random()*256);
320 g = Math.floor(Math.random()*256);
321 b = Math.floor(Math.random()*256);
322 RGB.push(r);
323 RGB.push(g);
324 RGB.push(b);
325 ctx.fillStyle = "rgb("+
326 r+","+
327 g+","+
328 b+")";
329 }
330 num.onchange = function() { set_exp(document.getElementById('num').value); control();}
331
332
333 }
html - файл:
1 <html>
2 <head>
3 <meta charset="UTF-8">
4 <title> Fractals </title>
5 <script src = 'Fractals.js'>
6 </script>
7 </head>
8 <body>
9 <p align = 'left'><canvas id = 'cnv' width = 1000 height = 1000 style='border: 1px solid black;'></canvas></p>
10 <b>(*) Задайте коэффициенты (в графе угла должен стоять "0"):</b>
11 <label><input type='text' id='a11' value='1' ><b>A_11</b></label>
12 <label><input type='text' id='a12' value='1' ><b>A_12</b></label>
13     <label><input type='text' id='number_it' value ='200000'><b>Количество итераций</b></label>
14 <br><b>(*) Включить очистку холста после клика? </b>
15 <label><input type = 'radio' name = 'clear_rect' value = 'yes'><b>Да</b></label>
16 <label><input type = 'radio' name = 'clear_rect' value = 'no' checked><b>Нет</b></label>
17     <label><input type='text' id='a21' value='1' ><b>A_21</b></label>
18 <label><input type='text' id='a22' value='1' ><b>A_22</b></label>
19 </br>
20 <br><b> Или меняйте коэффициенты с помощью ползунков:</b>
21     <label><b>Режим <I>ZOOM'а</I><input type = 'checkbox' id = 'zoom_check'></b></label>
22 <br><input type = 'range' id='a11_ch' min = '-2' max = '2' step = '0.05' value = '1'>
23 <input type = 'range' id='a12_ch' min = '-2' max = '2' step = '0.05' value = '1'>
24 <br><input type = 'range' id='a21_ch' min = '-2' max = '2' step = '0.05' value = '1'>
25 <input type = 'range' id='a22_ch' min = '-2' max = '2' step = '0.05' value = '1'>
26 <br><b> Выберите номер эксперимента:</b>
27 <input type='number' size='1' id = 'num' min='1' max='8' value='0' step='1'>
28 <br><b> <input type='button' id='addButton' value='Сменить цвет рисовки'>
29 <b>Способ вычисления новых точек:</b>
30 <input type = 'radio' name='ways' value = 'old' checked> <b>1-ый</b>
31 <input type = 'radio' name='ways' value = 'new'><b> 2-ой</b></br>
32 <br>
33 <b>Рисование с помощью поворота точки на заданный угол</b>
34 <label><input type='text' id='angle_rad' value ='0'><b> Угол поворота (в <I> радианах</I>)</b></label>
35 </body>
36 </html>