Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология Образование Политология Производство Психология Стандартизация Технологии |
Рисование геометрических фигур
Построение заполненных фигур
Ряд графических процедур выполняет построение заполненных фигур - фигур с замкнутым контуром, автоматически заполняемых сразу после построения. По умолчанию заполнение производится сплошным белым цветом. Цвет и стиль (орнамент) заполнения можно устанавливать из стандартного набора BGI или определять самим. SetFillStyle(P, N); - процедура установки орнамента P=0, 1, ..., 12 и цвета с номером " N" для заполняемых фигур.
P = 0 - сплошное заполнение цветом фона, при этом значение " N" игнорируется, P = 1 - сплошное заполнение цветом с номером " N", P = 2... 11 - стандартный набор орнаментов BGI, P = 12 - орнамент и цвет определяет пользователь. SetFillPattern(PP, N); - процедура установки орнамента пользователя PP и цвета с номером " N" для заполняемых фигур.
Параметр PP имеет тип FillPatternType или array [1.. 8] of byte. Байт состоит из восьми битов и соответствует ряду из 8 пикселов, т. е. параметр РР определяет элемент орнамента размером 8*8 пикселов (восемь рядов по восемь пикселов). Если бит равен 1, то пиксел высвечивается заданным цветом, если бит равен 0 - текущим цветом фона.
Пример орнамента в виде буквы Y: № элемент двоичные шестнадцатеричные Байта орнамента числа числа 1 1 0 0 0 0 0 0 1 $81 2 1 1 0 0 0 0 1 1 $C3 3 0 1 1 0 0 1 1 0 $66 4 0 0 1 1 1 1 0 0 $3C 5 0 0 0 1 1 0 0 0 $18 6 0 0 0 1 1 0 0 0 $18 7 0 0 0 1 1 0 0 0 $18 8 0 0 0 1 1 0 0 0 $18 Шестнадцатеричные цифры соответствуют двоичным тетрадам цифр:
0000 - 0 0100 - 4 1000 - 8 1100 - С 0001 - 1 0101 - 5 1001 - 9 1101 - D 0010 - 2 0110 - 6 1010 - A 1110 - E 0011 - 3 0111 - 7 1011 - B 1111 - F
Причем, двоичное число разбивается на тетрады цифр с конца числа, а шестнадцатеричное число получается заменой каждой тетрады соответствующей цифрой с добавлением в начале числа символа " $".
Орнамент удобно задавать, используя переменные с начальным значением (типизированные константы), например: {оператор описания: } Const Bukva_Y: FillPatternType=($81, $C3, $66, $3C, $18, $18, $18, $18 );
{оператор выполнения: } SetFillPattern(Bukva_Y, 4);
Можно добавлять один орнамент к другому используя логические операции, например, A и B - исходные орнаменты, Z - результирующий орнамент. Тогда: Z: = A and B; - орнамент из совпадающих единичных частей исходных орнаментов, Z: = A or B; - орнамент с добавлением единичных частей исходных орнаментов, Z: = A xor B; - орнамент из несовпадающих единичных частей исходных орнаментов, Z: = not A; - орнамент инверсный (обратный) к исходному орнаменту. Z: = A xor A; - обнуление, Z: = A xor (not A); - сплошное заполнение орнамента.
Приведем процедуры построения заполненных установленным орнаментом фигур. Граница заполняемых фигур рисуется текущим цветом для линий. Bar(X1, Y1, X2, Y2); - построить заполненный прямоугольник с заданными координатами левого верхнего (X1, Y1) и правого нижнего (X2, Y2) углов. Аналог процедуры: Rectangle(X1, Y1, X2, Y2);. Bar3d(X1, Y1, X2, Y2, d, t); -построить параллелепипед с заполненной передней гранью. Координаты углов: (X1, Y1), (X2, Y2), глубина " d". Переменная " t" типа boolean задает вывод верхней грани. При t=TopOn (true) верхняя грань показывается, при t=TopOff (false) - нет. FillEllipse(X, Y, RX, RY); - построить заполненный эллипс с центром в точке (X, Y) и радиусами ( полуосями ): RX - по горизонтали, RY - по вертикали. Sector(X, Y, A1, A2, RX, RY); - построить заполненный сектор эллипса. A1 и A2 - начальный и конечный углы (в градусах), отсчитываемые против часовой стрелки относительно направления оси Х. Аналог процедуры: Ellipse(X, Y, A1, A2, RX, RY); строит сектор эллипса без автоматического заполнения. PieSlice(X, Y, A1, A2, R); - построить заполненный сектор круга с центром в точке (X, Y) и радиусом R. Аналог процедуры: Arc(X, Y, A1, A2, R); строит дугу окружности. FillPoly(N, M); - заполнить произвольную плоскую фигуру с границей, описанной массивом точек. N - число точек границы, М - параметр - переменная типа PointType, определяемая в модуле Graph в виде: TYPE PointType = Record x, y: Integer End; В программе массив можно описать операторами: Const N=100; Var M: array[1..N] of PointType; Присвоение значений можно провести в цикле: For i: =1 to 3 do begin M[i].x: =random(95); M[i].y: =random(95) end; Приведем пример программы, выводящей два прямоугольника с орнаментами пользователя (bukva_Y и Red_50), а затем демонстрирующей набор стандартных орнаментов на передней грани параллелепипедов:
Uses Graph; Сonst bukva_Y: FillPatternType=($81, $C3, $66, $3C, $18, $18, $18, $18); Red_50: FillPatternType=($AA, $55, $AA, $55, $AA, $55, $AA, $55); var i, x1, y1, x2, y2, Gd, Gm: integer; Begin Gd: = Detect; InitGraph(Gd, Gm, '_'); SetFillPattern(Red_50, Red); { орнамент - 50% красных пикселов } Bar(250, 10, 350, 110); SetFillPattern(bukva_Y, Blue); { орнамент - синяя буква " Y" } Bar(340, 30, 440, 130); { стандартный набор из 12 орнаментов BGI выводим цветом с номером " 11" } for i: =0 to 11 do begin SetFillStyle(i, 11); if i< 6 then begin x1: =90*i; y1: =150 end else begin x1: =90*(i-6); y1: =270 end; x2: =x1+70; y2: =y1+80; Bar3d(x1, y1, x2, y2, 10, TopOn) end; ReadLn; CloseGraph End. Заполняя не черный экран орнаментом Red_50, можно получить новые цвета фона. Выбранным из стандартных или определенным орнаментом можно заполнить любую замкнутую область с границей цвета " N" оператором FloodFill(X, Y, N);
Заполнение начинает производится из точки X, Y и ограничивается при достижении границы цвета с номером " N". Например: Rectangle(x1, y1, x2, y2); FloodFill((x1+x2) div 2, (y1+y2) div 2, Red); Если область не замкнута или цвет границы не равен " N", то заполнение " разольется" по экрану.
Практическое задание N 1. 54
1. С использованием оператора цикла нарисовать на экране 12 одинаковых заполненных различными стандартными орнаментами фигур ( в 3 ряда по 4 фигуры). По нажатию клавиши должен меняться вариант фигуры: 1. 1 Прямоугольник, 2. 1 Эллипс, 1. 2 Параллелепипед. 2. 2 Круг. Выполнить задание с использованием процедур рисования фигур без автоматического заполнения, а затем заполнить их. 2. Нарисовать 5 вложенных прямоугольников с увеличением размера на 20 пикселов в каждом направлении. Стиль заполнения для каждой фигуры определить буквами Вашего имени. 3. Нарисовать 5 соосных кругов разного цвета с уменьшением радиуса на 10 пикселов. Стиль заполнения для каждого круга определить его номером, т. е. цифрами 1, 2, 3, 4, 5. 4. Определить три орнамента заполнения: " снежинка", " иголки" с наклоном влево и вправо. Нарисовать из треугольников пять елок и заполнить их орнаментом " иголки". Заполнить экран орнаментом " снежинка". 5. Создать элемент орнамента с единицами (4*4) в центре. Нарисовать на экране картину " ночной город", используя фрагменты " звездного неба" и пять прямоугольников, заполненных орнаментом 4*4 разного цвета. 6. Используя исходные орнаменты из одной линии составить с использованием логических операций орнаменты цифр: 1, 6, 7 и букв: B, F, E.
Работа с линиями
В графическом режиме курсор невидим, его положение можно определить функциями, возвращающими значения координат: GetX; - по оси " Х", GetY; - по оси " Y".
Следующие процедуры перемещают курсор без рисования: MoveTo(x, y); - переместить курсор в точку с координатами (x, y), MoveRel(dx, dy); - сместить курсор на расстояние dx, dy от текущего положения.
Для построения многоугольников и ломаных линий удобно использовать процедуры: LineTo(x, y); - провести отрезок прямой линии от текущего положения курсора до точки с координатами X, Y. LineRel(dX, dY); - провести отрезок прямой линии от текущего положения курсора до точки, смещенной на расстояние dX, dY по соответствующим осям. В отличие от процедуры Line(x1, y1, x2, y2); процедуры LineTo(x, y); и LineRel(dX, dY); при своем исполнении перемещают текущий указатель. Пример операторов для построения восьмиугольника: R: =100; { расстояние от вершин до центра xc, yc } xc: = GetMaxX div 2; yc: = GetMaxY div 2; for i: = 1 to 8 do begin alfa: = i * pi/4; { значение угла в рад. } x[i]: = xc + round(R * cos(alfa)); { координаты вершин } y[i]: = yc + round(R * sin(alfa)) end; MoveTo(x[8], y[8]); { исходная позиция для рисования } for i: = 1 to 8 do LineTo(x[i], y[i]); { рисование линий }
Для отрезков прямых линий и процедур с их использованием можно задать режимы построения прямых линий оператором: SetWriteMode(N);
N=0 - замещение линией изображения на экране ( режим CopyPut ) используется по умолчанию, N=1 - изображение комбинируется ( режим XorPut ). Работа функции состоит в изменении согласно логической операции " исключающее ИЛИ" исходного значения цвета пиксела (числа " 1" или " 0" ). Логическая функция Xor, примененная к одной переменной дважды, восстанавливает ее исходное значение: ( J xor I ) xor I = J. Следовательно при повторном проведении линии в режиме XorPut изображение этой линии уничтожается, а цвет пикселов экрана становится исходным. На этом правиле основаны некоторые программы построения движущихся изображений.
Пример операторов для рисования движущегося прямоугольника: SetWriteMode(1); a: = 100; b: = 50; { стороны прямоугольника } x1: = 0; y1: = GetMaxY div 2; N: = GetMaxX - x1 - a; { N - число перемещений } for i: = 0 to N do begin Rectangle(x1+i, y1, x1+a+i, y1+b); { рисование прямоугольника } delay(10); Rectangle(x1+i, y1, x1+a+i, y1+b); { стирание прямоугольника } end;
Практическое задание N 1. 55
1. Составить процедуру рисования N - угольной звезды. В параметры процедуры включить число лучей звезды, радиусы вписанной и описанной окружностей, цвет линий и координаты центра звезды. Перемещать две звезды разного цвета в пределах экрана случайным образом.
2. Составить процедуру рисования N - угольной звезды, где N= 3, 5, 7, ... Операторы рисования имеют вид: M: =N div 2; Moveto(x[1], y[1]); For i: =1 to N do begin j: =(M*i) mod N + 1; LineTo(x[j], y[j]) end; Перемещать две звезды разного цвета в пределах экрана. Толщину и форму (стиль) линий отрезков прямых, прямоугольников, окружностей, эллипсов можно задать оператором SetLineStyle(F, P, T);
Здесь F - форма линии из стандартного набора BGI: F=0 - сплошная, F=1 - пунктирная, F=2 - штрих-пунктирная, F=3 - штриховая. F=4 - форма линии задается параметром Р. При F< 4 значение Р игнорируется. Параметры F, P, T типа Word. Стиль линии Р - число, двоичное представление которого отображает заполнение линии длиной 16 пикселов. Если разряд числа равен 1, то пиксел высвечивается, 0 - не высвечивается. Удобно использовать шестнадцатеричные числа. Например: P = $35F1 = 0 0 1 1 0 1 0 1 1 1 1 1 0 0 0 1 ( двоичное ) отобразит стиль:
Можно использовать десятичную форму записи значения параметра " Р", где 0< = P < = 65535= 216-1. T - толщина линии может принимать два значения: T= 1 - тонкая (1 пиксел), T= 3 - толстая (3 пиксела). Например, операторы: SetLineStyle(4, $5555, 3); Line(x1, y1, x2, y2); определяют толстую мелким пунктиром линию.
Практическое задание N 1. 55
1. Вывести на экран горизонтальные толстые линии с двоичным представлением:
1111000001100000, 1111000011110000, 0111101111011110, 1100110011001100, 1001100110011001, 1111100011111000.
2. Вывести на экран вертикальные толстые линии с двоичным представлением:
0101010101010101, 1100011000110001, 1111110011111100, 0111011101110111, 1110001110001110, 1111000000001111.
3. Вывести на экран линии разных форм, заданных параметром РN = PN-1 + 2 * N, где P0= 1; N= 1, .., 150. Линии располагать вертикально. 4. Вывода на экран линий разных форм, заданных параметром РN = PN-1 + 2N, где P0= 1; N= 1, .., 15. Линии располагать горизонтально. 5. Нарисовать расходящийся из центра экрана по спирали ромбический лабиринт шириной 6 пикселов из отрезков наклонных прямых. Очищать экран и менять толщину и форму линии F= 0, .., 3. 6. Нарисовать расходящийся из центра экрана по спирали прямоугольный лабиринт шириной 5 пикселов из отрезков вертикальных и горизонтальных прямых. Очищать экран и менять толщину и форму линии.
Применяя к исходным стилям линий пользователя логические операции, можно получать новые стили линий. Например:
P3 = P1 and P2 - линии из совпадающих единичных битов. P3 = P1 or P2 - добавление единичных битов. P3 = P1 xor P2 - обнуление совпадающих значений битов. P3 = not P2 - изменение значений битов на противоположные. Таблица результатов выполнения логической операции " xor" над битами.
( Таблица результатов выполнения бит " A" операция бит " B" результат логических операций " or" и " and" над битами приведена на стр.. ) Xor 1 0 1 xor 0 1 Результат операции " A xor B" равен 0 xor 0 0 единице при различных значениях битов 0 xor 1 1 " A" и " B", иначе результат равен нулю.
Практическое задание N 1. 56
1. Создать эффект " бегущих огней" перемещением на один пиксел набора из трех касающихся толстых пунктирных линий ( перерисовка в режиме XorPut ). Крайние линии стиля " Р", средняя - стиля " not P". 2. Создать штриховые стили " Р1", " Р2" и рассчитать с использованием всех логические операций приведенные выше стили Р3. Вывести на экран исходные и расчетные линии.
Создание графических узоров
Графические узоры создают для декоративных заставок, рекламы, демонстрации возможностей аппаратуры. Как правило, компьютерные узоры выполняются по весьма простым алгоритмам. Главное - идея создания декоративного эффекта. Рассмотрим некоторые из принципов составления узоров на плоскости:
Перемещение фигуры. Если фигуру перемещать не вращая относительно своего " центра", то получим плоскопараллельное движение тела (любой отрезок прямой на фигуре остается параллельным самому себе). За " центр" фигуры может быть принята любая точка жестко связанная с фигурой. Обычно " центр" фигуры (xf, yf) перемещают относительно центра узора (xc, yc) по определенному закону: xc Fx xf X yc xf = xc + Fx(" параметры" ), Fy yf = yc + Fy(" параметры" ),
yf где Fx, Fy - функции от параметров. Y Y
Приведем пример задания закона движения " центра" фигуры относительно центра узора: 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);
Масштабирование фигуры. Рассмотрим случай уменьшения размеров фигуры делением ее сторон.
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 - параметр цикла.
|
Последнее изменение этой страницы: 2017-03-17; Просмотров: 565; Нарушение авторского права страницы