Визуализация фрактальных структур

"В один прекрасный день под поверхностью океана возникает темный плоский широкий круг с рваными краями и как бы залитый смолой. Через несколько часов он начинает делиться на части, все более расчленяется и одновременно пробивается к поверхности. Наблюдатель мог бы поклясться, что под ним происходит страшная борьба, потому что со всех сторон сюда мчатся похожие на искривленные губы, затягивающиеся кратеры, бесконечные ряды кольцевых волн громоздятся над разлившимся в глубине черным колеблющимся призраком..." Все написанное некогда Станиславом Лемом о невероятных образованиях, возникающих в недрах придуманного им мыслящего океана Соляриса, хорошо подходит к структурам фрактальных множеств Мандельброта и Жюлиа. Редкое математическое открытие в истории человечества удостаивалось столь широкой популярности. Сегодня изображения множества Мандельброта и множества Жюлиа можно встретить где угодно - на рекламных плакатах, обложках многочисленных книг, журналов и т.д. В мировом киберпространстве даже появились целые картинные галереи, поражающие своей завораживающей и странной красотой. Из-за бедных вычислительных возможностей человеческого мозга своеобразная красота этих множеств раньше была скрыта от наших глаз. Теперь же, использовав, к примеру, материал этой статьи, вы можете без особого труда создать собственный фрактальный "микроскоп" и попробовать свои силы в этой новой, недавно возникшей области компьютерного искусства.

Мы привыкли изображать объекты окружающего нас мира как некие сплошные тела с четко обозначенными границами. Но далеко не все формы в природе действительно таковы. Достаточно вспомнить, например, облака или морозные узоры на стеклах. Структуры подобного рода принято называть фрактальными. Множества Мандельброта и Жюлиа тоже представляют собой фрактальные объекты. Они не имеют ясно очерченных контуров. Вернее сказать, эти контуры настолько сложны, что мельчайшие их детали теряются в бесконечности. Последовательно увеличивая фрагменты множеств Мандельброта и Жюлиа, мы будем обнаруживать все новые и новые разнообразные "пейзажи" (см. рис.1 и рис. 2).

Рис. 1


Рис. 2
 

В этом состоит парадоксальная сущность природы фракталов. Благодаря своему бесконечно сложному строению фрактальные "кружева" имеют дробную (!) пространственную размерность. То есть они представляют собой нечто среднее между одномерными линиями и сплошными геометрическими фигурами.

Характерным свойством множеств Мандельброта и Жюлиа является самоподобие их отдельных деталей на разных масштабных уровнях рассмотрения. В отдельных фрагментах пограничных областей множества Мандельброта можно обнаружить многократно уменьшенные копии целого множества. Этот принцип иерархической организации широко распространен в природе и особенно ярко проявляется в мире биологических структур. Убедиться в этом можно, если внимательно рассмотреть лист любого растения или проанализировать форму строения органов (например, легких) у животных организмов. Возможно, в этом принципиальном подобии кроется секрет эстетической привлекательности фрактальных множеств

Умопомрачительная сложность структур множеств Мандельброта и Жюлиа порождается элементарной формулой:

Zi+1=Zi2 + C (1),

где Z и C - комплексные числа. Это совсем не означает, что всякий раз вам придется непременно извлекать немыслимый мнимый корень из минус единицы. Используя правила сложения и умножения комплексных чисел, эту формулу легко заменить двумя традиционными математическими выражениями, не содержащими никаких мнимых сомножителей:

xi+1=xi2 - yi2 + a, yi+1=2xiyi + b. (2)

Суть метода построения множества Мандельброта состоит в следующем. Для каждого пиксела, отображающего некоторую точку с координатами (a, b), проводят серию вычислений по формулам (2). При этом исходные значения x0 и y0 для каждой новой точки (a, b) изначально всегда равны нулю. На каждом шаге, кроме очередных значений xi+1 и yi+1, вычисляют величину ri=sqrt(xi+yi). Эта величина представляет собой не что иное, как расстояние от точки (xi, yi) до начала координат. Точка (a, b) считается принадлежащей множеству Мандельброта, если она в процессе вычислений никогда не удаляется от начала координат на критическое расстояние, большее или равное двум. Такой пиксел окрашивается в черный цвет. Для всех прочих значений a и b величина ri может переходить запретный рубеж в две единицы за разное количество шагов. В зависимости от этого, точку окрашивают в соответствующий цвет.

Критическое значение при программировании фрактального "микроскопа" имеет скорость вычислений. Для того, чтобы работа с программой доставляла удовольствие, код нужно стремиться максимально оптимизировать. Существенно влияют на время расчетов операции возведения в степень и извлечение квадратного корня. Возведение в квадрат целесообразно заменить умножением. Возводить координаты в квадрат следует лишь один раз, сохраняя результаты в промежуточных переменных (X2 и Y2). От извлечения квадратного корня вообще следует отказаться. Вместо самого значения расстояния ri можно вычислять лишь сумму квадратов x2+y2, сравнивая ее не с двойкой, а с четверкой.

