Nickolay.info. PHP. Статьи. Кривая Серпинского на PHP |
Собственно, мне понадобился наглядный пример рекурсии, для которой "линейные" (в смысле, выполняемые единственным циклом) расчёты, вроде факториала или ряда Фибоначчи, кажутся мне неудачными, а вот кривая Серпинского иллюстрирует идею рекурсии довольно ясно, особенно "лавину", начинающуюся уже с 5-6 вложений.
Ниже показаны кривые Серпинского порядков рекурсии от 1 до 5:
Конечно же, эти изображения я не рисовал, а сгенерировал оперативно написанным скриптом. Для рисования
используется библиотека GD, а интерес в коде представляют разве что отсутствующие в этой библиотеке функции для работы
с графическим курсором, привычные по Сишным или Паскалевским средам, прежде всего это
GetX
и GetY
- получение координат курсора, MoveTo
- его установка в нужную позицию рисунка и
LineTo
- проведение линии от позиции курсора до нужной точки. Функцию PutPixel
вполне заменит стандартная
для GD функция imagesetpixel
. Вот соответствующий кусочек кода:
function GetX ($x=0,$action=0) { static $cx; if (!$action) return $cx; $cx=$x; return $cx; } function GetY ($y=0,$action=0) { static $cy; if (!$action) return $cy; $cy=$y; return $cy; } function MoveTo ($x,$y) { GetX ($x,'set'); GetY ($y,'set'); } function LineTo ($img,$x2,$y2,$color) { $x1=GetX (); $y1=GetY (); if ($x1!=$x2) { //не вертикаль $a=($y2-$y1)/($x2-$x1); $b=$y1-$a*$x1; $n=abs($x2-$x1)+1; if ($x2>$x1) $dx=1; else $dx=-1; $x=$x1; for ($i=1; $i<=$n; $i++) { $y=round ($a*$x+$b); imagesetpixel ($img, $x, $y, $color); $x+=$dx; } } else { //вертикаль $n=abs($y2-$y1); if ($y2>$y1) $dy=1; else $dy=-1; $x=$x1; $y=$y1; for ($i=1; $i<=$n; $i++) { imagesetpixel ($img, $x, $y, $color); $y+=$dy; } } imagesetpixel ($img, $x, $y, $color); MoveTo ($x2,$y2); }
Скрипт можно вызывать со следующими параметрами URL ("понимается" только метод GET):
i
- порядок рекурсии, целое от 1 до 6 включительно;
u
- длина штриха кривой, от 1 до 50 включительно
xy
- желаемый размер картинки в пикселах, от 10 до 1000 включительно. Если размер не задан, он вычисляется
по формуле $xy = round(7.2*$u*pow(2,$i-1));
, более удачную я подобрать не пытался;
back
- цвет фона рисунка, должен быть передан в виде RRGGBB
, где RR, GG, BB - 16-ричные интенсивности красного, зелёного и синего от 00 до FF (от 0 до 255 десятичного) включительно, то есть, типовая система записи цвета RGB. Если передано любое значение back
меньше 0, фон будет прозрачным. По умолчанию белый;
lines
- цвет линий кривой Серпинского, также в виде RRGGBB
, по умолчанию красный.Эти ограничения можно поменять в коде скрипта.
Пример вызова с параметрами - кривая порядка 4, чёрным по прозрачному, авторазмер
Скачать исходник скрипта в архиве ZIP (2 Кб)
гостевая; E-mail |