![](https://habrastorage.org/webt/jb/ki/nd/jbkindqzsklr0ly3xblx8lkrgfc.png)
В статье присутствуют Gif (трафик!) и контрастные картинки. У эпилептиков может случиться эпилептический припадок.
Предыдущие части: 0, 1, 2.
Для начала вспомним, что за «бильярдные фракталы».
Бильярдные фракталы.
Есть у нас некоторая прямоугольная область («бильярд»), в которой движется бильярдный шар (или луч света).
![](https://habrastorage.org/webt/jv/jf/wh/jvjfwhbyinonpkoh0orhozxc-_k.png)
Шар упруго отражается от стенок по законам оптики (угол отражения равен углу падения). При этом шар бесконечно мал (абстрактная «материальная точка» из физики) и при движении и отражении скорости не меняет (скорость нас вообще не интересует).
Когда шар касается одной из выбранных стенок (не важно, какую стенку выбирать, но для примера выберем верхнюю) — фиксируем, в какую сторону движется шар — в левую или в правую:
![](https://habrastorage.org/webt/7f/5u/fo/7f5ufotnextd8w4gxo-8gsflmfc.png)
![](https://habrastorage.org/webt/gs/mr/3l/gsmr3ld3pj8ids2poajw8xlewi8.png)
Для бильряда, соотношение сторон которого — иррациональное число, последовательность отражений — фрактальная (насколько этот термин применим к двоичным последовательностям). Или фракталообразующая. Если визуализировать такую последовательность с помощью черепашьей графики, мы получим фрактал.
В качестве примера можем использовать последовательность для бильярда, соотношение сторон которого равно
Строить такие последовательность очень легко:
Берем поочередно каждое целое число
let a=[];
for(let x=0;x<100;x++) a[x]=Math.floor(x*Math.sqrt(2))%2;
console.log(a.join(''));
Первые 100 элементов этой последовательности:
0100110110010011001001101100110110010011011001101100100110010011011001001100100110110011011001001100
Визуализация этой последовательности с помощью черепашьей графики дает нам следующую фигуру:
![](https://habrastorage.org/webt/ka/n-/l4/kan-l4lbqdwkd0eqibmgcfcvydu.png)
Более подробно о том, откуда взялась эта формула и о визуализации последовательностей с помощью черепашьей графики, можно почитать во второй части — Фракталы в иррациональных числах
В реальном мире.
В реальном мире, такие последовательности встречаются гораздо чаще, чем может показаться на первый взгляд. Два примера.
Пример 1. Есть у нас два человека. Один побольше, второй — поменьше:
![](https://habrastorage.org/webt/sf/j7/cn/sfj7cnpwsfr4qih-kucjbgk5g88.jpeg)
Эти два человека идут по улице. У высокого шире шаг, чем у низкого. Чтобы успевать за высоким, низкому приходится быстрее ногами двигать и больше шагов делать. В каждый момент времени, когда низкий ставит правую ногу на асфальт, фиксируем какая нога высокого находится в воздухе — левая или правая. Если частоты шагов низкого и высокого несинхронизированные — получим фрактальную последовательность.
Пример 2. Вокруг некоторой планеты вращается спутник:
![](https://habrastorage.org/webt/br/ss/tk/brsstkwrsvqssdohsfvrgfmymwm.jpeg)
Выбираем временной интервал
Для наглядности, посмотрим на геометрическую интерпретацию бильярдных последовательностей.
Дискретизация линейной функции.
![](https://habrastorage.org/webt/p6/js/qt/p6jsqtpd_jtmuwkbum24g5gm7i8.png)
Для бильярда, соотношение сторон которого равно
Фактически, все что мы сделали, чтобы получить фрактальную последовательность — дискретизировали линейную функцию с иррациональным коэффициентом
Но прежде, чем переходить к нелинейным функциям, хотелось бы упомянуть об одном интересном наблюдении, сделанном в процессе написания статьи.
Об одном интересном наблюдении.
Возьмем нашу последовательность:
И построим из нее другую последовательность:
Первый элемент последовательности — произвольное число. Каждый следующий элемент — увеличиваем предыдущий элемент на 1, если соответствующий элемент первой последовательности (
let a=[50];
for(let x=1;x<size;x++){
if(Math.floor(x*Math.sqrt(2))%2==1)
a[x]=a[x-1]+1;
else
a[x]=a[x-1]-1;
}
После чего можем построить фрактальную кривую, отметив на графике точки с координатами
for(let x=0;x<size;x++){
context.fillRect(x, a[x], 1, 1);
}
![](https://habrastorage.org/webt/yw/ca/3f/ywca3fptp_twj3mnj8licu06rma.png)
Из этой же кривой можем получить фрактальную поверхность. Для каждой точки
Дальше можем сделать срез плоскости по оси
![](https://habrastorage.org/webt/hk/lg/tf/hklgtfrha_g6f32flh3hrz8jqhi.gif)
Или отметить такие точки, для которых
![](https://habrastorage.org/webt/oh/ii/4h/ohii4hsutvssloqblbvswdqjxly.png)
Следующая картинка — чем больше
![](https://habrastorage.org/webt/jj/c1/fa/jjc1farjzke02ooyxkyjv2x4ros.png)
Можем немного изменить последовательность:
Раскрыв скобки, получим:
Здесь
Как это выглядит в бильярдной модели? Мы увеличиваем предыдущий элемент последовательности на расстояние (по оси
![](https://habrastorage.org/webt/xf/ei/ka/xfeikada1ssvsqkeu9ksi_twnts.png)
![](https://habrastorage.org/webt/l1/p6/cd/l1p6cdzksajczyviclzq6zkxg1e.png)
let c, arr=[0];
for(let i=1;i<size;i++){
c=i*Math.sqrt(2);
if(Math.floor(c)%2){
arr[i]=arr[i-1]+(c-Math.floor(c));
}else{
arr[i]=arr[i-1]-(1-(c-Math.floor(c)));
}
}
После раскрытия скобок:
let c, arr=[0];
for(let i=1;i<size;i++){
c=i*Math.sqrt(2);
arr[i]=arr[i-1]+(c-Math.floor(c));
if(Math.floor(c)%2!=1){
arr[i]--;
}
}
let c, arr=[0];
for(let i=1;i<size;i++){
c=i*Math.sqrt(2);
arr[i]=arr[i-1]+(c-Math.floor(c));
}
В этом случае поверхность получится гладкой, а не фрактальной.
Делаем визуализацию тем же способом, который использовали выше. Для каждой точки
![](https://habrastorage.org/webt/i0/a-/hb/i0a-hbahpsxy0lcjnlhcasolkes.png)
До того, как мы изменили последовательность, все
![](https://habrastorage.org/webt/ew/6i/1x/ew6i1xsfz6itokwbbn264ma3bnk.png)
Самое интересное получится, если мы отметим пиксели, для которых
478:
![](https://habrastorage.org/webt/ls/wj/zx/lswjzxuhbgr8irovy6urvj236tm.png)
338:
![](https://habrastorage.org/webt/sl/va/h7/slvah7ejjitbr9xllgh2qin7jxw.png)
Получаем замечательные круги. Примечательно, что круги получаем для
Для других
144:
![](https://habrastorage.org/webt/ja/di/je/jadijema4eklj9igfetdmcnxzvs.png)
354:
![](https://habrastorage.org/webt/t-/yj/df/t-yjdf908qlosm8n2ogauj696sa.png)
Замечательные круги не получаем.
Здесь можно посмотреть в динамике, поводив мышкой по экрану.
Вернемся к дискретизации нелинейных функций.
Дискретизация нелинейной функции.
Например
![](https://habrastorage.org/webt/m0/34/td/m034tdqelex3xu8ha4hznxr8m1k.png)
Строим последовательность:
let a=[];
for(let x=0;x<100;x++) a[x]=Math.floor(x*x*Math.sqrt(2))%2;
console.log(a.join(''));
Для целых аргументов
Первые 100 элементов этой последовательности:
0110010100111110000011000100010100000001010011010110001100101001010011111000000000100110111111111000
Визуализация этой последовательности с помощью черепашьей графики дает такую кривую:
![](https://habrastorage.org/webt/vj/jd/al/vjjdalrj7iml-e3nxtcqdxsu-qo.png)
Эта последовательность выглядит немного более хаотичной, чем последовательность, полученная дискретизацией линейной функции. Но это не так. Если где-то не видим закономерность — значит плохо смотрим. Можем сделать очень простую визуализацию. Запишем первые 1000 элементов последовательности в блокнот, включим перенос строк.
![](https://habrastorage.org/webt/vn/x4/az/vnx4azmmgyxnb1strxlvb9tweju.png)
Можно разглядеть паттерн.
Для того, чтобы лучше разглядеть, единички заменяем на █, нолики — на ░:
![](https://habrastorage.org/webt/g9/dr/gn/g9drgn2ablachxbtmylt8tkvkrg.png)
Построим двухмерный график этой последовательности. На каждой следующей строчке
Для некоторых
35:
![](https://habrastorage.org/webt/vt/_y/_h/vt_y_hrv8xldcv-hm__e0uwo2cu.png)
661:
![](https://habrastorage.org/webt/p4/m_/vv/p4m_vvpzn6dwyu3m6pjugss984s.png)
Для
Дискретизация поверхностей с ненулевой кривизной.
Для дальнейших экспериментов запишем уравнение в более общем виде:
Точно так же, как мы дискретизировали линейную функцию, мы можем дискретизировать поверхности второго порядка. Для этого считаем
Для
Это уравнение элиптического параболоида. Коэффициент
![](https://habrastorage.org/webt/jo/ks/vt/joksvtycb32dkqjrtnbyk2tklwq.png)
for(var x=0;x<canvas.width;x++){
xx=x-canvas.width/2;
for(var y=0;y<canvas.height;y++){
yy=y-canvas.height/2;
z=a*(xx**2+b*xx*yy+c*(yy**2))**(d);
if(Math.floor(z*Math.sqrt(2))%2) context.fillRect(x, y, 1, 1);
}
}
Для
![](https://habrastorage.org/webt/jm/i0/pa/jmi0padbl06lf5ahitbepkcfxqa.png)
Можем этот же паттерн нарисовать недискретным. Вместо
![](https://habrastorage.org/webt/hz/ir/jk/hzirjkt-geoqk3urwrnq2gyknfo.png)
Для
![](https://habrastorage.org/webt/i5/-f/cl/i5-fclddtotjsdm-udsaadhgos8.png)
![](https://habrastorage.org/webt/rl/vu/xy/rlvuxyp6iiexnmcwqui2wdv3eow.png)
![](https://habrastorage.org/webt/1x/io/43/1xio43ptkrwdgggnmpgrwyrf_fs.gif)
Коэффициент
![](https://habrastorage.org/webt/kj/z0/go/kjz0goeeo-kizinm5enjy98usi0.png)
![](https://habrastorage.org/webt/ma/f2/kw/maf2kwt3dayiojxqds6xxbo60jw.png)
Коэффициент
![](https://habrastorage.org/webt/ht/k9/2k/htk92k5t1bcmbvtzkbnwcb0lh7y.png)
![](https://habrastorage.org/webt/jj/9j/tx/jj9jtxuyevzvx6ftla7bd7csb-m.png)
Дальше. Для
Это гиперболический параболоид — поверхность с отрицательной гауссовой кривизной:
![](https://habrastorage.org/webt/lc/1w/af/lc1wafq1kvkiqf9ogmouu43xjc4.png)
Для
![](https://habrastorage.org/webt/a6/dw/4y/a6dw4yxhwytim-mhlglkqfx7h1k.png)
Для
![](https://habrastorage.org/webt/yv/6s/33/yv6s33hromo-s9sofaactuupbv8.png)
Попробуем поменять степень
![](https://habrastorage.org/webt/y6/be/wz/y6bewzb8iupq0hodpeaio3ujjau.png)
Для
![](https://habrastorage.org/webt/_e/g3/bu/_eg3buq3ymow1tgku4aujaekfzq.png)
Для
![](https://habrastorage.org/webt/li/ja/rz/lijarzcrszc9e1ygx9abchv-1yu.png)
Для
![](https://habrastorage.org/webt/1y/zc/by/1yzcbyyhtvgimwvl-5kn7zmuz8a.png)
Для
![](https://habrastorage.org/webt/xo/uu/fw/xouufw4x1mjnf0_n5b1uxu0y1-y.png)
Для
![](https://habrastorage.org/webt/vv/gk/p4/vvgkp4alriamy8tmpuc3faukgou.png)
Для
![](https://habrastorage.org/webt/p6/u9/pg/p6u9pglwjf586jgxs0ziihumkd8.png)
Самые интересные паттерны получаются, если взять такое
Для
![](https://habrastorage.org/webt/ix/pa/rj/ixparjbm2b0cqpcfyqom75e7oda.png)
Для
![](https://habrastorage.org/webt/ti/_u/oi/ti_uoiibivfre1omif4zcsh-g4g.png)
Еще несколько примеров:
![](https://habrastorage.org/webt/2a/fa/g_/2afag_bjjhcsxjkap6s9-57mgok.png)
![](https://habrastorage.org/webt/eb/ms/my/ebmsmy5rkoqaokgpf1w2fpmocjq.png)
![](https://habrastorage.org/webt/bw/r3/mr/bwr3mrla3kdd3erpqbum9bmcini.png)
![](https://habrastorage.org/webt/ye/fg/cx/yefgcxsih7k7zmh-wlcnpaquzpu.png)
![](https://habrastorage.org/webt/qk/es/ux/qkesux00vnzezdjpjboqeleqk2g.png)
![](https://habrastorage.org/webt/77/dh/su/77dhsuipghdtajyqjyyfthhqhfe.png)
В статике — можем посмотреть дискретный и недискретный паттерны.
Подводя итоги...
Мы попробовали дискретизировать линейную функцию и получили фрактал. Если сделать срез трехмерной плоской волны поверхностью с ненулевой кривизной — получим голографический паттерн. Интересно, что мы получим, если сделаем срез четырехмерной плоской волны пространством с ненулевой кривизной? Об этом поговорим в другой раз.
Комментарии (14)
kovserg
28.05.2022 11:55+1Вот такие формулы глаз радуют больше
www.shadertoy.com/view/WsSBzh
www.youtube.com/watch?v=8--5LwHRhjkamarao
28.05.2022 18:24+3Стейк вкуснее ваших шейдеров.
// аргумент примерно такого же уровня. Человек про одно, вы про совершенно что-то несвязное с этим.
e-zig
28.05.2022 14:01Прокрутка сих картинок весьма показательный тест частоты обновления экрана смарта. Между 60 и 120 Гц разница очень заметна.
Browning
28.05.2022 20:30Симпатично, но странно, что ни разу не прозвучало словосочетание "последовательность Битти".
Chupaka
28.05.2022 23:40Муар — это тоже фрактал, получается?
З.ы. В заголовке как будто не хватает то ли "что" в начале, то ли "ничего" в конце...
iShrimp
30.05.2022 12:27Применительно к теме статьи, муар возникает в результате алиасинга - из-за того, что компьютер вычисляет функцию, имеющую высокие частоты, не во всех точках плоскости, а по дискретной сетке. Все эти кольца, кроме центральных, являются артефактами семплирования.
В природе таких паттернов не существует, так как нет дискретных сеток, а есть сплошная непрерывная (до уровня молекул) среда. Если мы возьмём ту же функцию sin(a(x²+y²)) и построим её график со сглаживанием, то получим кольца Ньютона, которые на периферии, по мере удаления от центра, просто сливаются в однородный фон.
Browning
30.05.2022 12:54+1Зато на уровне молекул муар проявляется. Среди физиков, изучающих графен и другие двумерные кристаллы, в последние годы все очень интересуется муаром, потому что там происходит всякие неожиданные вещи.
abcdsash
ничего не понятно, но очень интересно )