lrgraph
.pdf31
Рис. 4.1
SetActivePage(номер_страницы) - для установки номера активной страницы. Необхо-
димо учесть, что нумерация страниц в графическом режиме языка TurboPascal начинается с нуля.
SetVisualPage(номер_страницы) - для установки номера видимой (отображаемой на
экране) страницы.
GetImage(x1, y1, x2, y2, память) - для сохранения изображения заданного участка эк-
рана в ОЗУ. Параметры x1, y1, x2, y2 задают координаты левого верхнего и правого нижнего
углов сохраняемого участка экрана, а память представляет собой переменную-имя буфера в ОЗУ, хранящего данное изображение.
PutImage(x, y, память, способ) - для выдачи на экран сохраненного в ОЗУ участка.
Переменная способ указывает вид объединения передаваемой на экран информации с уже
имеющейся и может принимать следующие значения:
0 |
MOV |
1 |
XOR |
2 |
OR |
3 |
AND |
4 |
NOT |
Значение 0 (MOV) позволяет при наложении c некоторым сдвигом стереть предыдущее изо-
бражение и регенерировать его на новом месте, что создает эффект перемещения. Другие зна-
чения переменной способ позволяют создавать различные видеоэффекты.
Работа с выделенным фрагментом достаточно сложна, так как предполагает использо-
вание переменных типа Pointer (указатель) и требует предварительного определения размера выделяемого прямоугольника с помощью функции ImageSize(x1, y1, x2, y2) и резервирования в ОЗУ для него памяти с помощью процедуры GetMem(память, размер). Более подробно данный инструментарий рассмотрен в примере.
Графический режим позволят как в статике, так и в динамике выводить на экран фрагменты текста, для чего используются следующие процедуры:
32
SetTextJustify(горизонталь, вертикаль) - для выравнивания текста по горизонтали и вертикали.
горизонталь - переменная, задающая режим горизонтального выравнивания и прини-
мающая одно из следующих значений:
0 - левое выравнивание (выводимый символ располагается справа от задаваемой коор-
динаты вывода);
1 - выравнивание по центру;
2 - правое выравнивание.
вертикаль - переменная, задающая режим вертикального выравнивания и принимающая одно из следующих значений:
0 - нижнее выравнивание (выводимый символ располагается сверху по отношению к задаваемой координате вывода);
1 - верхнее выравнивание.
SetTextStyle(шрифт, направление, размер) - для установки текущих параметров выводимого текста.
шрифт - переменная, задающая тип шрифта и принимающая одно из значений в диапа-
зоне 0..4;
направление - переменная, задающая направление вывода текста (0 - по горизонтали, 1 -
по вертикали);
размер - переменная, задающая размер символов. Определяется опытным путем исходя из требований к изображению.
OutTextXY(x, y, строка) - для вывода на экран последовательности символов строка,
начиная с точки с координатами x, y.
OutText(строка) - для вывода на экран последовательности символов строка, начи-
ная с текущей позиции.
Пример программы
Задание: серповидная луна медленно уходит за горизонт. Программа реализована на основе метода выделения, сохранения и наложения сохраненного прямоугольного фрагмента для стирания старого и создания нового изображения на новом месте.
33
Листинг программы
program luna; uses
Graph, Crt; {подключение требуемых модулей} var
Driver, Mode:integer;
p:Pointer; {указатель на место расположения в памяти выделяемого прямоугольного фрагмента}
size:word; {размер выделяемого фрагмента} i:integer; {переменная цикла}
begin
Driver:=0; {автоматическое обнаружение поддерживаемого графического режима}
Mode:=0; {установка подрежима}
InitGraph(Driver, Mode, ''); {запуск графического режима}
SetBkColor(1); {установка синего цвета фона}
ClearDevice; {очистка экрана с окраской в цвет фона}
SetColor(14); {установка цвета для контура луны}
SetLineStyle(0, 0, 3); {установка типа линии: сплошная, толстая}
Arc(100, 100, 324, 36, 100); {задание первой дуги луны}
Arc(150, 100, 300, 60, 66); {задание второй дуги луны}
SetFillStyle(1, 14); {установка стиля заполнения}
FloodFill(205, 100, 14); {заполнения сектора луны желтым цветом}
Size:=ImageSize(180, 40, 220, 160); {определение размера выделяемого фрагмента}
GetMem(p, size); {выделение памяти для выделенного фрагмента экрана}
GetImage(180, 40, 220, 160, p^); {сохранение в памяти выделенного фрагмента} for i:=41 to 450 do {организация цикла для движения луны}
begin
Delay(300); {задержка на 0.3 сек. на каждом шаге}
34
PutImage(180, i, p^, 0); {стирание предыдущего изображения путем наложения фрагмента и генерация того же изображения на новом месте}
end;
Closegraph; {выход из графического режима} end.
Варианты задания
Создать программу, реализующую средствами графики языка программирования TurboPascal следующее динамическое изображение, базирующееся на задании предыдущей лабо-
раторной работы:
1)красное солнце поднимается из-за моря и перемещается вверх и вправо;
2)секундная стрелка совершает полный оборот;
3)два пузырька в стакане всплывают за 15 сек;
4)солнце вращается против часовой стрелки с дискретом 100/сек. Длина цикла 20 сек;
5)один шар из связки поднимется вверх, а второй - с удвоенной скоростью опускается вниз;
6)крюк крана двигается по стреле вправо и опускается вниз;
7)колесо вращается 15 сек с дискретом 0.5 сек, поворачиваясь на каждом шаге на 10о;
8)знак «Кирпич» постепенно (за 20 сек с дискретом 0.4сек на каждом шаге) прячется за го-
ризонт;
9)с дискретом 0.7 сек. меняется цвет светофора. Данная процедура повторяется три раза;
10)один шар на бильярдном столе движется вверх, а второй с удвоенной скоростью вправо;
11)показания термометра изменяются от -100 до 400, а затем в два раза медленней до 00;
12)окна дома разного цвета движутся навстречу друг другу и в конечном итоге меняются мес-
тами;
13) лестница перемещается справа налево, а утолщенная нижняя перекладина - за это же вре-
мя - вверх;
14)к парашюту подвешено слово «КГТУ». Все изображение опускается вниз и сносится влево с удвоенной скоростью;
15)диск телефона поворачивается на пять цифр с дискретом 2 сек;
16)на верху арки фонарь. Арка перемещается по экрану справа налево, при этом меняется цвет фонаря;
35
17)стол по синусоиде (один цикл) перемещается вдоль экрана;
18)стилизованное изображение шашки проходит по главной диагонали доски с дискретом 0.7
сек;
19)мяч перемещается снизу вверх и к концу движения уменьшается в два раза;
20)буква Н перемещается слева направо и уменьшается к концу движения в два раза;
21)на экране отображается понедельный по горизонтали календарь текущего месяца. Красная рамка перемещается по датам с дискретом 0.7 сек.;
22)на экране отображается понедельный по вертикали календарь текущего месяца. Красная рамка перемещается по датам с дискретом 1.1 сек.;
23)на экране по горизонтали нарисован спидометр до 200 км/час. Шкала доходит до 180 км за
20 сек., а затем за 15 сек. опускается до 60 км.;
24)справа налево по экрану движется стрелка, у которой хвост движется в два раза медленней начала;
25)на экране квадрат со стороной 200 пикселей. После запуска движения вертикальные сто-
роны начинают сдвигаться до превращения прямоугольника в прямую линию за 15 сек. Затем идет возврат в исходное состояние и повторение за то же время подобного движения верти-
кальных сторон; 26) на экране квадрат со стороной 300 пикселей. По часовой стрелке со скоростью 50 пиксе-
лей/сек вдоль внутренней стороны квадрата движется меньший квадрат со стороной 30 пиксе-
лей.
Выполнение лабораторной работы
1.Получить задание у преподавателя.
2.Написать и отладить программу, реализующую требуемое изображение.
3.Результат работы программы продемонстрировать преподавателю.
4.Напечатать листинг программы.
Содержание отчета
Отчет включает:
36
1)содержание задания;
2)блок-схему программы;
3)листинг программы;
Контрольные вопросы
1.Каким образом осуществляется смена графических страниц в алгоритмическом языке TurboPascal?
2.Можно ли менять высоту символов, отображаемых в графическом режиме?
3.Можно ли размещать текст вертикально по экрану в графическом режиме?
4.Можно ли использовать окна при создании динамического изображения в графическом режиме?
5.Какие предварительные операции требуются для сохранения в памяти ПК выделенного фрагмента?
Рекомендуемая литература
Смотри литературу, рекомендованную к лабораторной работе №3.
37
Лабораторная работа №5
Преобразование двумерных координат
Цель работы: исследование математических методов и алгоритмов преобразования двумерных координат в процессе построения сложных графических изображений.
Введение
Преобразования координат широко используются при синтезе как статических, так и динамических изображений с целью реализации таких операций над рисунком как перенос, поворот, подобие, симметрия. В лабораторных работах №2 и 4 движение создавалось путем переноса в системе координат, неявно существующей на экране дисплея. Перенос является достаточно простой операцией, т.к. реализуется путем изменения значений одной и/или второй координат. Другие операции, а тем более их комбинация, характеризуются большей сложностью и требуют соответствующих математических преобразований. Для простоты в данной лабораторной работе рассматриваются только двумерные преобразования. Обычно в данном процессе исходно задаются основные (первичные) координаты x1, y1, а через них в виде уравнений просчитываются вторичные координаты x22, y22.
x22 = f(x1, y1), y22 = f(x1, y1).
Наиболее распространены так называемые аффинные преобразования /1/, которые предполагают сохранение после расчета вторичных координат параллельность и формы у
прямых. Общий вид уравнений таких преобразований имеет вид
x22 = axxx1 + axyy1 + ax, y22 = ayxx1 + ayyy1 + ay.
При этом сдвиг без поворота характеризуется матрицей коэффициентов
1 |
0 |
ax |
0 |
1 |
ay |
где ax, ay - задают сдвиг соответственно по осям x и y, т.е. x2 = x1 + ax,
38
|
|
|
y2 = y1 + ay. |
|
Операция масштабирования (преобразования подобия) реализуется матрицей |
||||
|
М |
0 |
0 |
|
|
|
|||
|
0 |
М |
0 |
|
|
|
|
|
|
Зеркальное отображение относительно диагонали первого квадранта (смена координатных осей) предполагает матрицу вида
0 |
1 |
0 |
1 |
0 |
0 |
Повороту на угол α против часовой стрелки соответствует матрица
сosα |
-sinα |
0 |
sinαα |
cosα |
0 |
Комбинации двух или более операций преобразования соответствует комбинация ко-
эффициентов соответствующих матриц. Так, например, сдвиг с одновременным поворотом
реализуется матрицей |
|
|
|
|
сosα |
-sinα |
ах |
|
|||
|
sinαα |
cosα |
аy |
|
|
|
|
Описание среды программирования
При преобразовании координат в среде языка программирования TurboPascal необхо-
димо учесть, что графический экран ПК представляет собой четвертый квадрант прямоуголь-
ной системы координат, т.е. начало координат находится в левом верхнем углу. Полноценная система координат создается самим пользователем путем переноса ее начала вниз и/или впра-
во на величины x и/или y, т.е. реализуется локальная система, сдвинутая на данные величи-
ны относительно глобальной. В дальнейшем, глобальные координаты всех точек (xг, yг) пере-
считываются через локальные (xл, yл) по следующим уравнениям: xг = xл + x,
yг = y - yл.
Вторая проблема, возникающая обычно при сложных преобразованиях, - разная раз-
решимость (количество пикселей на единицу длины) графического экрана по горизонтали и
39
вертикали. Попытка изобразить квадрат путем задания одинакового количества пикселей по его сторонам приводит к отображению прямоугольника, вытянутого по высоте. Данный эффект отсутствует только при разрешении 640х480 и особенно усиливается при установке подрежимов с низким количеством пикселей по вертикали, например, 640х200 (см. лабораторную работу №3). Для устранения данного эффекта средствами языка Паскаль производится предварительное масштабирование изображения с помощью процедуры GetAspectRatio(mx, my),
где mx, my - переменные, в которые записывается число точек по горизонтали и вертикали. В дальнейшем, при построении требуемого изображения все координаты по оси x должны умножаться на отношение my/mx или, наоборот, все координаты по оси y умножаются на отношение mx/my. При этом возникает еще одна проблема, связанная с особенностями языка Паскаль: получаемые при умножении масштабированные координаты могут принимать вещественные значения, что запрещено для параметров графических примитивов данного языка. Поэтому все результаты таких умножений должны округляться функцией Round.
Пример программы
В первом квадранте локальной системы координат нарисовать две вертикальные параллельные линии, а затем сдвинуть их вверх и вправо на 100 пикселей и повернуть на 30о против часовой стрелки относительно начала локальных координат.
Начало локальной системы координат расположим в точке (300, 320) пикселей. Можно дополнить программу возможностью задания начала в диалоговом режиме при каждом запуске программы. Фрагмент программы, используемый для создания на экране локальной системы координат, выделен в отдельную процедуру, чтобы его можно было использовать в следующей лабораторной работе.
Листинг программы
Program Linii;
uses
Graph, Crt; var
40
GraphDriver:integer;
GraphMode:integer;
mx, my:word; {кооффициенты масштабирования}
x11, x12, x21, x22, y11, y12, y21, y22:integer; {координаты концов линий} dx, dy:integer; {сдвиг локальных координат относительно глобальных} a:real; {угол поворота}
x0, y0:integer; {величина сдвига линий в системе локальных координат}
procedure XY(xn, yn:integer); {процедура создания на экране локальных координат} begin
SetLineStyle(0,0,1); {установка стиля линий}
Line(xn, 300, xn, 50); {отображение на экране системы координат}
Line(xn, 50, xn-5, 60);
Line(xn, 50, xn+5, 60);
Line(40, yn, 600, yn);
Line(600, yn, 593, yn-3);
Line(600, yn, 593, yn+3);
SetColor(4); {установка цвета для вывода символов}
SetTextJustify(0,0); {установка стиля выравнивания текста}
SetTextStyle(0, 0, 1); {установка стиля текста}
OutTextXY(597, yn+15, 'X'); {вывод заголовка оси Х}
OutTextXY(xn-10, 50, 'Y'); {вывод заголовка оси Y} end;
begin
GraphDriver:=3; {установка графического режима EGA}
GraphMode:=1; {установка подрежима с разрешением 640x350}
InitGraph(GraphDriver, GraphMode, '' '');
SetBkColor(9); {установка светло-синего цвета фона}
ClearDevice; {закрашивание экрана цветом фона}
GetAspectRatio(mx, my); {определение коэффициентов масштабирования}
