вторник, 22 марта 2011 г.

Немного фракталов

1й пост будет о фракталах.
Небольшая справка: Фрактал  — сложная геометрическая фигура, обладающая свойством самоподобия, то есть составленная из нескольких частей, каждая из которых подобна всей фигуре целиком.
Рассмотрим один из самых простых примеров - множество Мандельброта.

Оно описывается итеративной последовательностью на комплексной плоскости.
где С для множества Мандельброта это

x,y координаты текущей точки.
Алгоритм построения до смешного прост, благодаря найденному ещё в начале 20 века условию,  как только модуль z_n\! окажется больше 2, последовательность станет стремиться к бесконечности, т.е. когда сумма квадратов действительной и мнимой частей станут больше 4.
Приведу пример метода на C# который реализует метод построения данного фрактала, вывод происходит в объект img класса Bitmap.

public void GenerateMandelbrot(int Radius,int MaxIter,double step)
{
//Помещаем начало координат в середину изображения
int Mx = img.Width / 2;
int My = img.Height / 2;
//Производим проход по каждой точке и определяем принадлежит ли она множеству
for (int y = -My; y < My; y++)
{              
for (int x = -Mx; x < Mx; x++)
{
double r=x*step,im=y*step;// при изменении положения изменяем начальные значения действительной и мнимой частей
int iterations = 0;//обнуляем итерации при перемещении
while (r * r + im * im < Radius * Radius && iterations<MaxIter)
{
double tmpR = r * r - im * im + x*step;
double tmpIm = 2 * r * im + y*step;
r = tmpR;
im = tmpIm;
iterations++;
}
if (iterations < MaxIter)//В случае если множество ушло в бесконечность делаем пиксель белым
img.SetPixel(Mx + x, My + y, Color.FromArgb(255, 255, 255));
else img.SetPixel(Mx + x, My + y, Color.Black);//Если же он приналежит множеству - чёрным

}
}
}


Radius задаёт как раз тот предел выше которого множество уходит в бесконечность;
MaxIter - максимальное количество итераций после которого мы прерываем наш цикл. Это нужно для нахождения точек принадлежащих множеству, а это точки которые никогда не достигнут предела и не уйдут в бесконечность.
step - позволяет нам выбирать "увеличение" нашего фрактала. т.к. если мы будем работать с реальными масштабами, то уже на 2м пикселе от начала координат наше множество закончиться.
В цикле мы считаем Z пока множество не уйдёт в бесконечность или не пройдёт достаточное количество итераций.
В результате для Radius=2,MaxIter=1000,step=0.003 мы получим такую картину




Естественно чем больше количество итераций, тем более точно наше множеству будет соответствовать правильному множеству.


Теперь же я предлагаю расширить наш метод.
И вместо  
подставить С=a+b*i, которое будет сохранятся константным на всей продолжительности. Также несколько изменим метод окраски. Теперь мы будет красить в 16 оттенков серого. Для этого немного изменим код

public void GenerateMandelbrot(double a,double b,int Radius,int MaxIter,double step)
        {
            int Mx = img.Width / 2;
            int My = img.Height / 2;
            for (int y = -My; y < My; y++)
            {
                
                for (int x = -Mx; x < Mx; x++)
                {
                    double r=x*step,im=y*step;
                    int iterations = 0;
                    while (r * r + im * im < Radius * Radius && iterations<MaxIter)
                    {
                        double tmpR = r * r - im * im + a;
                        double tmpIm = 2 * r * im + b;
                        r = tmpR;
                        im = tmpIm;
                        iterations++;
                    }
                    if (iterations < MaxIter)
                    //Раскраска 16 оттенками серого
                        img.SetPixel(Mx + x, My + y, Color.FromArgb(255 -
(iterations % 16) * 16, 255 - (iterations % 16) * 16, 255 - (iterations % 16) * 16));
                    else img.SetPixel(Mx + x, My + y, Color.Black);

                }
            }
        }
 
Теперь, для a=-1,b=0Radius=2,MaxIter=1000,step=0.003, мы уже имеем довольно интересный фрактал




Если же ещё немного поиграть со значениями(a=0,b=1,Radius=2,MaxIter=1000,step=0.003) то можно получить, например, такое
Можно ещё долго эспериментировать со значениями и получать множество красивых фракталов. В следующей статье я попробую рассказать о разных методах раскраски фракталов, для получения действительно красивых изображений.

Комментариев нет:

Отправить комментарий