В этой статье будет краткое руководство по созданию треугольника Серпинского с помощью рекурсии в Processing (java). Итак, для начала - что такое треугольник Серпинского?

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

Существует довольно много разных процессов для создания Треугольника Серпинского, и мы просто собираемся сосредоточиться на процессе сжатия и дублирования:

  1. Начните с равностороннего треугольника.
  2. Возьмите длину этого треугольника (длину одной стороны) и разделите ее пополам, чтобы получить новую длину.
  3. создайте новый равносторонний треугольник новой длины и продублируйте его 3 раза
  4. Каждый из трех новых треугольников нужно разместить так, чтобы каждый угол касался угла другого треугольника (включая исходный).
  5. повторить для каждого нового треугольника.

Теперь, когда мы рассмотрели основной шаблон, необходимый для создания треугольника Серпинского, мы попытаемся воссоздать его в Processing (java).

Если у вас еще не загружена обработка, перейдите сюда и загрузите: https://processing.org/download/

После загрузки откройте Процессор и создайте новый пустой файл и вставьте приведенную ниже начальную настройку для процессора:

Как только начальная настройка будет завершена, мы собираемся создать треугольник с начальной точкой в ​​центре окна. Процессор дает нам функцию triangle(x1, y1, x2, y2, x3, y3); для создания треугольника внутри окна - x1 и y1 - координаты начальной точки вашего треугольника, которая в данном случае будет нижней левой точкой. x2 и y2 - координаты второй точки, следующей против часовой стрелки, и так далее для x3 и y3.

Итак, с начальной координатой (x, y) и заданной длиной мы можем построить равносторонний треугольник. Нам нужно создать метод, который принимает координату x, координату y и длину и использует их для создания треугольника - мы назовем эту функцию tri();.

Формируем равносторонний треугольник:

первая точка: (x, y)

вторая точка: (x + length / 2, y-sin (PI / 3) * l) - Координата x составляет половину расстояния между двумя базовыми точками, и вычисление координаты y немного странно, но дает нам исправьте координату Y, чтобы сохранить длину.

третья точка: (x + length, y) - координата x находится на полном расстоянии от первой точки, а координата y такая же.

Итак, если мы создадим нашу функцию tri(); на основе этой логики, она будет выглядеть примерно так:

Если вы нажмете run, вы должны увидеть маленький серый треугольник с начальной точкой в ​​центре окна.

Мы передаем нашей tri(); функции width/2, height/2 (x и y для центра окна), а также длину 200. Это создает наш треугольник!

Теперь, когда у нас есть треугольник, нам нужно выяснить, как реализовать шаги, перечисленные выше, чтобы создать новый треугольник на основе длины / 2, продублировать его 3 раза и поместить в родительский треугольник. Это будет наша реализация рекурсии. Итак, давайте начнем с создания функции !!

Назовем эту функцию sierpinskiPattern! Эта функция должна будет принимать 5 разных вещей: 1. координату x 2. координату y 3. длину 4. наш рекурсивный случай (инкремент) 5. наш базовый случай (завершающий сценарий). Внутри функции нам понадобится условное выражение для создания точки завершения - в этом случае у нас есть инкрементатор (мы будем называть его depth, поскольку он представляет текущую глубину в шаблоне, на котором мы находимся), а также наша база (которая будет представлять насколько глубоко мы хотим углубиться в шаблон), используя эти две переменные, мы можем условно сравнить их для создания конечной точки: depth == base. Вот как будет выглядеть настройка этого метода:

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

Основываясь на нашем шаблоне, описанном выше, мы хотим создать новый равносторонний треугольник с длиной, равной половине длины предыдущего. Затем этот треугольник будет иметь ту же начальную точку (x, y), что и его родительский треугольник, но с половиной длины. Итак, вот как это будет выглядеть:

Здесь мы вызвали sierpinskiPattern внутри себя для создания рекурсии !! Мы присвоили базе значение 4, поэтому визуализируется 4 треугольника - каждый размером в половину своего родительского, и теперь мы также сохраняем длину в переменной len, а также увеличиваем нашу глубину каждый раз, когда вызываем функция, чтобы при depth==base (4 == 4) рекурсия прекратилась.

Теперь нам нужно создать два других треугольника и разместить их в правильном месте. Следующий треугольник, идущий против часовой стрелки, будет иметь начальную точку 1/4 длины в положительном направлении по оси x, а также на половину высоты в отрицательном направлении по оси y. Последний треугольник будет иметь начальную точку 1/2 длины в положительном направлении по оси x, она также будет той же осью y, что и исходная начальная точка. Так что давайте вызовем SierpinskiPattern еще два раза с этой логикой!

У НАС ЕСТЬ ТРЕУГОЛЬНИК СЕРПИНСКОГО !! Вы можете запустить его с большей длиной и более высоким основанием, чтобы увидеть более сложные версии.

Хорошо, теперь, когда у нас есть рендеринг треугольника Серпинского, давайте сделаем его круче! Мы собираемся использовать метод обработки под названием map(), который мы будем использовать для отслеживания нашей мыши. Затем положение мыши будет использоваться для определения base Треугольника Серпинского. метод карты принимает 5 параметров: map(value, start1, stop1, start2, stop2) - наше значение будет mouseX - текущее положение нашей мыши по оси x. Тогда start1, stop2 будут 0, width, покрывая всю ширину окна - start2, stop2 будет 1, 10, так что наш вывод будет целым числом от 1 до 10, которое будет соответствовать нашей базе. Теперь мы также хотим, чтобы наша начальная точка находилась ближе к нижней левой части окна, которым мы можем управлять с помощью нашего первоначального вызова sierpinskiPattern. Вот как это будет выглядеть:

Мы почти на месте!! Нажмите «Беги» и перетащите указатель мыши по ширине окна, и вы увидите эффект! Если вы хотите добавить несколько цветов для дальнейшего улучшения визуального восприятия, выполните следующие действия:

Мы собираемся использовать параметр base, поскольку он изменяется динамически, чтобы отображать разные цвета в зависимости от того, на какой глубине мы в данный момент находимся внутри треугольника. В нашем setup() давайте добавим noStroke() и fill(50), чтобы получить треугольники с серой заливкой. Затем в нашем draw() методе добавим background(255), чтобы он закрасил то, что стоит за ним - вы можете не указывать это, если хотите !! (это становится немного сумасшедшим)

Отрисовка разных цветов будет происходить в нашей sierpinskiPattern функции, когда мы визуализируем треугольник. используя fill() в формате rgb, вы можете возиться с манипулированием числами с помощью base для достижения различных эффектов. Моя реализация начинается с зеленого и заканчивается красным! Вот окончательный код учебника:

Надеюсь, вам понравился этот урок!