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