Rambler's Top100

Скачать программы    Все программы автора

1. 15. 3. 3 Создание графических узоров

Графические узоры создают для декоративных заставок, рекламы, демонстрации возможностей аппаратуры. Как правило, компьютерные узоры выполняются по весьма простым алгоритмам. Главное - идея создания декоративного эффекта.

Рассмотрим некоторые из принципов составления узоров на плоскости:

 

1. Перемещение фигуры.

 

Если фигуру перемещать не вращая относительно своего "центра", то получим плоско п араллельное движение тела (любой отрезок прямой на фигуре остается параллельным самому себе). За "центр" фигуры может быть принята любая точка жестко связанная с фигурой. Обычно "центр" фигуры (xf, yf) перемещают относительно центра узора (xc, yc) по определенному закону:

 

 

xf = xc + Fx("параметры"),

yf = yc + Fy("параметры"),

где Fx, Fy - функции от параметров.

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

for i:= 1 to Nc do begin

alfa:=2 * pi * i/Nc; { угол поворота "центра" фигуры }

Lx:= FLx(i); Ly:= FLy(i); { функции расстояний }

R:= FR(i); S:= FS(i); { функции радиуса и цвета окружности }

xf:= xc + round(Lx * cos(alfa)); { координаты "центра" фигуры }

yf:= yc + round(Ly * sin(alfa));

SetColor(S); Circle(xf, yf, R) end;

В этом фрагменте Nc - раз рисуется окружность с центром, поворачивающимся на угол alfa вокруг центра узора. Расстояние от центра i - й окружности до центра узора задается функциями Flx( i ), Fly( i ), радиус окружности - функцией FR( i ), цвет - функцией FS( i ). Подбором этих функций и числа окружностей Nc можно добиться разнообразных декоративных эффектов. Вместо окружностей можно строить любые фигуры, используя процедуры их рисования с заданием "центра" фигуры и других параметров в системе координат экрана.

В общем случае фигура может перемещаться вращаясь относительно своего "центра" и деформироваться. При этом параметры процедуры рисования фигуры должны включать все координаты точек, которые соединяются линиями. Координаты i - ой точки фигуры определяются по формулам:

xxi = xf + Kxi * ((xi-xf) * cos(A) - (yi-yf) * sin(A)),

yyi = yf + Kyi * ((yi-yf) * cos(A) + (xi-xf) * sin(A)),

где A - угол поворота фигуры относительно своего "центра", отсчитываемый в левой системе координат экрана по часовой стрелке относительно оси X,

xi, yi - исходные координаты i - ой точки фигуры,

xxi, yyi - новые координаты i - ой точки фигуры,

Kхi, Kyi - коэффициенты масштабирования координат i - ой точки по осям Х и Y.

Приведем пример задания закона движения линии относительно своего "центра":

for j:= 1 to Nf do begin

A:= 2 * pi * j/Nf; { угол поворота линии вокруг своего "центра" }

Kx1:= FKx1(j); Ky1:= FKy1(j); Kx2:= FKx2(j); Ky2:= FKy2(j);

{ координаты 1 - ой точки фигуры }

xx1:= xf + round(Kx1 * ((x1-xf) * cos(A) - (y1-yf) * sin(A)));

yy1:= yf + round(Ky1 * ((y1-yf) * cos(A) + (x1-xf) * sin(A)));

{ координаты 2 - ой точки фигуры }

xx2:= xf + round(Kx2 * ((x2-xf) * cos(A) - (y2-yf) * sin(A)));

yy2:= yf + round(Ky2 * ((y2-yf) * cos(A) + (x2-xf) * sin(A)));

SetColor(14); line(xx1, yy1, xx2, yy2); delay(100);

end;

x1, y1, x2, y2 - исходные координаты точек фигуры,

xx1, yy1, xx2, yy2 - координаты 1 - ой и 2 - ой точек фигуры на i - ом шаге рисования.

В этом фрагменте многократно (Nf - раз) рисуется линия, вращающаяся на угол "A” относительно своего центра xf, yf. Фигура может искажаться (деформироваться), если не соблюдаются равенства: Fkx1( j)= Fky1( j)= Fkx2( j)= Fky2( j)= K= 1.

Если центр узора перемещается, то изменение его координат необходимо задать во внешнем цикле.

 

Практическое задание N 1. 56

 

1. Нарисовать узор из 30 - ти эллипсов с центром узора в середине экрана. Радиусы каждого эллипса (Rx, Ry) и расстояние от "центра" эллипсов до центра узора увеличивать на один пиксел.

