Папоротник Барнсли является фрактал названный в честь британского математика Майкла Барнсли , который первым описал его в своей книге Fractals Everywhere . [1] Он сделал его похожим на черную селезенку, Asplenium adiantum-nigrum .
История
Папоротник - один из основных примеров самоподобных множеств, то есть это математически сгенерированный узор, который можно воспроизвести при любом увеличении или уменьшении. Подобно треугольнику Серпинского , папоротник Барнсли показывает, как графически красивые структуры могут быть построены путем многократного использования математических формул с помощью компьютеров. Книга Барнсли 1988 года « Фракталы повсюду» основана на курсе, который он преподавал для студентов и аспирантов в Школе математики Технологического института Джорджии , под названием « Фрактальная геометрия» . После публикации книги был разработан второй курс под названием « Теория фрактальной меры» . [1] Работы Барнсли были источником вдохновения для художников-графиков, пытающихся имитировать природу с помощью математических моделей.
Код папоротника, разработанный Барнсли, является примером системы повторяющихся функций (IFS) для создания фрактала. Это следует из теоремы о коллаже . Он использовал фракталы для моделирования разнообразных явлений в науке и технике, но в особенности структур растений.
IFS предоставляют модели для определенных растений, листьев и папоротников в силу самоподобия, которое часто встречается в ветвящихся структурах в природе. Но природа также демонстрирует случайность и вариации от одного уровня к другому; Нет двух совершенно одинаковых папоротников, и ветвящиеся листья в меньшем масштабе превращаются в листья. Фракталы с V-переменной допускают такую случайность и изменчивость по масштабам, в то же время допуская непрерывную зависимость от параметров, что облегчает геометрическое моделирование. Эти факторы позволяют нам создавать гибридные биологические модели ... ... мы предполагаем, что когда найдена геометрическая фрактальная модель с переменной V, которая хорошо сочетается с геометрией данного растения, то между ними существует определенная взаимосвязь. кодовые деревья и информация, хранящаяся в генах растения.
—Майкл Барнсли и др. [2]
Строительство
Папоротник Барнсли использует четыре аффинных преобразования . Формула для одного преобразования следующая:
Барнсли показывает код IFS для своего фрактала черного папоротника селезенки в виде матрицы значений, представленных в таблице. [3] В таблице столбцы от «a» до «f» представляют собой коэффициенты уравнения, а «p» представляет собой коэффициент вероятности.
ш | а | б | c | d | е | ж | п | Порция произведена |
---|---|---|---|---|---|---|---|---|
ƒ 1 | 0 | 0 | 0 | 0,16 | 0 | 0 | 0,01 | Корень |
ƒ 2 | 0,85 | 0,04 | -0,04 | 0,85 | 0 | 1,60 | 0,85 | Последовательно меньшие листовки |
ƒ 3 | 0,20 | -0,26 | 0,23 | 0,22 | 0 | 1,60 | 0,07 | Самая большая левая листовка |
ƒ 4 | -0,15 | 0,28 | 0,26 | 0,24 | 0 | 0,44 | 0,07 | Самая большая правая листовка |
Им соответствуют следующие преобразования:
Компьютерное поколение
Хотя папоротник Барнсли теоретически можно нарисовать от руки ручкой и миллиметровой бумагой, количество необходимых итераций исчисляется десятками тысяч, что делает использование компьютера практически обязательным. Многие компьютерные модели папоротника Барнсли популярны среди современных математиков. Пока математика запрограммирована правильно с использованием матрицы констант Барнсли, будет получена такая же форма папоротника.
Первая нарисованная точка находится в начале координат ( x 0 = 0, y 0 = 0), а затем новые точки вычисляются итеративно путем случайного применения одного из следующих четырех преобразований координат: [4] [5]
ƒ 1
- х п + 1 = 0
- у н + 1 знак равно 0,16 у н .
Это преобразование координат выбирается в 1% случаев и просто сопоставляет любую точку с точкой в первом линейном сегменте у основания ствола. Эта часть рисунка будет завершена в первую очередь в ходе итераций.
ƒ 2
- x n + 1 = 0,85 x n + 0,04 y n
- у N + 1 знак равно -0,04 х N + 0,85 у N + 1,6.
Это преобразование координат выбирается в 85% случаев и сопоставляет любую точку внутри листовки, представленной красным треугольником, с точкой внутри противоположной, меньшей листовки, представленной синим треугольником на рисунке.
ƒ 3
- x n + 1 = 0,2 x n - 0,26 y n
- у н + 1 знак равно 0,23 х п + 0,22 у п + 1,6.
Это преобразование координат выбирается в 7% случаев и сопоставляет любую точку внутри листочка (или ушной раковины ), представленного синим треугольником, с точкой внутри чередующегося соответствующего треугольника на стержне (оно переворачивает его).
ƒ 4
- х п + 1 = -0,15 х п + 0,28 у п
- y n + 1 знак равно 0,26 x n + 0,24 y n + 0,44.
Это преобразование координат выбирается в 7% случаев и сопоставляет любую точку внутри листочка (или ушной раковины ), представленного синим треугольником, с точкой внутри чередующегося соответствующего треугольника поперек стержня (без его переворачивания).
Первое преобразование координат рисует стержень. Второй создает последовательные копии стебля и нижних листьев, чтобы получился полноценный папоротник. Третий рисует нижний лист слева. Четвертый рисует нижний лист справа. Рекурсивный характер IFS гарантирует, что целое является более крупной копией каждой ветви. Обратите внимание, что полный папоротник находится в диапазоне от -2,1820 < x <2,6558 и 0 ≤ y <9,9983.
Мутантные разновидности
Играя с коэффициентами, можно создавать мутантные разновидности папоротников. В своей статье о фракталах V-переменной Барнсли называет эту особенность суперфракталом . [2]
Один экспериментатор составил таблицу коэффициентов для получения еще одного папоротника удивительно естественно выглядящего, но напоминающего Cyclosorus или Thelypteridaceae . Это: [6] [7]
ш | а | б | c | d | е | ж | п |
---|---|---|---|---|---|---|---|
ƒ 1 | 0 | 0 | 0 | 0,25 | 0 | -0,4 | 0,02 |
ƒ 2 | 0,95 | 0,005 | -0,005 | 0,93 | -0,002 | 0,5 | 0,84 |
ƒ 3 | 0,035 | -0,2 | 0,16 | 0,04 | -0,09 | 0,02 | 0,07 |
ƒ 4 | -0,04 | 0,2 | 0,16 | 0,04 | 0,083 | 0,12 | 0,07 |
Примеры синтаксиса
Вы можете использовать приведенный ниже синтаксис, чтобы нарисовать папоротник самостоятельно.
Python
импорт черепаха импорт случайныйручка = черепаха . Ручка черепаха () . скорость ( 15 ) ручка . цветное ( «синее» ) перо . penup ()x = 0 y = 0 для n в диапазоне ( 110000 ): pen . goto ( 65 * x , 37 * y - 252 ) # 57 - масштабирование папоротника, а -275 - начало рисования снизу. ручка . pendown () ручка . точка () ручка . penup () r = случайный . random () # чтобы получить вероятность r = r * 100 xn = x yn = y if r < 1 : # лестница elif на основе вероятности x = 0 y = 0,16 * yn elif r < 86 : x = 0,85 * xn + 0,04 * yn y = - 0,04 * xn + 0,85 * yn + 1,6 elif r < 93 : x = 0,20 * xn - 0,26 * yn y = 0,23 * xn + 0,22 * yn + 1,6 иначе : x = - 0,15 * xn + 0,28 * yn y = 0,26 * xn + 0,24 * yn + 0,44
р
# Папоротник Барнсли# Создать функцию вероятности и текущей точки fractal_fern2 <- функция ( х , р ) { если ( р <= 0,01 ) { т <- матрица ( с ( 0 , 0 , 0 , . 16 ), 2 , 2 ) е <- C ( 0 , 0 ) } остальное , если ( р <= 0,86 ) { т <- матрица ( с ( . 85 , -.04 , . 04 , . 85 ), 2 , 2 ) е <- с ( 0 , 1.6 ) } иначе , если ( р <= 0,93 ) { т <- матрица ( с ( . 2 , . 23 , -.26 , . 22 ), 2 , 2 ) е <- с ( 0 , 1,6 ) } еще { м <- матрица ( с ( -.15 , . 26 , . 28 , . 24 ), 2 , 2 ) е <- с ( 0 , . 44 ) } м % *% х + е }# количество повторений определяет, насколько детальным будет папоротник повторений <- 10000# создаем вектор со значениями вероятности и матрицу для хранения координат p <- runif ( reps )# инициализируем точку в координатах начала координат <- c ( 0 , 0 )# вычислить фрактальные координаты m <- Reduce ( фрактал_ферн2 , p , накопить = T , init = coords ) m <- t ( do.call ( cbind , m ))# Создать график участка ( m , type = "p" , cex = 0.1 , col = "darkgreen" , xlim = c ( -3 , 3 ), ylim = c ( 0 , 10 ), xlab = NA , ylab = NA , оси = ЛОЖЬ )
Обработка
/ * Папоротник Барнсли для обработки 3.4 * /// объявление переменных x и y float x , y ;// создание холста void setup () { size ( 600 , 600 ); фон ( 255 ); }/ * установка обводки, отображение холста и затем нанесение точек * / void drawPoint () { stroke ( 34 , 139 , 34 ); strokeWeight ( 1 ); float px = map ( x , - 2.1820 , 2.6558 , 0 , ширина ); float py = map ( y , 0 , 9.9983 , height , 0 ); точка ( px , py ); }/ * алгоритм вычисления значения (n + 1) -го члена x и y на основе матриц преобразования * / void nextPoint () { float nextX , nextY ; float r = random ( 1 ); если ( г < 0,01 ) { nextX = 0 ; nextY = 0,16 * y ; } иначе, если ( r < 0,86 ) { nextX = 0,85 * x + 0,04 * y ; nextY = - 0,04 * x + 0,85 * y + 1,6 ; } иначе, если ( r < 0,93 ) { nextX = 0,20 * x - 0,26 * y ; nextY = 0,23 * x + 0,22 * y + 1,6 ; } else { nextX = - 0,15 * x + 0,28 * y ; nextY = 0,26 * x + 0,24 * y + 0,44 ; } x = nextX ; y = nextY ; }/ * повторяем функции построения и вычисления в цикле * / void draw () { for ( int i = 0 ; i < 100 ; i ++ ) { drawPoint (); nextPoint (); } }
P5.JS
пусть x = 0 ; пусть y = 0 ;функция настройки () { createCanvas ( 600 , 600 ); фон ( 0 ); }// диапазон −2,1820 функция drawPoint () { ход ( 255 ); strokeWeight ( 1 ); пусть px = map ( x , - 2.1820 , 2.6558 , 0 , width ); пусть py = map ( y , 0 , 9.9983 , height , 0 ); точка ( px , py ); }функция nextPoint () { let nextX ; let nextY ; пусть r = random ( 1 ); if ( r < 0.01 ) { // 1 nextX = 0 ; nextY = 0,16 * y ; } else if ( r < 0,86 ) { // 2 nextX = 0,85 * x + 0,04 * y ; nextY = - 0,04 * x + 0,85 * y + 1,60 ; } else if ( r < 0,93 ) { // 3 nextX = 0,20 * x + - 0,26 * y ; nextY = 0,23 * x + 0,22 * y + 1,60 ; } else { // 4 nextX = - 0,15 * x + 0,28 * y ; nextY = 0,26 * x + 0,24 * y + 0,44 ; } x = nextX ; y = nextY ; }функция draw () { for ( пусть я = 0 ; я < 1000 ; я ++ ) { drawPoint (); nextPoint (); } }
JavaScript (HTML5)
< canvas id = "canvas" height = "700" width = "700" > canvas >< скрипт > пусть холст ; let canvasContext ; пусть x = 0 , y = 0 ; окно . onload = function () { холст = документ . getElementById ( "холст" ); canvasContext = холст . getContext ( '2d' ); canvasContext . fillStyle = "черный" ; canvasContext . fillRect ( 0 , 0 , холст . ширина , холст . высота ); setInterval (() => { // Обновляем 20 раз каждый кадр для ( let i = 0 ; i < 20 ; i ++ ) update (); }, 1000 / 250 ); // 250 кадров в секунду }; function update () { let nextX , nextY ; пусть r = Math . случайный (); если ( г < 0,01 ) { nextX = 0 ; nextY = 0,16 * y ; } иначе, если ( r < 0,86 ) { nextX = 0,85 * x + 0,04 * y ; nextY = - 0,04 * x + 0,85 * y + 1,6 ; } иначе, если ( r < 0,93 ) { nextX = 0,20 * x - 0,26 * y ; nextY = 0,23 * x + 0,22 * y + 1,6 ; } else { nextX = - 0,15 * x + 0,28 * y ; nextY = 0,26 * x + 0,24 * y + 0,44 ; } // Масштабирование и позиционирование let plotX = canvas . ширина * ( x + 3 ) / 6 ; пусть plotY = холст . высота - холст . высота * (( y + 2 ) / 14 ); drawFilledCircle ( plotX , plotY , 1 , «зеленый» ); x = nextX ; y = nextY ; } const drawFilledCircle = ( centerX , centerY , radius , color ) => { canvasContext . beginPath (); canvasContext . fillStyle = цвет ; canvasContext . дуга ( centerX , centerY , radius , 0 , 2 * Math . PI , true ); canvasContext . fill (); }; скрипт >
QBasic
ЭКРАН 12 ОКНО ( -5 , 0 ) - ( 5 , 10 ) RANDOMIZE ТАЙМЕР ЦВЕТ 10 DO Select Case RND ПРИМЕР IS < .01 nextX = 0 nextY = 0,16 * у ПРИМЕР .01 К .08 nextX = 0,2 * х - 0,26 * у nextY = 0,23 * х + .22 * у + 1.6 ПРИМЕР .08 К .15 nextX = -.15 * х + 0,28 * у nextY = 0,26 * х + 0,24 * у + 0,44 СЛУЧАЙ ИНАЧЕ nextX = 0,85 * х + 0,04 * у nextY = -.04 * х + 0,85 * у + 1.6 END SELECT , х = nextX у = nextY PSET ( х , у ) ЦИКЛ ДО INKEY $ = CHR $ ( 27 )
VBA (CorelDraw)
Саб Барнсли () Dim iEnd As Long Dim i As Long Dim x As Double Dim y As Double Dim nextX As Double Dim nextY As Double Dim sShapeArray () As Shape Dim dSize As Double Dim sColor As String dSize = 0.01 'Размер точек sColor = "0,0,100" ' Цвет точек RGB, диапазон значений от 0 до 255 iEnd = 5000 'Количество итераций ReDim sShapeArray ( iEnd ) ' В Corel для каждого нарисованного объекта требуется имя переменной свой собственный Randomize 'Инициализировать функцию Rnd For i = 0 To iEnd ' Iterate ... Select Case Rnd Case Is < 0,01 ' f1 = Нарисовать основу nextX = 0 nextY = 0,16 * y Case 0,01 To 0,08 'f3 nextX = 0,2 * x - 0,26 * y nextY = 0,23 * x + 0,22 * y + 1,6 Случай 0,08 До 0,15 'f4 nextX = -0,15 * x + 0,28 * y nextY = 0,26 * x + 0,24 * y + 0,44 Case Else ' f2 nextX = 0,85 * x + 0,04 * y nextY = - 0,04 * x + 0,85 * y + 1,6 Выбор конца x = nextX y = nextY Установите sShapeArray ( i ) = ActiveLayer . CreateEllipse2 ( x + 2.5 , y + 0.5 , dSize ) sShapeArray ( i ) . Стиль . StringAssign "{" "fill" ": {" "primaryColor" ":" "RGB255, USER," & sColor & ", 100,00000000-0000-0000-0000-000000000000" "," "secondaryColor" ":" " RGB255, USER, 255,255,255,100,00000000-0000-0000-0000-000000000000 "", "" type "": "" 1 "", "" fillName "": null}, "" outline "": {"" width " ":" "0" "," "color" ":" "RGB255, USER, 0,0,0,100,00000000-0000-0000-0000-000000000000" "}," "прозрачность" ": {}}" DoEvents Следующий Конец подписки
Амола
addpackage ( "Forms.dll")set ( "x", 0)set ( "y", 0)set ( "ширина", 600)set ( "высота", 600) настройка метода ()createCanvas ( ширина , высота )rect ( 0 , 0 , 600 , 600 , цвет ( 0 , 0 , 0 ))конецметод drawPoint () set ( "curX", div (mult (width, add (x, 3)), 6)) set ( "curY", sub (height, mult (height, div (add (y, 2), 14)))) set ( "размер", 1)// журнал ( curX )// журнал ( curY )прямоугольник ( круглый ( curX - размер / 2 ), круглый ( curY - размер / 2 ), круглый ( curX + размер / 2 ), круглый ( curY + размер / 2 ), цветной ( 34 , 139 , 34 ))конецметод nextPoint ()set ( "nextX", 0)set ( "nextY", 0)set ( "случайный", random (0, 100))если ( случайное < 1 )set ( "nextX", 0)set ( "nextY", 0,16 * y)конецещеесли ( случайное < 86 )set ( "nextX", 0,85 * x + 0,04 * y)set ( "nextY", -0,04 * x + 0,85 * y + 1,6)конецещеесли ( случайное < 93 )set ( "nextX", 0,2 * x - 0,26 * y)set ( "nextY", 0,23 * x + 0,22 * y + 1,6)конецещеset ( "nextX", -0,15 * x + 0,28 * y)set ( "nextY", 0,26 * x + 0,24 * y + 0,44)конецконецконецset ( "x", nextX)set ( "y", nextY)конецнастройка ()в то время как ( правда )drawPoint ()nextPoint ()конец
TSQL
/ * таблица результатов * / declare @ fern table ( Fun int , X float , Y float , Seq int identity ( 1 , 1 ) первичный ключ , DateAdded datetime по умолчанию getdate ())declare @ i int = 1 / * итераций * / declare @ fun int / * случайной функции * /объявить @ х флоат = 0 / * Initialise Х = 0 * / DECLARE @ у поплавка = 0 / * Initialise Y = 0 * / DECLARE @ ранда флоат вставки в @ папоротниковых ( Fun , X , Y ) значений ( 0 , 0 , 0 ) / * установить начальную точку * /while @ i < 5000 / * сколько очков? * / начатьустановить @ rand = rand ()select @ Fun = case / * получить случайную функцию для использования - @fun = f1 = 1%, f2 = 85%, f3 = 7%, f4 = 7% * / when @ rand <= 0 . 01, затем 1, когда @ rand <= 0 . 86, затем 2, когда @ rand <= 0 . 93, затем 3, когда @ rand <= 1, затем 4 конецвыберите начало 1 @ X = X , @ Y = Y из порядка @ fern по Seq desc / * получить предыдущую точку * / insert into @ fern ( Fun , X , Y ) / * преобразование с использованием четырех различных функциональных выражений * / select @ fun , case @ fun, когда 1, затем 0, когда 2, затем 0 . 85 * @ х + 0 . 04 * @ y, если 3, то 0 . 2 * @ х - 0 . 26 * @ y, когда 4, то - 0 . 15 * @ х + 0 . 28 * @ y end X , case @ fun когда 1, то 0 . 16 * @ y, когда 2, то - 0 . 04 * @ х + 0 . 85 * @ y + 1 . 6, если 3, то 0 . 23 * @ х + 0 . 22 * @ y + 1 . 6, когда 4, то 0 . 26 * @ х + 0 . 24 * @ y + 0 . 44 конец Yустановить @ i = @ i + 1 конецвыбрать топ 5000 * , география :: Точка ( Y , X , 4326 ) от @ папоротника порядка по NEWID ()
MATLAB
N = 1000000 ; xy = [ 0 ; 0 ]; папоротник = нули ( N , 2 ); f_1 = [ 0 0 ; 0 0,16] ; f_2 = [ 0,85 0,04 ; - 0,04 0,85 ]; f_3 = [ 0,2 - 0,26 ; 0,23 0,22 ]; f_4 = [ - 0,15 0,28 ; 0,26 0,24 ]; P = randsample ( 1 : 4 , N , истина , [ 0,01 0,85 0,07 0,07 ]); для i = 2 : N р = Р ( я - 1 ) если p == 1 % стержень ху = f_1 * ху ; elseif p == 2 % Подписки ху = f_2 * ху + [ 0 ; 1.6 ]; elseif p == 3 % Листовка слева ху = f_3 * ху + [ 0 ; 1.6 ]; else % Правый буклет ху = f_4 * ху + [ 0 ; 0,44 ]; конец папоротник ( i , 1 ) = ху ( 1 ); папоротник ( i , 2 ) = ху ( 2 ); конецclearvars - кроме N папоротник % R2008a + % Создание папоротника% { % Лучшая детализация, более низкая производительность c = linspace (0, 0,35, N - 1); c (конец + 1) = 1; палитра (лето (N)); set (gcf, 'Color', 'k', 'position', [10, 50, 800, 600]); разброс (папоротник (:, 1), папоротник (:, 2), 0.1, c, 'o'); set (gca, 'цвет', 'k'); %}%% Меньше деталей, выше производительностьc = linspace ( 1 , 0,2 , N - 1 ); c ( конец + 1 ) = 0 ; палитра ( лето ( N ));set ( gcf , 'Color' , 'k' , 'position' , [ 10 , 50 , 800 , 600 ]); разброс ( папоротник (:, 1 ), папоротник (:, 2 ), 0.1 , c , '.' ); set ( gca , 'цвет' , 'k' ); %}
Рекомендации
- ^ a b Fractals Everywhere , Бостон, Массачусетс: Academic Press, 1993, ISBN 0-12-079062-9
- ^ Б Майкл Барнсли , и др. , " " V-переменные фракталы и суперфракталы " " (PDF) . (2,22 МБ)
- ^ Fractals Everywhere , таблица III.3, код IFS для папоротника.
- ^ Барнсли, Майкл (2000). Фракталы повсюду . Морган Кауфманн. п. 86. ISBN 0-12-079069-6. Проверено 7 января 2010 .
- ^ Вайсштейн, Эрик. "Папоротник Барнсли" . Проверено 7 января 2010 .
- ^ Другие сорта папоротника с предоставленными коэффициентами
- ^ Генератор папоротника Барнсли