Фрактал

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