Фрактал
Материал из 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 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
39 iterations.onchange = function () {
40 N = document.getElementById('number_it').value;
41 }
42
43 butt.onclick = function () {
44 r = Math.floor(Math.random()*256);
45 g = Math.floor(Math.random()*256);
46 b = Math.floor(Math.random()*256);
47 RGB.push(r);
48 RGB.push(g);
49 RGB.push(b);
50 ctx.fillStyle = "rgb("+
51 r+","+
52 g+","+
53 b+")";
54 }
55 update.onclick = function () { ctx.clearRect(0,0,w,h); control(); }
56 a11.onchange = function() {
57 a_11 = parseFloat(document.getElementById('a11').value);
58 document.getElementById('angle_rad').value = 0;
59 document.getElementById('num').value = 0;
60 angle = 0;
61 }
62 a12.onchange = function() {
63 a_12 = parseFloat(document.getElementById('a12').value);
64 document.getElementById('angle_rad').value = 0;
65 document.getElementById('num').value = 0;
66 angle = 0;
67 }
68 a21.onchange = function() {
69 a_21 = parseFloat(document.getElementById('a21').value);
70 document.getElementById('angle_rad').value = 0;
71 document.getElementById('num').value = 0;
72 angle = 0;
73 }
74 a22.onchange = function() {
75 a_22 = parseFloat(document.getElementById('a22').value);
76 document.getElementById('angle_rad').value = 0;
77 document.getElementById('num').value = 0;
78 angle = 0;
79 }
80
81 angle_rad.onchange = function() {
82 angle = parseFloat(document.getElementById('angle_rad').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 if (z != 1) {
91 z2 = x_max - x_min;
92 x = x_min + (event.clientX - rect.left)*z2/scale;
93 y = y_min + (event.clientY - rect.top)*z2/scale;
94 } else {
95 x = (event.clientX - rect.left)/scale;
96 y = (event.clientY - rect.top)/scale;
97 }
98 clear = document.getElementsByName('clear_rect');
99 if (clear[1].checked == true) {
100 r = Math.floor(Math.random()*256);
101 g = Math.floor(Math.random()*256);
102 b = Math.floor(Math.random()*256);
103 RGB.push(r);
104 RGB.push(g);
105 RGB.push(b);
106 ctx.fillStyle = "rgb("+
107 r+","+
108 g+","+
109 b+")";
110 } else {
111 ctx.clearRect(0,0,w,h);
112 X = [];
113 Y = [];
114 ctx.beginPath();
115 ctx.arc(x*scale,y*scale,3,0,2*Math.PI);
116 ctx.strokeStyle = 'blue';
117 ctx.stroke();
118 }
119 X.push(x);
120 Y.push(y);
121
122 if (angle != 0) {
123 a_11 = Math.cos(angle);
124 a_22 = a_11;
125 a_12 = Math.sin(angle);
126 a_21 = -a_12;
127 document.getElementById('a11').value = a_11;
128 document.getElementById('a12').value = a_12;
129 document.getElementById('a21').value = a_21;
130 document.getElementById('a22').value = a_22;
131 }
132
133 control();
134 } else {
135 var rect = cnv.getBoundingClientRect();
136 z2 = x_max - x_min;
137 x_oldmin = x_min*scale;
138 y_oldmin = y_min*scale;
139 x_oldmax = x_max*scale;
140 y_oldmax = y_max*scale;
141 x_min = (event.clientX - rect.left)*z2 + x_oldmin;
142 y_min = (event.clientY - rect.top)*z2 + y_oldmin;
143 x_relativemin = event.clientX - rect.left;
144 y_relativemin = event.clientY - rect.top;
145 ctx.beginPath();
146 ctx.rect(event.clientX - rect.left,event.clientY - rect.top,1,1);
147 ctx.fillStyle = 'blue';
148 ctx.fill();
149 move = true;
150 }
151
152
153 }
154
155 cnv.onmousemove = function () {
156 if (move) {
157 var rect = cnv.getBoundingClientRect();
158 y_move = (event.clientY - rect.top);
159 x_move = (y_move-y_relativemin) + x_relativemin;
160 ctx.beginPath();
161 ctx.arc(x_move,y_move,3,0,2*Math.PI);
162 ctx.fill();
163 }
164 }
165
166 cnv.onmouseup = function () {
167 zoom = document.getElementById('zoom_check');
168 if (zoom.checked) {
169 x_relativemax = x_move;
170 y_relativemax = y_move;
171 y_max = y_move*z2 + y_oldmin;
172 x_max = x_move*z2 + x_oldmin;
173 x_min = x_min/scale;
174 y_min = y_min/scale;
175 x_max = x_max/scale;
176 y_max = y_max/scale;
177 if (x_min > x_max) {
178 intermid = x_min;
179 x_min = x_max;
180 x_max = intermid;
181 }
182 if (y_min > y_max) {
183 intermid = y_min;
184 y_min = y_max;
185 y_max = intermid;
186 }
187 z = z*scale/(x_relativemax - x_relativemin);
188 ctx.clearRect(0,0,w,h);
189 move = false;
190 control();
191 }
192 }
193
194 function Func (numb) {
195 decim = parseFloat(numb) - Math.floor(numb);
196 return(decim);
197 }
198
199 function coord() {
200 way = document.getElementsByName('ways');
201 if (way[0].checked == true) {
202 numb1 = a_11*x+a_12*y;
203 numb2 = a_21*x+a_22*y;
204 x = Func(numb1);
205 y = Func(numb2);
206 }
207 if (way[1].checked == true) {
208 numb1 = a_11*x+a_12*y;
209 x = Func(numb1);
210 numb2 = a_21*x+a_22*y;
211 y = Func(numb2);
212 }
213 }
214 function draw() {
215 zoom = document.getElementById('zoom_check');
216 if ((zoom.checked)||( z != 1)) {
217 if ((x>=x_min)&&(x<=x_max)&&(y>=y_min)&&(y<=y_max)) {
218 ctx.beginPath();
219 ctx.rect((x-x_min)*z*scale,(y-y_min)*z*scale,1,1);
220 ctx.fill();
221 }
222 } else {
223 ctx.beginPath();
224 ctx.rect(x*scale,y*scale,1,1);
225 ctx.fill();
226
227 }
228 }
229
230 function control () {
231 zoom = document.getElementById('zoom_check');
232 if (zoom.checked) {
233 numberof = X.length;
234 for (m = 0; m<numberof; m++) {
235 x = X[m];
236 y = Y[m];
237 r = Number(RGB[m*3]);
238 g = Number(RGB[m*3+1]);
239 b = Number(RGB[m*3+2]);
240 ctx.fillStyle = "rgb("+r+","+g+","+b+")";
241 for (j = 0;j<=N; j++){
242 coord();
243 draw();
244 }
245 }
246 } else {
247 for (j = 0;j<=N; j++){
248 coord();
249 draw();
250 }
251 }
252 }
253
254 function set_exp(N_exp) {
255 var k = Number(N_exp);
256 ctx.clearRect(0,0,w,h);
257 X = [];
258 Y = [];
259 RGB = [];
260 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; }
261 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; }
262 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; }
263 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; }
264 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; }
265 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; }
266 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; }
267 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; }
268 if (N_exp) {
269
270 a11.value = a_11; angle_rad.value = angle;
271 a12.value = a_12; X.push(x); Y.push(y);
272 a21.value = a_21;
273 a22.value = a_22;
274 }
275 r = Math.floor(Math.random()*256);
276 g = Math.floor(Math.random()*256);
277 b = Math.floor(Math.random()*256);
278 RGB.push(r);
279 RGB.push(g);
280 RGB.push(b);
281 ctx.fillStyle = "rgb("+
282 r+","+
283 g+","+
284 b+")";
285 }
286 num.onchange = function() { set_exp(document.getElementById('num').value); control();}
287
288
289 }
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>