лабораторные работы паскаль. Практикум по программированию на языке Паскаль Учебное пособие
Скачать 0.89 Mb.
|
Тема: "Введение в машинную графику" Цель работы Овладение начальными навыками работы с графическим режимом экрана, используя модуль GRAPH. Краткие сведения из теории Стандартный модуль GRAPH содержит библиотеку из более чем 50 графических программ. В нем поддерживается несколько видов закрашивания, типов линий и шрифтов, размер которых можно изменять. Для переключения экрана в графический режим необходимо выполнить процедуру: InitGraph (var Graphdriver : integer; var GraphMode : integer; PathToDriver : string); По этой процедуре выполняются: − поиск в каталоге PathToDriver файла драйвера графической карты с номером GraphDriver; − загрузка драйвера в оперативную память; − установка указанного графического режима GraphMode. Если имя каталога не указано (параметр PathToDriver представляет собой пустую строку ''), то файл ищется в текущем каталоге. Если GraphDriver = 0, то происходит автоматическое определение графической среды, а переменным GraphDriver и GraphMode присваиваются величины, определяющие номер драйвера и номер режима графического экрана. Номера карт (графических драйверов) и режимов могут быть выражены с помощью следующих обозначений: Detect=0 -aвтоматическое распознавание графической карты; CGA=1 - карта CGA; MCGA=2 - карта MCGA; EGA=3 - карта EGA; EGA64=4 - карта EGA64; EGAMono=5 - карта EGAMono; Reserved=6 - зарезервировано (не используется); HercMono=7 - карта Hercules; ATT400=8 - карта ATT400; VGA=9 - карта VGA; PC3270=10 - карта PC3270, а также используются некоторые символы режима: EGALo=0 - 620х200 пикселей, 16 цветов, 4 страницы; EGAHi=1 - 640x350 пикселей, 16 цветов, 2 страницы. Пиксель - это единичный элемент экрана. Количеством пикселей по горизонтали и вертикали определяется размер графического экрана. Синонимом пикселя является понятие "точка". Для перехода из графического режима в текстовый используется процедура CloseGraph без параметров, которая устанавливает текстовый режим и очищает память, автоматически выделенную программе. Это выполняется подсистемой управления графикой. Для того, чтобы с помощью операторов, строящих изображение, можно было обращаться к заданным точкам экрана, необходимо иметь возможность однозначно их идентифицировать. Положение точки (пикселя) задается с помощью двух координат X, Y, где X - номер столбца, Y - номер строки. По соглашению верхний левый угол экрана имеет координаты (0,0). Координата X увеличивается при перемещении вправо, а координата Y - при перемещении вниз. Таким образом, координаты каждого из четырех углов и конкретной точки, например, середины экрана, могут выглядеть следующим образом: 103 Здесь рассмотрен графический режим с матрицей экрана 640х350 пикселей. В некоторых других режимах эта матрица может быть иной, например, 320х200 или 640х200 и так далее. Определение координат правого нижнего угла экрана выполняется по функциям: GetMaxX, GetMaxY. Синтаксис: GetMaxX : integer; GetMaxY : integer. Графические объекты могут быть черно-белыми или цветными. Черно-белые рисунки выполняются обычно в системах с графическими картами, не учитывающими цвет, например, с картой Hercules. Если возможен вывод в цвете (например, карта EGA или CGA), то при установке графического режима можно определить его параметры и тем самым доступную цветовую гамму. Цвета гаммы (она отсутствует для карты Hercules) пронумерованы от 0 до GetMaxColor. Цвета могут быть фиксированными (для карты CGA), либо произвольно изменяемыми (для карты EGA и VGA). Если цвета могут изменяться, то присвоение выбранного цвета позиции цветовой гаммы производится с помощью процедуры SetPalette. Синтаксис: SetPalette (ColorNum, Color : word); Идентификатор цвета Color присваивается позиции ColorNum цветовой гаммы. Изменение цвета на экране будет обнаружено после выполнения процедуры SetPalette. Идентификаторы цветов могут быть выражены следующим образом: Black=0 (черный); DarkGray=8 (темно-серый); Blue=1 (синий); LightBlue=9 (светло-синий); Green=2 (зеленый); LightGreen=10 (светло-зелен.); Cyan=3 (голубой); LightCyan=11 (светло-голуб.); Red=4 (красный); LightRed=12 (светло-кpасн.); Magenta=5 (лиловый); LightMagenta=13 (светло-лилов.); Brown=6 (коричневый); Yellow=14 (желтый); LightGray=7 (светло-серый); White=15 (белый). Выбор номера цвета для изображения объектов обеспечивает процедура SetColor. Синтаксис: SetColor(N : word); При выполнении этой процедуры объекты будут рисоваться цветом, связанным аппаратно или программно с позицией N цветовой гаммы. Программное присвоение этой позиции другого цвета немедленно изменяет цвет рассматриваемых объектов. Процедура SetBkColor изменяет цвет фона на такой цвет, который соответствует позиции N текущей цветовой гаммы. Синтаксис: SetBkColor(N : word). 14.1. Рисование графических примитивов Рисование точки (пикселя) с координатами (X, Y) цветом с номером Color выполняется процедурой PutPixel(X, Y: integer; Color: word). Рисование отрезков прямых линий можно выполнить одной из следующих трех процедур: Line(X1, Y1: integer; X2, Y2: integer) - рисование отрезка прямой линии, соединяющего точки с координатами (X1,Y1) и (X2,Y2); (639,0) (0,0) (319,174) (639,349) (0,349) 104 LineRel(dX, dY: integer) - рисование отрезка прямой линии от текущего положения графического курсора на расстояние dX по горизонтали и dY по вертикали; LineTo(X, Y: integer) - рисование отрезка прямой линии от текущего положения графического курсора к точке, имеющей координаты (X, Y). После установления графического режима по умолчанию графическим окном будет весь экран. Левый верхний угол графического экрана имеет координаты (0,0), а правый нижний (GetMaxX, GetMaxY). Графическое окно можно установить с помощью процедуры: SetViewPort(X1, Y1: integer; X2, Y2: integer; Clip :boolean); Процедура задает графическое окно в виде прямоугольника с координатами противоположных углов (X1, Y1) и (X2, Y2). CLIP определяет, должны ли обрезаться выходящие за пределы окна части рисунка: если этот параметр задается константой ClipOff (или False), то не обрезать, если же константой ClipOn (или True), то обрезать. Все графические операции выполняются в текущем графическом окне, а координаты графического курсора отсчитываются всегда относительно левого верхнего угла окна. Графический курсор невидим, но его текущие координаты могут быть определены с помощью процедур GetX и GetY. Синтаксис: GetX : integer; GetY : integer. Для очистки графического экрана используется процедура без параметров ClearDevice. После очистки экрана графический курсор будет установлен в верхнем левом углу текущего графического окна. Процедура без параметров ClearViewPort очищает текущее графическое окно и заполняет его цветом первой позиции цветовой гаммы. Пример графического построения: Пусть требуется на желтом фоне экрана размером 640х350 построить графическое окно симметрично относительно центра экрана с размерами в два раза меньше размеров экрана, и в этом окне построить синюю диагональную прямую и красную точку в левом нижнем углу окна. Программа: Program Gra1; Uses Graph; {вызов модуля Graph} Var Driver, Mode : integer; Begin Driver := Detect; {автоматическое распознавание карты} InitGraph(Driver,Mode,''); {установка графического режима} SetBkColor(14); {установка желтого цвета фона} SetViePort(160,88,479,262,ClipOn);{выделение графического окна размером 320х175} SetColor(1); {выбор синего цвета} LineRel(319,174); {рисование диагонали} PutPixel(0,174,4); { отображение красной точки } Readln; CloseGraph { возврат в текстовый режим } end. Здесь предложение READLN позволяет задержать на экране окно вывода с графическими изображениями до тех пор, пока не будет нажата клавиша Рисование окружности с центром в точке (X, Y) и радиусом Radius выполняется процедурой Circle(X, Y: integer; Radius: word); Рисование дуги окружности с центром в точке (X, Y), радиусом Radius, углом начала StAngle и углом конца EndAngle, выполняется процедурой: Arc(X, Y : integer; StAngle, EndAngle : word; Radius : word). 105 Углы StAngle и EndAngle выражаются в радианах. Рисование происходит против движения часовой стрелки. Рисование дуги эллипса с центром в точке (X, Y), полуосями XRadius и YRadius, углами начала StAngle и конца EndAngle выполняется процедурой: Ellipse(X, Y: integer; StAngle, EndAngle : word; Radius, YRadius : word). Углы выражаются в радианах. Рисование осуществляется против часовой стрелки. Для StAngle = 0 и EndAngle = 2 будет нарисован полный эллипс. Изображение закрашенного сектора круга выполняется процедурой: PieSlice(X, Y : integer; StAngle, EndAngle : word; Radius : word). Параметры этой процедуры имеют тот же смысл, что и в процедуре Arc, рассмотренной выше. Шаблон закраски задается процедурой SetFillStyle (см. ниже). Пусть, например, требуется построить сектор круга с центром в точке (319, 174), радиусом в 100 точек и представляющим собой левую нижнюю четверть круга. Для этого достаточно выполнить процедуру PieSlice со следующими параметрами: PieSlice (319,174,180,270,100). Процедурой Reсtangle(X1, Y1: integer; X2, Y2: integer) будет построен прямоугольник, противоположные вершины которого имеют координаты (X1, Y1) и (X2, Y2). Процедура Bar(X1, Y1: integer; X2, Y2: integer) в отличие от предыдущей процедуры строит закрашенный прямоугольник. Допустим, необходимо построить закрашенный в синий цвет прямоугольник с горизонтальной стороной в 200 точек, с вертикальной в 100 точек и с центром в точке (319, 174). Два следующих предложения решают эту задачу: SetColor (1); { выбор синего цвета } Bar(219,124, 419,224); {вычерчивание закрашенного прямоугольника} Выбор типа линии, которой будет нарисован объект, можно выполнить процедурой: SetLineStyle(LineStyle: word; Pattern: word; ThickNess:word); Выбор типа линий выполняется на основании LineStyle и толщины линии по ThickNess. Если LineStyle = UserBitLn, то тип линии выбирается по системе битов Pattern. Этот параметр рассмотрен при описании процедуры "заливки". Тип линии может быть выражен следующим образом: SolidLn = 0 - сплошная линия; DottedLn = 1 - пунктирная линия (из точек); CenterLn = 2 - осевая линия (из точек и тире); DashedLn = 3 - штриховая линия; UserBitLn = 4 - линия, определяемая пользователем. Толщина линий может быть выражена следующим образом: NormWidth = 1 - тонкая линия; ThickWidth = 3 - толстая линия . Пример Построить прямоугольник точечной тонкой линией зеленого цвета, противоположные углы которого имеют координаты (10,10) и (319,174). Программа: Program Rect; Uses Graph; Var dr, mode : integer; Begin { инициализация граф. экрана } dr := detect; InitGraph (dr, mode,''); { Установка тонкой (1) линии точечного типа } 106 SetLineStyle(DottedLn, 0, 1); SetColor(2); { вычерчивание прямоугольника } Rectangle(10,10, 319,174); Readln End. Заполнять области стандартными шаблонами позволяет процедура: SetFillStyle(Pattern : word; Color : word), где Pattern задает номер шаблона, а Color - номер цвета шаблона. Номера заполняющих шаблонов могут быть выражены следующим образом: EmptyFill = 0 - заполнение цветом фона; SolidFill = 1 - сплошное заполнение; LineFill = 2 - заполнение толстыми горизонтальными линиями; LtSlashFill = 3 - заполнение наклонными линиями (правый наклон); SlashFill = 4 - заполнение толстыми наклонными линиями; BkSlashFill = 5 - заполнение толстыми косыми линиями (левый наклон); LtBkSlashFill = 6 - заполнение косыми линиями; HatchFill = 7 - заполнение вертикальной сеткой; HatchFill = 8 - заполнение наклонной сеткой; InterleaveFill = 9 - заполнение переплетенными линиями; WideDotFill = 10 - заполнение точками; CloseDotFill = 11 - плотное заполнение точками. Например , чтобы заполнить вертикальной сеткой красного цвета прямоугольник, рассмотренный в предыдущем примере, необходимо использовать следующие предложения: SetFillStyle(7, 4); Bar(10,10, 319,174); Заполнение заданным шаблоном области, охватывающей точку с координатами (X, Y), ограниченной линией, номер цвета которой определен Border, выполняется процедурой FloodFill(X, Y: integer; Border: word). Шаблон и цвет заполнения области могут быть определены с помощью процедуры SetFillStyle . Например , чтобы заполнить наклонными линиями коричневого цвета круг желтого цвета с центром в точке (319, 174) и радиусом 100, необходимо использовать операторы: SetFillStyle(3, 6); SetColor(14); Circle(319, 174, 100); FloodFill (310, 170, 14); 14.2. Контроль за выполнением графических операций При выполнении графических процедур возможны следующие ошибочные ситуации: 1. Параметры процедуры не нарушают требований синтаксиса, но подобраны неправильно при этом выполнение процедуры не вызовет никаких изменений. 2. Параметры подобраны правильно, а процедура выполняется неправильно. 3. Определение причин неправильного выполнения графических операций остается за разработчиком программы. Эту задачу упрощает функция GraphResult, позволяющая определить результат завершения графической операции. Синтаксис: GraphResult : integer; Если операция закончилась успешно, функция возвращает 0, в противном случае отрицательное значение, идентифицирующее причину неудачи. Коды ошибок: grOk -0 -нормальное выполнение графической операции; 107 grNoInitGraph -1 -графический режим не установлен; grNotDetected -2 -нет графической карты; grFileNotFound -3 -файл драйвера устройства не найден; grInvalidDriver -4 -неподходящий файл драйвера устройства; grNoloadMem -5 -нет памяти для загрузки драйвера; grNoScanMem -6 -нет памяти для заполнения области методом сканирования; grNoFloodMem -7 -нет памяти для заполнения области методом заливки; grFontNotFound -8 -файл со шрифтами не найден; grNoFontMem -9 -нет памяти для загрузки шрифта; grInvalidMode -10 -неправильный графический режим; grError -11 -другие ошибки; grIOError -12 -ошибки операции ввода - вывода; grInvalidFont -13 -ошибочный стиль шрифта; grInvalidFontNum -14 -ошибочный номер стиля шрифта; grInvalidDeviceNum -15 -ошибочный номер устройства. Поскольку двукратный вызов функции GraphResult (без выполнения между вызовами графической операции) приводит к тому, что вторым результатом всегда будет 0, рекомендуется назначить первый результат промежуточной переменной. Для обработки "неуспешных" графических операций следует создавать процедуры анализа и выхода из ситуаций, вызвавших неуспех. Контрольные вопросы 1. Какой модуль обеспечивает графику на ЭВМ? 2. Как инициализировать графический режим, если неизвестно, какой графический драйвер используется на данной машине? 3. Всегда ли необходимо явно задавать все параметры процедуры InitGraph? 4. Что такое пиксел и каковы его характеристики? 5. С помощью каких функций можно узнать размеры экрана и количество цветов в цветовой гамме (палитре) данного графического режима? 6. Могут ли на экране высвечиваться одновременно отрезки прямых линий разных цветов? 7. Где будет графический курсор после выполнения одной из процедур PutPixel, Line, LineRel, LineTo и как это проверить практически? 8. Всегда ли высвечиваются рисуемые точки после определения графического окна? 9. Какими процедурами можно нарисовать окружность? 10. Как отсчитываются углы в тех процедурах, где они используются в качестве параметров? 11. Почему в процедурах Rectangle и Bar указываются координаты лишь двух вершин прямоугольника? 12. Какие из рассмотренных процедур рисуют линии, а какие - области? 13. Влияет ли процедура SetLineStyle на результаты работы процедур, которые рисуют области? 14. Влияет ли процедура SetFillStyle на результаты работы процедур, рисующих линии? 15. К каким результатам приводит обращение к процедуре FloodFill, когда первые два ее параметра задают точку, лежащую вне области, охватываемой линией? 16. Что произойдет, если в процедуре FloodFill линия , охватывающая заданную точку, окажется не замкнутой? 17. Можно ли результаты процедур Ваr, PieSlice получать с использованием других процедур? Задание к работе Построить круговую диаграмму, отображающую процентное соотношение отличников, хорошистов и прочих. Для заливки секторов использовать различные шаблоны и цвета. Построить столбиковую диаграмму, отображающую рост цен на бензин. Построить график функции, заданной в индивидуальном задании. 108 Методические указания 1. Разработать алгоритмы и программы для решения задач заданий. 2. Скомпилировать программы. 3. Составить контрольные тесты и протестировать программы. 4. Составить отчет и представить его к защите. Для выполнения первого задания необходимо придерживаться следующей схемы: а) подсчитать общее количество элементов, входящих в систему, например: К = КО + КХ + КП, где К - количество элементов в системе (количество всех студентов); КО - количество отличников; КХ - количество хорошистов; КП - количество прочих; б) вычислить процентное отношение группы элементов в системе, например, процентное отношение отличников в системе равно: %O KO *100% K = в) вычислить, сколько радиан составляет та или иная группа элементов, если вся система составляет 2 π радиан, например: Кол.рад.отл.= 2 * * %O 100% π г) используя графические процедуры и функции вывести на экране круговую диаграмму. Для выполнения второго задания необходимо: а) определить максимальное значение элементов, входящих в систему, в нашем примере - максимальную стоимость (Max) бензина за рассматриваемый период времени; б) рассчитать высоту HMax в пикселах самого высокого столбика Max, используя функцию GetMaxY; в) вычислить количество пикселей KPixH, приходящихся на единицу стоимости; г) вычислить высоту в пикселях каждого элемента системы; д) рассчитать ширину одного столбика, учитывая при этом межстолбиковое расстояние и используя функцию GetMaxX; е) используя графические процедуры и функции вывести столбиковую диаграмму на экран. Для выполнения третьего задания используйте пример программы, приведенный ниже. Пример . Построение графика функции Y = Sqr(X). При отображении графика функции на экране необходимо выполнить переход от локальной системы координат в систему координат экрана, а также во избежание помех рассчитать граничные значения X, при которых значения Y начинают выходить за пределы экрана. Программа: Program GraficFunction; Uses Graph; Var grDriver : Integer; grMode : Integer; ErrCode : Integer; X, Y, X1, Y1, CX, CY, XG: Integer; Begin {*** инициализация графического режима экрана ***} grDriver := Detect; 109 InitGraph(grDriver, grMode,''); ErrCode := GraphResult; If ErrCode=grOk then {инициализация графического экрана прошла успешно} begin {*** Построение осей координат ***} CX := Round(GetMaxX / 2); {для настройки на координаты любого} CY := Round(GetMaxY / 2); {экрана используем функции GetMaxX и GetMaxY} {(СХ, СУ) - центр сист. коорд-т} Line(0, CY, GetMaxX, CY); {вычерчивание оси ординат} Line(CX, 0, CX, GetMaxY); { - " - абцисс} {*** Построение графика функции Y = Sqr(X)***} XG:=Round(Sqrt(20*(GetMaxY-CY)));{определение ширины параболы} for X:= -XG to XG do begin X1 := X + CX; {определение текущей координаты Х экрана} Y := Sqr(X); {определение ординаты функции} Y1 := GetMaxY - Round(( Y / 20 + CY)); {преобразование текущей ординаты функции в текущую координату Y экрана} Circle(X1, Y1, 2) { точка, инцидентная параболе, вычерчивается в виде окружности радиусом в два пикселя} end; {*** Вывод на экран пояснительного сообщения ***} SetTextStyle(0, 0, 2); OutTextXY(180, 350, 'Гpафик функции Y = Sqr(X)'); ReadLn; CloseGraph; end else { возникла ошибка при инициации графического экрана} WriteLn('Graphics error:',GraphErrorMsg(ErrCode)); {вывод диагностического сообщения} End. Содержание отчета 1. Титульный лист. 2. Словесная постановка задачи. 3. Текстуальный или графический алгоритм работы программы. 4. Листинг программы. 5. Анализ допущенных ошибок. 6. Сведения об использованных цветах и шаблонах заполнения областей. 7. Ответы на контрольные вопросы по согласованию с преподавателем. Варианты заданий 1. Y = A · lg(X); 2. Y = A · sin(X); 3. Y = A · exp(X); 4. Y = A·X 2 + B·X + C; 5. Y = A · tg(X); 6. Y = A · arctg(X); 7. Y = A · X n + C, n=1; 8. Y = A · X n + C, n=2; 9. Y = A · X n + C, n=3; 10. Y = A · X n + C, n=4, где A, B, C - произвольные параметры. |