Фрактал

Материал из Department of Theoretical and Applied Mechanics
Версия от 16:47, 26 июля 2020; Borisenkov (обсуждение | вклад) (Код программы)

Перейти к: навигация, поиск

Программа позволяет строить фрактальные и простые структуры при заданных начальных условиях: координат "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 &emsp;&emsp;&hairsp;&hairsp;<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 &emsp;&emsp;&hairsp;&hairsp;<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 &emsp;&emsp;&hairsp;&hairsp;<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>