Этюды о бесполезной красоте - Пузыри и сотовая связь | Евгений Скляревский | 25.09.2001 | |
|
44k | ||
Автор: Евгений
Скляревский
Адаптация для TMT Pascal: Валерий Вотинцев Оригинал статьи для Visual Basic: Журнал Hard'n'Soft Этюды
о бесполезной красоте
Этюд третий. Пузыри и сотовая связь
Часто бывает, увидишь картинку, придумаешь алгоритм, а идея не отпускает. Так вот и с пузырями. Суть в том, что на плоскости случайным образом задаются точки, и из них, как из центров, строятся окружности с увеличивающимися радиусами и уменьшающейся яркостью. В каждой точке плоскости цвет берется от окружности с большей яркостью, т.е. от ближайшей. На картинке получается нечто похожее на взбитую пену.
Программа рисования пузырей несложная. Задается их количество, случайным образом выбираются координаты, потом в цикле проходятся все точки плоскости с определением расстояния до ближайшего центра, и соответственно этому расстоянию уменьшается яркость. Небольшое замечание: предварительно экран стоит перевести в режим 16- или 24-битного представления цвета.
Увеличив
количество пузырей до 100 или 200, получим пену, похожую на легкие
или какие-то другие объекты явно биологического происхождения.
А при чем здесь, спросите вы, сотовая связь? Очень просто. Мобильный телефон с помощью компьютера выбирает антенну, от которой идет самый сильный сигнал, обычно она оказывается ближайшей. При перемещении телефона его сопровождение передается от одной антенны к другой, с самым сильным сигналом для данной точки. Лучшей иллюстрации этого процесса, чем наша картинка с пузырями, не найти. Но приступим к делу. Приведенная ниже программа создана в TMT Pascal 4, хотя вы можете реализовать этот нехитрый алгоритм на любом доступном языке. Я, например, свои первые пузыри рисовал на Visual FoxPro 6.0 и Visual Basic 6. Скопируйте приведенный ниже текст в окно редактора TMT Pascal и запустите программу.
Program Bubbles; (***********************************************) (* Пузыри *) (* Автор алгоритма: Евгений Скляревский (VB) *) (* ------------------------------------------- *) (* Адаптация для TMT Pascal: *) (* Валерий Вотинцев *) (* MS-DOS 32-bit protected mode *) (***********************************************) uses CRT, Math, Graph; Type dArray = Array[0..0] of LongInt; pArray = ^dArray; var i, j, k, x, y, q, step, xmax, ymax, v, col, uu: longint; ColDepth: word; red, green, blue: LongInt; xc, yc, r: pArray; begin xmax := 800; // Разрешение по горизонтали ymax := 600; // Разрешение по вертикали ColDepth := 16; // Максимальная глубина цвета (бит на пиксел) v := 8; // Количество пузырей step := 4; // Шаг движения по x и y ("мозаичность" картины): // step = 1 -> Рисование по 1 пикселу // step > 1 -> Рисование квадратами step*step Randomize; // Установим графический режим SetSVGAMode(xmax,ymax,ColDepth,LFBorBanked); if GraphResult<>grOk then begin // Проверка результата Writeln('Mode not supported..'); Halt(0); end; // Выделяем память для трех массивов GetMem(xc,v*SizeOf(LongInt)); GetMem(yc,v*SizeOf(LongInt)); GetMem(r, v*SizeOf(LongInt)); // Задаем случайные координаты пузырькам For i := 0 To pred(v) do begin xc^[i] := Random(xmax); yc^[i] := Random(ymax); end; // В цикле проходим все поле по X и Y x := 0; While (x < xmax) do begin y := 0; While (y < ymax) do begin For q := 0 To pred(v) do begin {1} r^[q] := Trunc(Power(IntPower((xc^[q] - x),2) + IntPower((yc^[q] - y),2),0.5)); {1a} {r^[q] := Trunc(Power(IntPower((xc^[q] - x),2) + IntPower((yc^[q] - y),2),0.8));} {1b} {r^[q] := Trunc(Power(Abs(IntPower((xc^[q] - x),2) - IntPower((yc^[q] - y),2)),0.5));} end; // Сортируем пузырьки методом пузырька по возрастанию радиуса For k := 0 To v - 2 do begin For j := 0 To v - 2 do begin If r^[j] > r^[j + 1] Then begin uu := r^[j]; r^[j] := r^[j + 1]; r^[j + 1] := uu; End; end; end; // Задаем цвет {2} red := 255 - r^[0]; green := 255 - Trunc(r^[0] * 1.3); blue := 255 - Trunc(r^[0] * 1.1); {2a} {red := 100 - r^[0]; green := 100 - Trunc(r^[0] * 1.3); blue := 100 - Trunc(r^[0] * 1.1);} {2b} {red := 255 - Trunc(r^[0] * 2.5); green := 255 - Trunc(r^[0] * 1.1); blue := 255 - Trunc(r^[0] * 1.1);} If red < 0 Then red := 0; If green < 0 Then green := 0; If blue < 0 Then blue := 0; Col := RGBColor(red, green, blue); // Рисуем очередную точку или квадрат If (step = 1) Then PutPixel(x, y, Col) else begin SetFillColor(Col); Bar (x, y, x + step, y + step); end; Inc(y,step); end; Inc(x,step); end; // Освобождаем выделенную память FreeMem(xc,v*SizeOf(LongInt)); FreeMem(yc,v*SizeOf(LongInt)); FreeMem(r, v*SizeOf(LongInt)); // Ждем нажатия Esc Repeat until ReadKey=#27; CloseGraph; end.
Количество пузырей, точнее, размерность массивов, в которых
расположены координаты центров и радиуса, задается переменной v.
Причем память под массивы выделяется динамически, в зависимости
от заданного значения v.
Цикл с переменной i задает центры пузырей
случайным образом. Для того, чтобы при каждом запуске расположение
пузырей было разным, мы используем функцию Random.
В цикле с переменной q по теореме
Пифагора вычисляем для каждой точки с координатами x
и y расстояние
до каждого из центров пузырей Получив минимальный радиус для текущей точки, можно приступать к формированию цвета - это и есть изюминка всей затеи. Каждая составляющая rgb-функции цвета уменьшается пропорционально радиусу. Меняя коэффициенты и максимальное значение, равное в примере 255, на меньшее, можно получать различные оттенки пены и регулировать контрастность рисунка. Попробуйте убрать комментарии с блоков, помеченных как {2a} и {2b}.
Программа предоставляет безграничный простор для экспериментов. Попробуйте сделать так, чтобы яркость не уменьшалась с удалением от центра пузыря, а увеличивалась, и вы будете поражены получившейся картиной. Попробуйте при вычислении радиуса поменять показатель степени с 0,5 на 0,8 или 0,3 (кстати, именно для этого мы и воспользовались функцией Power, а не Sqrt). Уберите комментарии со строки {1a}.
Попробуйте также вместо формулы А бесконечные игры с цветами, шагом и количеством пузырей... Естественно, что с уменьшением шага рисования (переменная step) и увеличением количества пузырей (v) время рисования возрастает, т.к. в каждой точке рисунка проверяются расстояния до всех центров пузырей, а любые попытки оптимизировать алгоритм лишь замедлят работу программы. А что если разукрасить пузыри - каждый в свой цвет? Тут придется поработать, ведь нужно не только задать массив цветов для каждого пузыря и заполнить его случайным образом, но и, отслеживая соответствие каждой точки плоскости ближайшему центру, запоминать еще его цвет. Это непросто, потому что при выборе наименьшего радиуса его индекс в массиве теряется. Задача, конечно, решаемая, и если вы с ней справитесь, то будете сторицей вознаграждены получившейся картиной. Экран заполняется разноцветными шариками, как в моделях сложных молекул, или одинокими фонариками - в зависимости от ваших настроек.
Вот и все. Как ни странно, нам удалось связать вместе пену, TMT Pascal и мобильники. Отладка программы и попутные опыты доставят вам массу удовольствия. Задание на дом: научите пену бурлить, чтобы некоторые пузыри лопались, а соседи занимали их место. Да, и не забудьте выложить изображения на свой сайт: Созерцание пузырей рождает прекрасные мысли, недоступные в обыденной суете. Может, в этом и состоит их предназначение? Поразмышляйте об этом на досуге.
| |||