Фрактал(2-ая версия программы)

Материал из Department of Theoretical and Applied Mechanics
Перейти к: навигация, поиск

Первая версия программы: http://tm.spbstu.ru/Фрактал
Данная программа осуществляет один из возможных алгоритмов нахождения нерегулярных областей. Понятие регулярной и нерегулярной области введено в разделе "Направление исследований" на странице первой программы.

Принцип работы программы[править]

Аналогично начальным условиям 1-ой версии программы: дан единичный квадрат А, отображаемый программой с разрешением 100x100 пикселей.

Также имеется единичный квадрат Б, не видимый пользователю, с разрешением 30x30 пикселей.
Для каждой из точек, соответствующих "пикселям" квадрата А программа осуществляет следующий алгоритм:

Таким образом, программа упрощенно проверяет каждую точку квадрата на то, к какой области фрактала она относится: регулярной или нерегулярной, и отображает лишь нерегулярные области, наиболее интересные для рассмотрения. Для более детального рассмотрения какой-либо области следует воспользоваться 1-ой программой.

Код программы[править]

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