| Этюды о бесполезной красоте - Пузыри и сотовая связь |
Евгений Скляревский
|
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 и мобильники. Отладка программы и попутные опыты доставят вам массу удовольствия. Задание на дом: научите пену бурлить, чтобы некоторые пузыри лопались, а соседи занимали их место. Да, и не забудьте выложить изображения на свой сайт: Созерцание пузырей рождает прекрасные мысли, недоступные в обыденной суете. Может, в этом и состоит их предназначение? Поразмышляйте об этом на досуге.
| |||