Программные процедуры для генерации множества Мандельброта на языке Visual Basic приведены ниже. В зависимости от полученного значения k (обратного счетчика итераций), очередная точка закрашивается в соответствующий цвет (в данном случае точка окрашивается в различные градации серого цвета). Если k оказывается равным нулю, то точка с координатами (a, b) принадлежит множеству Мандельброта. В отношении всех прочих точек имеет значение, насколько велико или мало значение k. Оно характеризует скорость убегания величины ri за дозволенный предел при данных значениях a и b.

DefSng X-Z
DefInt I-N
Private Sub Command1_Click()
Dim c As Long
n = 525
xmin = text1(0).Text
xmax = text1(1).Text
ymin = text1(2).Text
ymax = text1(3).Text
hx = (xmax - xmin) / n
hy = (ymax - ymin) / n
x = xmin
y = ymin
For j = 0 To n
 For i = 0 To n
 c = Mandelbrot(x, y)
 x = x + hx
 Screen.PSet (i, j), c
 Next i
 y = y + hy
 x = xmin
Next j
End Sub
Public Function Mandelbrot(a As Single, b As Single) As Long
Dim k As Byte
x = 0
y = 0
k = 100
Do While r <4 And k> 0
 X2 = x * x
 Y2 = y * y
 xy = x * y
 x = X2 - Y2 + a
 y = 2 * xy + b
 r = X2 + Y2
 k = k - 1
Loop
k = (k / 100) * 255
Mandelbrot = RGB(k, k, k)
End Function

Полное изображение множества Мандельброта можно построить на участке координатной плоскости от -2 до 1 по оси x, и от -1,5 до 1,5 - по оси y (см. рис. 1). Предельное ограничение для количества итераций для одного пиксела задается произвольно. Известно, что для достижения вполне приемлемой точности достаточно 100 итераций. По традиции точки, остающиеся на расстоянии менее 2 единиц от начала координат в течение всех 100 итераций, принято окрашивать в черный цвет и считать принадлежащими множеству Мандельброта. В отношении всех прочих можно поступать как подсказывает интуиция и художественный вкус. Эстетическая привлекательность получаемых изображений очень зависит именно от удачного выбора того или иного цветового решения. Так, например, эффект протянутых в бесконечность полосатых "щупалец" (см. рис. 3) можно получить, окрашивая все точки, для которых число итераций k было четным, - в черный цвет, а те точки, для которых k было нечетное - в белый.

Рис. 3

С отображением (1) связано еще одно фрактальное множество - множество Жюлиа (рис. 4, 5).

Рис. 4


Рис. 5

При построении множества Мандельброта от пиксела к пикселу изменяется значение a и b. Начальные значения x0 и y0 всегда равны нулю. Если же наоборот, изменять значения x0 и y0, выбрав какие-то определенные значения a и b, то в результате получится множество Жюлиа. Множество Жюлиа, как и множество Мандельброта, обладает фрактальными свойствами. Для того, чтобы сгенерировать множество Жюлиа, требуется лишь незначительно модифицировать приведенную программу. Вызывающую процедуру можно оставить той же самой, заменив лишь обращение c = Mandelbrot(x, y) на c=Julia(x, y). В тексте самой подпрограммы-функции надо изменить заголовок и передаваемые параметры x и y принимать не как очередные значения a и b, а как очередные значения x0 и y0.

Public Function Julia(x0 As Single, y0 As Single) As Long
Dim k As Byte
Dim x2 As Single
Dim y2 As Single
Dim xy As Single
a = -0.55
b = -0.55
k = 100
x = x0
y = y0
Do While r <4 And k> 0
 x2 = x * x
 y2 = y * y
 xy = x * y
 x = x2 - y2 + a
 y = 2 * xy + b
 r = x2 + y2
 k = k - 1
Loop
k=(100 / k) * 255
Julia = RGB(k, k, k)
End Function

Мир фракталов не исчерпывается лишь рассмотренными множествами Мандельброта и Жюлиа. Просто они приобрели наибольшую известность у любителей программирования. Фракталы - это весьма обширный класс геометрических объектов. Многие очень интересные самоподобные фрактальные изображения, такие, как, например, треугольник Серпинского, можно получить, используя аффинные преобразования координат. На основе этого подхода ведется разработка методов невероятно эффективного кодирования произвольных изображений, позволяющих добиться сверхвысокой степени сжатия графической информации. Сжатие изображений является одним из наиболее интересных, но далеко не единственным направлением практического использования фрактальной геометрии. Кроме того, фракталы дают богатую пищу для философских размышлений о фундаментальных принципах устройства нашего мира. Исходя из "фрактальной" логики можно заключить, что природе вовсе не обязательно проявлять бесконечную изобретательность. Разнообразие форм, которое мы видим вокруг, в принципе может быть построено при помощи небольшого количества остроумных нелинейных соотношений, способных порождать сложные фракталоподобные структуры.

А.КОЛЕСНИКОВ

Версия для печатиВерсия для печати

Номер: 

16 за 1999 год

Рубрика: 

Азбука программирования
Заметили ошибку? Выделите ее мышкой и нажмите Ctrl+Enter!