Главная » Советы по графике в Delphi
Содержание:

- Фрактальные множества.
- Перетаскивание окна за рабочую область.
- Огненные буквы (эфект огня).
- "Звездные" окна.
- Несколько графических эфектов.

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

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

Итак приступим к самому главному, ради чего мы здесь и собрались. Как же строятся эти удивителные множества ?

Все сводится к вычислению одной единственной формулы.

zi+1=zi2+c

Здесь z и c - комплексные числа. Как видно, формулы по сути представляет собой обычную рекурсию (или что-то вроде многократно примененного преобразования). Зная правила работы с комплексными числами данную формулу можно упростить и привести к следующему виду.

xi+1=xi2-yi2+a

yi+1=2*xi*yi+b

Построение множества Мандельброта сводится к следующему. Для каждой точки (a,b) проводится серия вычислений по вышеприведенным формулам, причем x0 и y0 принимаются равными нулю, т.е. точка в формуле выступает в качестве константы. На каждом шаге вычиляется величина r=sqrt(x2+y2 ). Значением r ,как ни трудно заметить, является расстояние точки с координатами (x,y) от начала координат ( r=sqrt[ (x-0)2+(y-0)2] ). Исходная точка (a,b) считается принадлежащей множеству Мандельброта, если она никогда не удаляется от начала координат на какое-то критическое число. Для отображения можно подсчитать скорость удаления от центра, если например точка ушла за критическое расстояние, и в зависимости от нее окрасить исходную точку в соответствующие цвет. Полное изображение множества Мандельброта можно получить на плоскости от -2 до 1 по оси x и от -1.5 до 1.5 по оси y. Также известно, что для получения примелимой точности достаточно 100 итеарций (по теории их должно быть бесконечно много). Ниже представлен листинг функции реализующей выполнение итераций и определение принадлежности точки множеству Мандельброта, точнее на выходе мы получаем цвет для соответствующе точки. В качестве критического числа взято число 2. Чтобы не вычислять корень, мы сравниваем квадрат расстояния (r2) с квадратом критического числа, т.е. сравниваем (x2+y2) и 4.function mandelbrot(a,b: real): tcolor;
var x,y,xy: real;
x2,y2: real;
r:real;
k: integer;
begin
r:=0;
x:=0; y:=0;
k:=100;
while (k>0)and(r<4) do begin
x2:=x*x;
y2:=y*y;
xy:=x*y;
x:=x2-y2+a;
y:=2*xy+b;
r:=x2+y2;
dec(k)
end;
k:=round((k/100)*255);
result:=rgb(k,k,k);
end; Множество Жюлиа получается если зафиксировать в формуле значение комплексной константы (a+ib), которая будет одинакова для всех точек, а начальные значения x0 и y0 принимать равными значениям координатам вычисляемой точки. Листинг для множества Жюлиа приведен ниже.function julia(x0,y0: real): tcolor;
var a,b,x,y,x2,y2,xy: real;
r:real;
speed,k: integer;
begin
r:=1;
a:=-0.55; b:=-0.55;
x:=x0; y:=y0;
k:=100;
while (k>0)and(r<4) do begin
x2:=x*x;
y2:=y*y;
xy:=x*y;
x:=x2-y2+a;
y:=2*xy+b;
r:=x2+y2;
dec(k)
end;
k:=round((k/100)*255);
result:=rgb(k,k,k);
end; Ниже приведен листинг функции отображающий данные множества.procedure t form1.bitbtn2click(s ender: tobject);
var x_min,y_min,x_max,y_max,hx,hy,x,y: real;
i,j,n: integer;
color: tcolor;
begin

x_min:=-1.5; x_max:=2;
y_min:=-1.5; y_max:=1.5;
n:=300;
y:=y_min;
hx:=(x_max-x_min)/n;
hy:=(y_max-y_min)/n;
for j:=0 to n do begin
x:=x_min;
for i:=0 to n do begin
if rbm.checked then color:=mandelbrot(x,y);
if rbj.checked then color:=julia(x,y);
impict.picture.bitmap.canvas.pixels[i,j]:=color;
x:=x+hx;
end;
y:=y+hy;
end;
end; При рассмотрении темы большую помощь оказала статья А.Колесникова "Визуализация фрактальных структур" в "Компьтерных вестях".
Перетаскивание окна за рабочую областьДля решения данной проблемы в можно пойти в двух направлениях один не очень изящный и слегка корявый, второй более изящный. Рассмотрим оба.

