Фрактал

Материал из Department of Theoretical and Applied Mechanics
Версия от 16:36, 1 августа 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 	
 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 &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>