
В статье присутствуют Gif (трафик!) и контрастные картинки. У эпилептиков может случиться эпилептический припадок.
Предыдущие части: 0, 1, 2.
Для начала вспомним, что за «бильярдные фракталы».
Бильярдные фракталы.
Есть у нас некоторая прямоугольная область («бильярд»), в которой движется бильярдный шар (или луч света).

Шар упруго отражается от стенок по законам оптики (угол отражения равен углу падения). При этом шар бесконечно мал (абстрактная «материальная точка» из физики) и при движении и отражении скорости не меняет (скорость нас вообще не интересует).
Когда шар касается одной из выбранных стенок (не важно, какую стенку выбирать, но для примера выберем верхнюю) — фиксируем, в какую сторону движется шар — в левую или в правую:


Для бильряда, соотношение сторон которого — иррациональное число, последовательность отражений — фрактальная (насколько этот термин применим к двоичным последовательностям). Или фракталообразующая. Если визуализировать такую последовательность с помощью черепашьей графики, мы получим фрактал.
В качестве примера можем использовать последовательность для бильярда, соотношение сторон которого равно
Строить такие последовательность очень легко:
Берем поочередно каждое целое число
let a=[];
for(let x=0;x<100;x++) a[x]=Math.floor(x*Math.sqrt(2))%2;
console.log(a.join(''));
Первые 100 элементов этой последовательности:
0100110110010011001001101100110110010011011001101100100110010011011001001100100110110011011001001100
Визуализация этой последовательности с помощью черепашьей графики дает нам следующую фигуру:

Более подробно о том, откуда взялась эта формула и о визуализации последовательностей с помощью черепашьей графики, можно почитать во второй части — Фракталы в иррациональных числах
В реальном мире.
В реальном мире, такие последовательности встречаются гораздо чаще, чем может показаться на первый взгляд. Два примера.
Пример 1. Есть у нас два человека. Один побольше, второй — поменьше:

Эти два человека идут по улице. У высокого шире шаг, чем у низкого. Чтобы успевать за высоким, низкому приходится быстрее ногами двигать и больше шагов делать. В каждый момент времени, когда низкий ставит правую ногу на асфальт, фиксируем какая нога высокого находится в воздухе — левая или правая. Если частоты шагов низкого и высокого несинхронизированные — получим фрактальную последовательность.
Пример 2. Вокруг некоторой планеты вращается спутник:

Выбираем временной интервал
Для наглядности, посмотрим на геометрическую интерпретацию бильярдных последовательностей.
Дискретизация линейной функции.

Для бильярда, соотношение сторон которого равно
Фактически, все что мы сделали, чтобы получить фрактальную последовательность — дискретизировали линейную функцию с иррациональным коэффициентом
Но прежде, чем переходить к нелинейным функциям, хотелось бы упомянуть об одном интересном наблюдении, сделанном в процессе написания статьи.
Об одном интересном наблюдении.
Возьмем нашу последовательность:
И построим из нее другую последовательность:
Первый элемент последовательности — произвольное число. Каждый следующий элемент — увеличиваем предыдущий элемент на 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);
}

Из этой же кривой можем получить фрактальную поверхность. Для каждой точки
Дальше можем сделать срез плоскости по оси

Или отметить такие точки, для которых

Следующая картинка — чем больше

Можем немного изменить последовательность:
Раскрыв скобки, получим:
Здесь
Как это выглядит в бильярдной модели? Мы увеличиваем предыдущий элемент последовательности на расстояние (по оси


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));
}
В этом случае поверхность получится гладкой, а не фрактальной.
Делаем визуализацию тем же способом, который использовали выше. Для каждой точки

До того, как мы изменили последовательность, все

Самое интересное получится, если мы отметим пиксели, для которых
478:

338:

Получаем замечательные круги. Примечательно, что круги получаем для
Для других
144:

354:

Замечательные круги не получаем.
Здесь можно посмотреть в динамике, поводив мышкой по экрану.
Вернемся к дискретизации нелинейных функций.
Дискретизация нелинейной функции.
Например

Строим последовательность:
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
Визуализация этой последовательности с помощью черепашьей графики дает такую кривую:

Эта последовательность выглядит немного более хаотичной, чем последовательность, полученная дискретизацией линейной функции. Но это не так. Если где-то не видим закономерность — значит плохо смотрим. Можем сделать очень простую визуализацию. Запишем первые 1000 элементов последовательности в блокнот, включим перенос строк.

Можно разглядеть паттерн.
Для того, чтобы лучше разглядеть, единички заменяем на █, нолики — на ░:

Построим двухмерный график этой последовательности. На каждой следующей строчке
Для некоторых
35:

661:

Для
Дискретизация поверхностей с ненулевой кривизной.
Для дальнейших экспериментов запишем уравнение в более общем виде:
Точно так же, как мы дискретизировали линейную функцию, мы можем дискретизировать поверхности второго порядка. Для этого считаем
Для
Это уравнение элиптического параболоида. Коэффициент

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);
}
}
Для

Можем этот же паттерн нарисовать недискретным. Вместо

Для



Коэффициент


Коэффициент


Дальше. Для
Это гиперболический параболоид — поверхность с отрицательной гауссовой кривизной:

Для

Для

Попробуем поменять степень

Для

Для

Для

Для

Для

Для

Самые интересные паттерны получаются, если взять такое
Для

Для

Еще несколько примеров:






В статике — можем посмотреть дискретный и недискретный паттерны.
Подводя итоги...
Мы попробовали дискретизировать линейную функцию и получили фрактал. Если сделать срез трехмерной плоской волны поверхностью с ненулевой кривизной — получим голографический паттерн. Интересно, что мы получим, если сделаем срез четырехмерной плоской волны пространством с ненулевой кривизной? Об этом поговорим в другой раз.
Комментарии (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
ничего не понятно, но очень интересно )