2. Нарисовать узор из 20 - ти прямоугольников с центром узора в середине экрана. Длины сторон прямоугольников и расстояние от центра узора до "центра" фигуры (например, левого верхнего угла прямоугольника) уменьшать на один пиксел. Для рисования прямоугольника использовать оператор: Rectangle(xf, yf, xf+a - i, yf+b - i); где a и b - стороны прямоугольника, i - параметр цикла вращения вокруг центра узора.

3. Нарисовать узор из отрезка прямой линии, вращающегося вокруг своего "центра" (N - раз) за один оборот вокруг центра узора.

4. Нарисовать узор из отрезка прямой линии, вращающегося вокруг своего "центра" (N - раз) за один полупериод движения по синусоиде.

yf = yс + Af * sin((xf-xc)/100), где Xf = xc + 10 * Pi * j; j= 1, 2, . . , 10,

Af - задать исходя из размеров экрана.

5. Составить процедуру рисования самолета (задавать координаты узлов, которые соединяются прямыми линиями). Нарисовать самолет, движущийся вокруг центра узора по эллиптической траектории (Lx<>Ly). Самолет должен поворачиваться вокруг своего "центра" в соответствии с траекторией ( cos(A)= Fx/L, sin(A)= Fy/L, где L= /Fx2 + Fy2 ).

