Фрактал(2-ая версия программы)
Материал из Department of Theoretical and Applied Mechanics
Версия от 00:40, 25 января 2021; Borisenkov (обсуждение | вклад)
Программа позволяет строить фрактальные и простые структуры при заданных начальных условиях.
Первая версия программы: http://tm.spbstu.ru/Фрактал
Принцип работы программы
Аналогично начальным условиям в 1-ой версии программы: дан единичный квадрат.
Программа проверяет каждую точку этого квадрата, считая координаты точки равными координатам узла соответствующего квадрата сетки, по следующему алгоритму:
Таким образом, программа упрощенно проверяет каждую точку квадрата на то, к какой области фрактала она относится: регулярной или нерегулярной, и отображает лишь нерегулярные области, наиболее интересные для рассмотрения.
Код программы
Код программы на языке 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 = 100;
8 var scale2 = 30;
9 var a_11; var a_12; var a_21; var a_22;
10 var numb1; var numb2; var decim;
11 var interv;
12 var clear;
13 var start_draw = document.getElementById('to_start');
14 var move = false;
15 var z = 1;
16 var z2 = 1;
17 // начальные условия
18 a_11 = 1;
19 a_12 = 1;
20 a_21 = 1;
21 a_22 = 1;
22 var x_min = 0; var y_min = 0;
23 var x_max = 1; var y_max = 1;
24 var x_move; var y_move;
25 var x_oldmin = 0;
26 var x_oldmax = scale;
27 var y_oldmin = 0;
28 var y_oldmax = scale;
29 var intermid;
30 var imageData = ctx.createImageData(w,h);
31 var imageData2;
32 var SECCANV = []; // массив пикселей маленького канваса
33 var square; // площадь при конкретных начальных условиях
34 var SQ = []; // массив площадей нерегулярных областей
35 var RGB = []
36 var numbclr; var nz = z;
37 x_minim.innerHTML = x_min.toFixed(2);
38 y_minim.innerHTML = y_min.toFixed(2);
39 x_maxim.innerHTML = x_max.toFixed(2);
40 y_maxim.innerHTML = y_max.toFixed(2);
41
42 for (d = 0; d<24; d++) {
43 RGB.push(Math.floor(Math.random()*256));
44 }
45
46 // заполняем холст непрозрачными белыми пикселями
47 for (i = 0; i<100; i++) {
48 for (j = 0; j<100; j++) {
49 index = parseInt((i*w + j)*4);
50 imageData.data[index+0] = 255;
51 imageData.data[index+1] = 255;
52 imageData.data[index+2] = 255;
53 imageData.data[index+3] = 255;
54 }
55 }
56 ctx.putImageData(imageData,0,0);
57 start_draw.onclick = function () {
58 zoom = document.getElementById('zoom_check');
59 if (!zoom.checked) {
60 clearcanv();
61 square = 0;
62 SQ = [];
63 checking(x_min,y_min,x_max,y_max);
64 } else {
65 alert("Выключите режим зума");
66 }
67 }
68
69 a11.onchange = function() {
70 a_11 = parseFloat(document.getElementById('a11').value);
71 document.getElementById('num').value = 0;
72 }
73 a12.onchange = function() {
74 a_12 = parseFloat(document.getElementById('a12').value);
75 document.getElementById('num').value = 0;
76 }
77 a21.onchange = function() {
78 a_21 = parseFloat(document.getElementById('a21').value);
79 document.getElementById('num').value = 0;
80 }
81 a22.onchange = function() {
82 a_22 = parseFloat(document.getElementById('a22').value);
83 document.getElementById('num').value = 0;
84 }
85
86 cnv.onmousedown = function() {
87 var zoom = document.getElementById('zoom_check');
88 if (zoom.checked) {
89 var rect = cnv.getBoundingClientRect();
90 z2 = x_max - x_min;
91 x_oldmin = x_min*scale;
92 y_oldmin = y_min*scale;
93 x_oldmax = x_max*scale;
94 y_oldmax = y_max*scale;
95 x_min = (event.clientX - rect.left)*z2 + x_oldmin;
96 y_min = (event.clientY - rect.top)*z2 + y_oldmin;
97 x_relativemin = event.clientX - rect.left;
98 y_relativemin = event.clientY - rect.top;
99 move = true;
100 imageData2 = ctx.getImageData(0,0,w,h);
101 }
102 }
103
104 cnv.onmousemove = function () {
105 if (move) {
106 ctx.putImageData(imageData2,0,0);
107 rect = cnv.getBoundingClientRect();
108 y_move = (event.clientY - rect.top);
109 x_move = (y_move-y_relativemin) + x_relativemin;
110 ctx.beginPath();
111 ctx.rect(x_relativemin,y_relativemin,x_move - x_relativemin,y_move - y_relativemin);
112 ctx.fillStyle = 'green';
113 ctx.stroke();
114 }
115 }
116
117 cnv.onmouseup = function () {
118 zoom = document.getElementById('zoom_check');
119 if (zoom.checked) {
120 x_relativemax = x_move;
121 y_relativemax = y_move;
122 y_max = y_move*z2 + y_oldmin;
123 x_max = x_move*z2 + x_oldmin;
124 x_min = x_min/scale;
125 y_min = y_min/scale;
126 x_max = x_max/scale;
127 y_max = y_max/scale;
128 if (x_min > x_max) {
129 intermid = x_min;
130 x_min = x_max;
131 x_max = intermid;
132 }
133 if (y_min > y_max) {
134 intermid = y_min;
135 y_min = y_max;
136 y_max = intermid;
137 }
138 z = z*scale/(x_relativemax - x_relativemin);
139 some_span.innerHTML = "Увеличение в "+z.toFixed(2)+" раз";
140 nz = Math.pow(z,(1/4));
141 scale2 *= nz;
142 clearcanv ();
143 SECCANV = [];
144 SQ = [];
145 square = 0;
146 move = false;
147 checking(x_min,y_min,x_max,y_max);
148 }
149 x_minim.innerHTML = x_min.toFixed(2);
150 y_minim.innerHTML = y_min.toFixed(2);
151 x_maxim.innerHTML = x_max.toFixed(2);
152 y_maxim.innerHTML = y_max.toFixed(2);
153 }
154
155 function Func (numb) {
156 decim = parseFloat(numb) - Math.floor(numb);
157 return(decim);
158 }
159
160 function coord() {
161 numb1 = a_11*x+a_12*y;
162 x = Func(numb1);
163 numb2 = a_21*x+a_22*y;
164 y = Func(numb2);
165 }
166
167 // функция отчистки канваса
168 function clearcanv () {
169 for (i = 0; i<scale; i++) {
170 for (j = 0; j<scale; j++) {
171 index = parseInt((i*w + j)*4);
172 imageData.data[index+0] = 255;
173 imageData.data[index+1] = 255;
174 imageData.data[index+2] = 255;
175 }
176 }
177 ctx.putImageData(imageData,0,0);
178 }
179
180 function checking (xmin,ymin,xmax,ymax) {
181 for (i = 0;i<scale; i++) {
182 for (j = 0;j<scale; j++) {
183 SECCANV = [];
184 square = 0;
185 x = xmin + j*(xmax - xmin)/scale;
186 y = ymin + i*(ymax - ymin)/scale;
187 index = Math.floor(x*scale2)*scale2 + Math.floor(y*scale2);
188 draw_check = control(index);
189 if (draw_check == 1) {
190 index = parseInt((i*w + j)*4);
191 if (numbclr == -1) {
192 numbclr = SQ.length;
193 SQ.push(square);
194 }
195 if (numbclr>7) {
196 numbclr = (numbclr - 1)%8;
197 }
198 imageData.data[index+0] = RGB[numbclr*3];
199 imageData.data[index+1] = RGB[numbclr*3+1];
200 imageData.data[index+2] = RGB[numbclr*3+2];
201 }
202 }
203 }
204 ctx.putImageData(imageData,0,0);
205 }
206
207 function control(ind) {
208 numbclr = -1;
209 SECCANV[ind] = 1;
210 square += 1;
211 for (k = 0; k<parseInt(600*nz); k++) {
212 coord();
213 idx = Math.floor(x*scale2)*Math.floor(scale2) + Math.floor(y*scale2);
214 if (SECCANV[idx] != 1) { SECCANV[idx] = 1; square+= 1;}
215 }
216 if (square >=parseInt(180*nz)) {
217 if (SQ == []) {
218 SQ.push(square);
219 numbclr = 0;
220 } else { for (m = 0; m<SQ.length; m++) {
221 if (square == SQ[m]) { numbclr = m; break;}
222 }
223 }
224 return(1);
225 } else { return(0); }
226 }
227
228
229 function set_exp(N_exp) {
230 var k = Number(N_exp);
231 clearcanv ();
232 SQ = [];
233 if (N_exp == 1) {a_11 = 1; a_12 = 0.5; a_21 = -0.5; a_22 = 1; }
234 if (N_exp == 2) {a_11 = 1; a_12 = 1; a_21 = -0.9; a_22 = 1; }
235 if (N_exp) {
236
237 a11.value = a_11;
238 a12.value = a_12;
239 a21.value = a_21;
240 a22.value = a_22;
241 }
242 }
243
244 num.onchange = function() { x_min = 0; y_min = 0; x_max = 1; y_max = 1; set_exp(document.getElementById('num').value); checking(x_min,y_min,x_max,y_max);}
245
246 }
html - файл:
1 <html>
2 <head>
3 <meta charset="UTF-8">
4 <title> Fractals </title>
5 <script src = 'Fractals17_11_20.js'>
6 </script>
7 </head>
8 <body>
9 <p align = 'left'><canvas id = 'cnv' width = 100 height = 100 style='border: 1px solid black;'></canvas></p>
10 <span id=some_span></span>
11 <br><b>Рассматриваемая область: x_min = <span id =x_minim></span> , y_min = <span id =y_minim></span>, x_max = <span id=x_maxim></span>, y_max = <span id=y_maxim></span>
12 <br><b>(*) Задайте коэффициенты: </b>
13                  <label><input type='text' id='a11' value='1' ><b>A_11</b></label>
14 <label><input type='text' id='a12' value='1' ><b>A_12</b></label>
15 <br><b>(*) Включить очистку холста после клика? </b>
16 <label><input type = 'radio' name = 'clear_rect' value = 'yes'><b>Да</b></label>
17 <label><input type = 'radio' name = 'clear_rect' value = 'no' checked><b>Нет</b></label>
18     <label><input type='text' id='a21' value='1' ><b>A_21</b></label>
19 <label><input type='text' id='a22' value='1' ><b>A_22</b></label>
20 </br>
21     <label><b>Режим <I>ZOOM'а</I><input type = 'checkbox' id = 'zoom_check'></b></label>
22 <br><b> Выберите номер эксперимента:</b>
23 <input type='number' size='1' id = 'num' min='1' max='2' value='0' step='1'>
24 <input type = 'button' style="width:200px;height:40px" id = 'to_start' value = 'Запуск '></b></br>
25 </body>
26 </html>