Первый способ.Первый способ состоит в обработки событий нажатия клавиши мыши на форме, перемещения мыши и отпускании клавиши. Предварительно следует объявить следующие переменные.hit: boolean;
_x,_y: integer; Переменная hit в начале работы должны иметь значение false. Это удобно сделать в обработчике события формы oncreate.procedure t form1. formcreate(s ender: tobject);
begin
hit:=false;
end; Далее следует написать обработчик для события onmousedown(нажата клавиша мыши).procedure t form1. formmousedown(s ender: tobject; button: tmousebutton;
shift: tshiftstate; x, y: integer);
begin
hit:=true;
_x:=x; _y:=y;
end; Здесь мы мутем присваивания перменно hit значение true указываем, что было произведено нажатие кнопки мыши (пока кнопка будет удерживаться в нажатом состоянии значение переменной hit будет равно true). Также здесь мы запоминаем текущие координаты мыши. Далее следует написать обработчик для события onmousemove (перемещение курсора мыши)procedure t form1. formmousemove(s ender: tobject; shift: tshiftstate; x,
y: integer);
begin
if hit then begin
left:=left+(x-_x);
top:=top+(y-_y);
end;
end; Сначала идет проверка нажата ли клавиша мыши, если нажата, то перемещаем наше окно. И осталось написать обработчик для события onmouseup.procedure t form1. formmouseup(s ender: tobject; button: tmousebutton;
shift: tshiftstate; x, y: integer);
begin
hit:=false;
end; Таким образом мы указываем что кнопка было отпущена, и теперь при перемещении мыши не следует перетаскивать окно.
А теперь о недостатках это метода. Во первых, перетаскивание в том виде, в котором приведено выше будет осуществляться с помощью обоих кнопок мыши (обычно это принято делать только левой кнопкой). Этот недостаток легко обходиться, следует лишь дополнительно проверять параметр button:tmousebutton. Второй недостаток просто так не обойти. Если стоит режим, когда при перетаскивании окна само окно не перетаскивается, а перетаскивается его контур и лишь при отжатии клавиши окно рисуется на новом месте, то данный метод будет делать окно "белой вороной" перетаскиваемое окно, т.к. оно будет постоянно перерисовываться при перетаскивании.

Второй способ
Второй способ состоит в обработке сообщения wm_nchittest. Сообщение посылается окну, и параметрами его являются координаты курсора мыши. Сообщение обрабатывается и возврашается одно из значений, из которых нас будут интерисовать только два: htclient и htcaption. После обработки соообщения по умолчанию возврщается результат над какой областью окна была нажата клавиша мыши. htclient означает что клавиша была нажата над клиентской областью, а htcaption- над заголовком окна. Как известно windows обеспечивает перетаскивание за заголовок окна, следовательно нам надо перехватить на обратном пути сообщение, и если клавиша была нажата над клиентской областью, то подменить возвращаемое значение, указывая что будто-бы нажатие было над заголовком.
В delphi это делается следующим образом. Сначала объявляем обработчик сообщения, это делается в объявлении класса окна.procedure wmnchittest ( var msg: twmnchittest); message wm_nchittest; После этого описываем соответствующий обработчик.procedure t form1.wmnchittest ( var msg: twmnchittest);
begin
inherited;
if msg.result=htclient then
msg.result:=htcaption;
end; Сначала мы вызываем обработку по умолчанию, а затем если надо переобпределяем возвращаемое значение.
Данный метод не обладает теми недостатками, которые были указаны приминительно к первому методу. Кстати таким образом можно перетаскивать окна и не имеющие заголовка, правда Огненные буквы (эфект огня)
Древний человек покорил огонь, узнал его секреты и поставил на службу человечеству. Так давайте и мы попытаемся покорить эту стихию.
Для начала разберем принцип создания эфекта огня. В компьютерной графике при работе с изображениями очень часто используются всевозможные фильтры. Давайте рассмотрим принцип построения подобных фильтров. Пусть имеется матрица (таблица) размером 3х3(или 5х5), элементами которой являются какие-либо числа (коэффициенты). Например вот такая127496385 Категория: Языки программирования | Просмотров: 82 Искал где посмотреть мебель в кухню? Подскажу тебе, что кухни покупаются тут