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