Фрактал

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

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

Программа позволяет строить фрактальные и простые структуры при заданных начальных условиях: координат "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 &emsp;&emsp;&hairsp;&hairsp;<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 &emsp;&emsp;&hairsp;&hairsp;<label><b>Режим <I>ZOOM'а</I><input type = 'checkbox' id = 'zoom_check'></b></label>
21 &emsp;&emsp;&hairsp;&hairsp;<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>