6. Составить процедуру рисования машины (задавать координаты узлов, которые соединяются прямыми линиями). Нарисовать машину, движущуюся синусоиде. Машина должна поворачиваться вокруг своего "центра" в соответствии с траекторией ( A= arctg(d(yf)/d(xf)), для данного случая: A:=arctan(Af/100 * cos((xf-xc)/100);

 

 

Примечание к п. 5, 6:

 

Фигура перерисовывается в режиме SetWriteMode(1);

2. Масштабирование фигуры.

Рассмотрим случай уменьшения размеров фигуры делением ее сторон.

 

N:= 7; R:= 170; xc:= GetMaxX div 2; yc:= GetMaxY div 2;

for i:= 1 to N do begin alfa:= i * 2. * pi/N;

x[i]:= xc + round(R * cos(alfa)); { координаты вершин }

y[i]:= yc + round(R * sin(alfa)) { исходного N - угольника }

end;

MoveTo(x[N], y[N]);

for i:= 1 to N do LineTo(x[i], y[i]); { рисуем N - угольник }

ch:= ReadKey; { нажать клавишу }

Repeat { найдем середины сторон многоугольника

и запишем их в массивы новых координат многоугольника }

x1:= x[1]; y1:= y[1];

for i:=1 to N-1 do begin x[i]:= (x[i]+x[i+1]) div 2;

y[i]:= (y[i]+y[i+1]) div 2 end;

x[N]:= (x[N]+x1) div 2;

y[N]:= (y[N]+y1) div 2;

{ строим многоугольник по новым точкам }

MoveTo(x[N], y[N]);

for i:=1 to N do LineTo(x[i], y[i]);

ch:=ReadKey; { нажать клавишу }

Until ch=#27;

При нажатии клавиши внутрь фигуры будет "убегать" ее уменьшенная копия до нажатия клавиши Esc. Стороны можно делить не пополам, а в каком - либо соотношении. Для стирания фигуры необходимо перерисовать ее в режиме XorPut.

Масштабирование фигур можно проводить используя зависимости, приведенные выше для вращения фигуры относительно своего "центра", изменяя Kx и Ky, при постоянных параметрах xf, yf, A.

 

Практическое задание N 1. 57

 

1. Создать уменьшающийся треугольник (деление сторон 9:1) и пульсирующий треугольник.

2. Создать уменьшающийся прямоугольник (деление сторон 3:1) и пульсирующий прямоугольник.

Примечание к п. 1 и п. 2: пульсация фигуры достигается перерисовкой ее в режиме XorPut, при многократном увеличении и последующем уменьшении коэффициента масштабирования, например, по закону: K= K + i * 0. 02. Где i - параметр цикла.

3. Симметричное отображение фигуры.

Пусть хz - ось зеркальной симметрии, тогда координата "yzi" i - ой точки фигуры в системе координат (xz, yz) определяется по формуле:

yzi= (yi-yf) * cos(A)-(xi-xf) * sin(A),

где xf, yf - координаты любой точки на оси зеркальной симметрии,

xi, yi - координаты отображаемой точки в системе координат экрана,

A - угол наклона оси симметрии относительно оси "x" по часовой стрелке.

 

 

Тогда координаты отраженной точки в системе координат (X0Y) определяются по формулам:

 

xoi = xi + 2 * yzi * sin(A);

yoi = yi - 2 * yzi * cos(A);

 

Приведем пример операторов для расчета координат xo[ i], yo[ i] точек фигуры зеркально отображенной относительно оси, наклоненной под углом "A" и проходящей через точку с координатами xf, yf.

for i:= 1 to N do begin

yzi:= round((y[i]-yf) * cos(A) - (x[i]-xf) * sin(A));

xo[i]:= x[i] + 2 * round(yzi * sin(A));

yo[i]:= y[i] - 2 * round(yzi * cos(A))

end;

 

Практическое задание N 1. 58

 

1. Нарисовать елку с основанием в центре экрана и получить три зеркальных отображения относительно осей, проходящих через центр экрана под углом +45 0 , 0 0 , - 45 0 к оси "х".

2. Выполнить п. 1 для подсвечника со свечой.

4. Штриховка углов.

Определим координаты отрезков, образующих стороны угла и поделим их на N - частей. Соединим попарно точки раздела сторон угла так, чтобы наиболее удаленная от вершины угла точка на одной стороне соединялась с наименее удаленной точкой на другой стороне. Приведем процедуру штриховки угла.

Procedure UGOL ( x 1, y 1, x 2, y 2, x 3, y 3, N : integer );

var xx1, xx2, yy1, yy2, i: integer; k: real;

begin

for i:= 1 to N+1 do begin k:= (i-1)/N;

xx1:=x1+round((x2-x1) * k); yy1:=y1+round((y2-y1) * k);

xx2:=x2+round((x3-x2) * k); yy2:=y2+round((y3-y2) * k));

line(xx1, yy1, xx2, yy2) { линия штриховки угла }

end

end;  

 

Здесь x2, y2 - координаты вершины угла, x1, y1, x3, y3 - координаты крайних точек сторон. Коэффициент "k" определяет удаленность точки от вершины угла. Огибающая пересекающихся отрезков образует параболическую границу.

 

 

Практическое задание N 1. 59

 

1. Составить программу рисования звезды с N - вершинами, имеющими перекрестную штриховку углов. Звезда получается вращением угла вокруг центра, лежащего на биссектрисе на расстоянии, равном удвоенной длине стороны угла.

2. В предыдущей задаче центр узора располагать на биссектрисе с внешней стороны угла.

 

5. Использование рекурсии.

 

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

Рекурсия позволяет компактно реализовать некоторые алгоритмы. При этом нужно корректно определять условие прекращения работы рекурсивной процедуры во избежание зацикливания программы. Приведем пример рекурсивного построения узора последовательным построением отрезков прямых:

Uses Graph;

var Gd, Gm, x1, y1, { x1, y1 - координаты конца отрезка }

l, delta, { l, delta - длина отрезка и ее приращение }

alfa, ugol: integer; { alfa - угол поворота, ugol - текущий угол в градусах }

Procedure OTREZOK(x, y: integer);

begin x1:= x + round(l * cos(ugol * pi/180));

y1:= y - round(l * sin(ugol * pi/180));

line(x, y, x1, y1);

ugol:= ugol + alfa; { изменение угла }

l:= l + delta; { изменение длины отрезка }

{ условие продолжения рекурсии: }

if (x1 > 0) and (x1 < GetMaxX) and (y1 > 0) and (y1 < GetMaxY)

then OTREZOK(x1, y1); { рекурсивный вызов процедуры }

end;

{ (x, y), (x1, y1) - координаты начала и конца отрезка }

begin ugol:= 0; alfa:= 13; l:= 10; delta:= 3;

Gd:= Detect; InitGraph(Gd, Gm, ' с :\tp7\bgi');

OTREZOK(GetMaxX div 2, GetMaxY div 2); { вызов процедуры }

readln; CloseGraph;

end.

Узор получается перемещением отрезка с вращением вокруг точки (x, y). Поскольку внутри процедуры OTREZOK происходит вызов этой же процедуры с фактическими параметрами (x1, y1), то новое построение отрезка начинается с конца предыдущего. Варьируя alfa и delta можно строить различные спиралевидные узоры.

 

Практическое задание N. 1. 60

 

1. С использованием процедуры OTREZOK построить (при alfa= 90 o ) прямоугольный и ромбический спиралевидные лабиринты из отрезков разного цвета.

2. Построить прямоугольник со сторонами разного цвета и основанием, движущимся согласно процедуре OTREZOK.

Следующий пример показывает использование рекурсии при построении узоров, напоминающих кружева. Задается размер "стежка" - короткой линии длиной dl, функция варьирования угла перемещения ugol в зависимости от номера шага n.

uses Graph;

var gD, gM, n, x, y, x1, y1, k: integer; dl, ugol, ugol_0, s, i: real;

{ ----------------------------------------------------------------- }

PROCEDURE ANGLE(x, y: integer);

begin n:= n+1;

ugol:=2 * pi * n/s; ugol_0:=ugol; { равномерное увеличение угла по параметру n }

ugol:= ugol_0 + i * sin(k * ugol); { периодическое отклонение угла:

параметр i определяет амплитуду, k - частоту отклонений }

x1:= x + round(dl * cos(ugol)); { (x1, y1) - координаты следующей точки }

y1:= y + round(dl * sin(ugol));

Line(x, y, x1, y1); { рисуем " стежок " }

if n<s then ANGLE(x1, y1) { рекурсивный вызов }

end;

begin gD:= Detect; InitGraph(gD, gM, 'z:\tp7\bgi');

ugol_0:= 0; { начальное значение угла }

n:= -1; { начальное значение счетчика изменения угла }

x:= 300; y:= 70; { координаты начала рисования }

dl:= 4; { размер линии ("стежка") }

k:= 8; { количество циклических изменений угла }

s:= 500; { количество "стежков" узора }

i:= 2. ; { амплитуда циклических изменений угла }

ANGLE(x, y); readln; CloseGraph end.

 

 

Вид функции "ugol_0" определяет базовую форму узора. В приведенном варианте "ugol_0" равномерно изменяется от 0 до 2 * PI и базовой линией является окружность (многоугольник). Слагаемое i * sin(k * ugol) определяет отклонение от базовой формы узора - циклические пульсации угла и заставляет узор "завиваться" вокруг базовой линии. Коэффициент "k" определяет количество "лепестков" узора, от параметров "i" и "dl" зависит их форма и размер. Параметр "s" определяет количество "стежков" в узоре и следовательно общий размер узора.

Меняя форму базовой линии, функцию пульсации угла, а также размер стежка "dl" в зависимости от номера шага "n", можно получать самые разнообразные узоры. Например, если убрать оператор ugol_0:= ugol;, то базовой линией узора будет прямая, наклоненная к оси "Х" под углом ugil_0. Варьированием i, k, s можно менять периодичность, форму и размер деталей узора.

 

Практическое задание N . 1. 61

 

1. С использованием процедуры ANGLE построить 14 - лепестковый узор без самопересечений с разным цветом для каждого лепестка узора. Построить эллиптический узор, задав вместо dl два различных значения dlx и dly.

2. Построить "кружевную ленту" с базовой линией узора в форме синусоиды: вместо оператора ugol_0:= ugol; подставить ugol_0:= Pi/4 * sin(ugol);.

•  Построить "кружевную рамку", задавая поворот базовой линии через определенное число циклических изменений угла: ugol_0:= ugol_0 + pi/2;.

 

6. Создание узоров построением зеркальных отображений фигуры.

 

Большинство людей впервые знакомятся с некоторыми принципами построения узоров, изучая детский зеркальный калейдоскоп. В калейдоскопе система из трех зеркал создает эффект нескольких шестикратных отражений набора цветных кристаллов. Математически такой принцип построения узора можно описать следующим образом. Имеется "N" выходящих из одной точки лучей - осей симметрии. Угол между лучами равен 2 * PI/N. Строится первая (исходная) фигура в секторе между первым и вторым лучами. Затем строится вторая фигура как зеркальное отображение первой фигуры относительно второго луча, третья фигура, как зеркальное отображение второй фигуры относительно третьего луча и так далее. Если N - четно, то исходная фигура будет также зеркальным отражением N - й фигуры и получившийся узор будет симметричным (правильный калейдоскоп). Если нет необходимости моделировать реальные отражения, то исходную фигуру можно строить с пересечением осей симметрии и по любому количеству секторов.

Ниже приведен пример программы создания узора построением отражений "m" точек относительно "n" осей отражения (зеркал). Исходная фигура - замкнутая ломаная, состоящая из разноцветных отрезков прямых. Для каждой узловой точки линии определяется расстояние до центра узора (радиус r). Угол (ugol), под которым расположена узловая точка относительно горизонтальной линии, вычисляется как арктангенс отношения ординаты "x" к абсциссе "y" (в системе координат центра узора). Угол, под которым расположена отраженная точка, увеличивается на величину, равную удвоенной разности между углом наклона оси отражения и углом расположения отражаемой точки.

"Калейдоскоп":

Строится фигура в виде ломаной линии, состоящей из "m - 1" отрезков прямых и "n" зеркальных отражений этой ломаной относительно осей симметрии, проходящих через центр узора.

Uses Graph, Crt;

type mas = array[1..40, 1..20] of integer;

var Gd, Gm, n, m, i, j,

Rz, { длина зеркала }

xc, yc, { координаты центра узора }

xr, yr: integer; { координаты концов зеркал }

alf: real; { угол между зеркалом и осью X }

x, y: mas; { координаты узлов фигуры }

{ -------------------------------------------------- }

{ процедура построения фигуры в виде ломаной линии с "m" узлами }

Procedure UZOR(m, n: integer; x, y: mas);

Var i, j : integer;

ugol : real;

begin

for j:= 1 to n do begin

moveto(x[m,j],y[m,j]); { установка курсора в m - ную точку ломаной }

for i:= 1 to m do begin { цикл рисования j - ой ломаной по m точкам }

setcolor(i mod 7+9);

lineto(x[i, j], y[i, j])

end end

end;

{ ----------------------------------------------------------------- }

{ процедура расчета координат отражений точки (x, y) относительно центра узора}

Procedure MIRROR(n, m: integer; var x, y: mas);

var i, j : integer;

r, ugol: real; { координаты точки в полярной системе координат }

begin

for i:= 1 to m do begin

if x[i,1]<>0 then ugol:=arctan(y[i,1]/x[i,1]) else ugol:=Pi/2;

r:= sqrt(1. * x[i,1] * x[i,1]+y[i,1] * y[i,1]);

for j:= 1 to n do begin

ugol:= 4 * Pi * j/n - ugol;

x[i,j]:=round(r * cos(ugol)); y[i,j]:=round(r * sin(ugol)) end

end

end;

{ ---------------------------------------------------------------- }

BEGIN Gd:= Detect; InitGraph(Gd, Gm, 'C:\tp7\bgi'); SetWriteMode(1);

xc:= GetmaxX div 2; yc:= GetmaxY div 2; { координаты центра узора }

n:= 12; { число зеркал }

m:= 10; { число узловых точек ломаной }

Rz:= 150; { длина линии зеркала }

for i:= 1 to n do begin alf:= 2. * PI * i/n;

xr:= xc + round(Rz * cos(alf));

yr:= yc - round(Rz * sin(alf));

setcolor(7); line(xr,yr,xc,yc) { построение линий зеркал }

end;

Randomize;

Repeat

for i:= 1 to m do begin { расчет координат точек исходной фигуры }

x[i,1]:= Random(200)+1; y[i,1]:= Random(100) end;

MIRROR(n, m, x, y); { расчет координат отраженных точек

в системе координат узора }

for i:= 1 to m do { расчет координат точек узора}

for j:= 1 to n do begin { в системе координат экрана }

x[i,j]:= x[i,j] + xc; y[i,j]:= y[i,j] + yc end;

UZOR(m,n,x,y); delay(1000); UZOR(m,n,x,y) { рисование узора }

Until KeyPressed; CloseGraph

END.

 

Практическое задание N 1. 61

 

1. Смоделировать детский калейдоскоп для набора из трех разноцветных "кристаллов" ( 3 - х, 4 - х и 5 - ти угольников), размещенных в одном секторе.

2. Смоделировать калейдоскоп с 8 осями симметрии. Смещая при каждом изменении фигуры на пять пикселов диапазон задания координат "х" точек исходной ломанной (10 раз увеличивая, затем 10 раз уменьшая получить пульсирующее движение фигур.

3. Смоделировать вращение узора, полученного из отражений ломанной линии.

•  Смоделировать случайное перемещение узора, полученного из отражений ломанной линии. Контролировать выход узора за границу экрана.

Вверх

Белорусский рейтинг MyMinsk.com Сайты беларуси Регистр "ЗУБР" Каталог на TIGA.BY, а также  новости, работа, объявления, фото и многое другое Rambler's Top100 Белорусский каталог программ Faststart - рейтинг сайтов, каталог интернет ресурсов, счетчик посещаемос­ти Яндекс.Метрика
Hosted by uCoz