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

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

Программа позволяет строить фрактальные и простые структуры при заданных начальных условиях.
Первая версия программы: http://tm.spbstu.ru/Фрактал

Принцип работы

В отличие от первой программы, данная программа требует только задания коэффициентов a11,a12,a21,a22. Дальше происходит следующее:
1. Единичный квадрат разбивается сеткой 100x100 пикселей.

2. Программа проверяет каждую точку этого квадрата, считая координаты точки равными координатам узла соответствующего квадрата сетки, по следующему алгоритму:

а) Единичный квадрат разбивается сеткой 30x30 пикселей, i-ой точке квадрата с сеткой 100x100 сопоставляется точка на квадрате с сеткой 30x30 пикселей.
б) Программа производит 450 итераций расчета координат новых точек, ставя им в соответствие "квадраты" сетки 30x30 пикселей.
в) Подсчитывается площадь, занятая "закрашенными" квадратами 30x30 пикселей. "Закрашенным" квадрат считается, если вычисленная точка попадает в этот квадрат.
г) Если закрашено менее 20 процентов единичного квадрата, делается вывод, что данная точка является частью регулярной области - крупного эллипса, если закрашено более 20 процентов - считается, что это нерегулярная область, которая в большей степени прорисовывает фрактал и является наиболее интересной. Во втором случае точка с данными координатами подсвечивается на экране.
Таким образом программа "отсеивает" регулярные области, оставляя наиболее интересные для рассмотрения.

Код программы

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