Здесь рассказывается о построении фрактальных картинок с помощью JavaScript с выводом в окно Web-браузера. Приводится код программы и сведения о его работе в различных браузерах. Построение фракталов средствами Web-браузеров, разумеется, далеко не лучшая идея в технологическом отношении, но она интересна с точки зрения тестирования браузеров.
Фракталы — очень интересная тема. Однако здесь я не буду
останавливаться на подробном разъяснении понятия фрактала и его применениях. В
Интернете вы легко можете найти соответствующие сведения. Отмечу лишь, что чаще
всего это понятие иллюстрируют различными графическими изображениями (см.рис.),
построенными с помощью программ. Такие изображения сочетают в себе одновременно
некоторую регулярность (как узоры на ковре) и хаотичность (как облака).
Недаром их называют ”упорядоченным хаосом”. Поражает то, что посредством несложных
программ создаются довольно сложные изображения облаков, растений, ландшафтов и
т.п. Таким способом построенные изображения называют фрактальными.
Идея фракталов и область их практического применения значительно глубже и шире, чем рисование фантастических или, наоборот, реалистических картинок. Но здесь не об этом.
В общем виде алгоритм построения фрактального изображения заключается в следующем:
1. Выбираем прямоугольную область на числовой плоскости.
2. Для каждой точки z выбранной области вычисляем ее образ, т.е. новую точку z'=F(z), где F() — некоторая функция.
К полученной точке применяем ту же функцию F(), получая следующую точку.
Данную процедуру повторяем несколько раз, задав некоторое правило ограничения количества таких итераций.
3. В зависимости от количества итераций, выполненных на предыдущем этапе, назначается цвет исходной точки.
4. Каждая окрашенная точка отображается на экране.
Как известно, точка на плоскости задается парой координат (x,y), где x и y — вещественные числа. В то же время точку можно задать комплексным числом вида z=x+yj, где j 2 = -1. В качестве примера функции F(z) преобразования точки z=x+yj можно взять такую:
F(z) = az2 + b,
где z = x+yj — некоторое комплексное число (x, y — координаты точки на числовой плоскости);
a, b — некоторые комплексные числа.
Указанная функция задает так называемое конформное преобразование, при котором фигуры на плоскости преобразуются в себе подобные с изменением масштаба и поворотом.
Пусть zi — точка, полученная на i-ой итерации, тогда на следующей итерации мы получаем точку zi+1 = azi2 + b. Таких итераций можно выполнить сколько угодно, но обычно их количество каким-то образом ограничивают. Например, итеративный процесс прекращают, если полученная точка вышла за пределы круга заданного радиуса с центром в начальной точке или количество выполненных итераций превысило некоторое заданное число. В зависимости от количества выполненных итераций определяется, каким цветом следует окрасить начальную точку.
Очевидно, программу для реализации описанного выше алгоритма
написать нетрудно. Я решил это сделать на JavaScript, чтобы выводить картинки в
окно web-браузера. Хотя программа и не очень сложна, она требует довольно
больших затрат времени и памяти на выполнение. Поэтому тем, кто интересуется
собственно построением фрактальных изображений, лучше использовать другие
средства программирования. Впрочем, существует довольно много готовых программ
для этой цели.
Я сделал два варианта программы:
Программа выполняет необходимые вычисления и формирует
строку, содержащую множество HTML-тегов <div>. Каждый из этих
тегов представляет точку генерируемой фрактальной картинки. Стилевые параметры
задают размеры (у меня — 1x1px) и цвет точки. Затем данная строка тегов
записывается в документ методом document.write().
Ниже приводится CSS- и JavaScript-код программы, рисующей фрактальную картинку.
Опробовать работу программы рисования фрактальной картинки на основе <div> (это может занять до нескольких секунд).
<style>
/* Общие параметры для отображаемой точки */
div.fract {position:absolute;width:1px;height:1px}
</style>
function fractal(x0,y0,xk,yk,dx,kmax,lmax,a,b,mode){ // конструктор
/* Описание:
Данный объект генерирует строку тегов для вывода на экран браузера
фрактальной картинки,вычисленной по простой формуле.
В прямоугольнике с координатами углов (x0,y0) и (xk,yk)
тестируются все точки через интервал dx путем итерационного преобразования:
z(i+1)=F(z(i)),
где z - комплексное число вида x+yi;
F() -функция преобразования комплексного числа в другое комплексное число.
Если на какой-то итерации точка выйдет за круг радиуса lmax с центром
в начальной точке или же количество итераций превысит kmax, исходная точка
окрашивается в цвет, зависящий от номера итерации.
Собственно формула преобразования задается кодом функции next(), а исследование судьбы точки
при итерационном преобразовании — кодом функции explore().
Параметры (свойства):
x0,y0 - начальное число (вещественная и мнимая части комплексного числа)
xk,yk - конечное число (вещественная и мнимая части комплексного числа)
dx - приращение числа в итерации при вычислении функции F()
kmax - максимальное количество итераций (ограничение)
lmax - радиус круга с центром в начальной точке (при выхде из него итерации прекращаются)
mode - задает формулу преобразования координат точек, т.е. функцию z(i+1)=F(z(i)):
если не указан, то z(i+1)=a*z(i)*z(i)+b (a,b — некоторые комплексные числа);
в противном случае z(i+1) определяется несколько иначе (см. функцию next()).
В исходном варианте функция преобразования имеет вид z(i+1)=a*z(i)*z(i)+b.
Метод get() возвращает строку тегов,описывающих фрактальную картинку;
Свойство resume содержит строку отчета о работе;
*/
/* Параметры: */
/* Примеры значений, которые вы можете изменить: */
this.x0=x0||-1.5;
this.y0=y0||-1.5;
this.xk=xk||1.5;
this.yk=yk||1.5;
this.dx=dx||0.01; // приращение чисел
this.kmax=kmax||100;// ограничение итераций
this.lmax=lmax||30; // радиус области
this.a=a; // множитель a в формуле zi+1=a*F(zi)+b
this.b=b; // слагаемое b в формуле zi+1=a*F(zi)+b
this.mode=mode||null; // вид преобразования
this.resume="";
if (!a) this.a=new Array(1,0);
if (!b) this.b=new Array(0,0);
/* Метод, возвращающующий строку тегов для вывода: */
this.get=function() {
var time=new Date(); // хронометраж для отчета
var t0=time.getTime();
var x,y,n;
var x0s=0;
var y0s=0;
var i=0;
var str="";
for (y=this.y0;y<this.yk;y=y+this.dx){
x0s=0;
for (x=this.x0;x<this.xk;x=x+this.dx){
n=explore(x,y,this.kmax,this.lmax,this.a,this.b,this.mode);// судьба точки; возвращает номер итерации
/*** Цвет точки: *******/
if (n>this.kmax) n=this.kmax;
var color="000000"+toh(16715266-n*(16581891/this.kmax));
color="#"+color.substr(color.length-6);
/* Код для отображения точки: */
str+='<div class="fract" style="background:'+color+
'; top:'+y0s+'px;left:'+x0s+'px"'+
'title="'+x.toFixed(3)+','+y.toFixed(3)+'"></div>';
x0s++;
i++;
}
y0s++;
}
var time=new Date(); // хронометраж для отчета
t0=time.getTime()-t0;
/* Отчет: */
this.resume="Отчет\nТочек: "+i+"\nВремя: "+t0+"мс"+"\nБайт: "+str.length;
return str;
}
/*** Функции ***********************************************/
function explore(x,y,kmax,lmax,a,b,mode){ /* исследует судьбу
точки; возвращает номер итерации */
var z,k,q,w;
z=new Array(x,y)
k=0;
while (true){
z=next(z[0],z[1],a,b,mode);
if (x==z[0]&&y==z[1]) return kmax;
k++;
q=(x-z[0]);q=q*q;w=(y-z[1]);w=w*w;
if ((q+w)>lmax*lmax)
return k; // если вышли за пределы области
if (k>kmax) return kmax;// если количество итераций слишком велико
}
}
/***************************************************/
function next(x,y,a,b, mode){ // возвращает координаты следующей точки
/* Возможны различные формулы вычисления */
if (mode){
var x1=Math.sqrt(Math.abs(x*x-y*y));
var y1=Math.sqrt(2*x*y);
}
if (!mode){ // Квадрат (по умолчанию)
var x1=x*x-y*y;
var y1=(2*x*y);
}
x=x1*a[0]-y1*a[1]+b[0];
y=y1*a[0]+x1*a[1]+b[1];
return new Array(x,y);
}
/***************************************************/
function toh(n){ // возвращает 16-е число, соответствующее 10-му числу n
n=Math.round(n);
var hchars="0123456789abcdef" /* строка, содержащая все
шестнадцатеричные цифры */
if (n<16) return hchars.charAt(n);
var i=n%16;
return toh((n-i)/16)+hchars.charAt(i)
}
}
/*****************************************************************/
myfr=new fractal(); // создаем экз. объекта fractal /* Устанавливаем значения свойств: */ myfr.x0=-1; myfr.xk=1; myfr.lmax=100; myfr.kmax=30; myfr.a=new Array(1,0.5); // параметр a myfr.b=new Array(0.5,0.5); /* Получаем строку HTML-кода и записываем в документ: */ document.write(myfr.get()); alert(myfr.resume) // выводим отчет
Опробовать работу программы рисования фрактальной картинки на основе <div>
Перейти к описанию программы рисования фрактальной картинки на основе canvas