ОргЭВМ(лабы 1-5) / отчетЛаб3
.docxМИНОБРНАУКИ РОССИИ
–––––––——————————–––––––
Санкт-Петербургский государственный электротехнический университет «ЛЭТИ»
————————————————————
Кафедра ИС
отчет
по лабораторной работе №3
по дисциплине «Организация ЭВМ и систем»
Тема: Исследование видеосистемы (графический режим)
|
Выполнили Ильичева К. Середа И. Факультет: КТИ Группа № 4373 Принял Иванов Д.
Санкт-Петербург |
||||||||||
|
2016 г.
Цель работы: изучение работы с видеосистемой в графическом режиме, вывод графика заданной функции с масштабированием и разметкой осей. Порядок выполнения работы: 1. Разработать программу для вывода на экран графика заданной функции. Вариант задания:
2. Произвести разметку осей и проставить истинные значения точек. 3. Найти максимальное значение функции на заданном интервале и вывести в отдельное окно на экране.
|
||||||||||
Теоретические сведения
Использование графики в языке С++ - это многошаговый процесс. Прежде всего необходимо определить тип видеоадаптера. Затем устанавливается подходящий режим его работы и выполняется инициализация графической системы в выбранном режиме. После этого становятся доступными для использования функции графической библиотеки <graphics.h> для построения основных графических примитивов: отрезков прямых линий, окружностей, эллипсов, прямоугольников, секторов, дуг и т.д., появляется возможность вывода текста с использованием различных шрифтов.
Реализация:
Начнем рассмотрение с подключения графического режима:
int driver, mode; // драйвер и режим
driver = DETECT; // автоопределение
initgraph(&driver,&mode,"c:\\borlandc\\bgi");
Инициализацию графической модели выполняет функция initgraph():
void far initgraph(int *graphdriver, int *graphmode, char * pathtodriver).
При вызове она инициализирует графическую систему, загружая. BGI-драйвер, определяемый указателем graphdriver, и устанавливая видеоадаптер в графический режим, задаваемый указателем graphmode. Третий аргумент функции initgraph() задает маршрут поиска файла, содержащего .BGI-драйвер. Если файл не найден в заданной директории, функция просматривает текущий директорий. В нашем случае маршрут задан следующим образом: "c:\\borlandc\\bgi"
С++ поддерживает фиксированное число драйверов, каждый из которых, в свою очередь, поддерживает ряд режимов. Как тип драйвера, так и режим могут быть заданы числом или символической константой.
Далее перейдем непосредственно к выводу графика заданной функции:
Две функции позволяют определить ширину и высоту экрана в пикселах для текущего видеорежима: getmaxx() и getmaxy().
Задание стиля линии выполняет функция setlinestyle().
void setlinestyle (int linestyle, unsigned upattern, int thickness)
Устанавливает стиль "рисования" отрезков прямых линий и графических примитивов. Аргумент linestyle выбирает стиль линии, а аргумент thickness - толщину линии.
Аргумент upattern используется только в том случае, когда задается отличный от предопределенных стиль линии, т.е. если linestyle равен USERBIT_LINE (4).
Что же касается функции rectangle(), то ее прототип выглядит следующим образом:
void rectangle( int left, int top, int right, int bottom)
Выводит контур прямоугольника, заданного координатами левого верхнего (left, top) и правого нижнего (right, bottom) углов. Координаты углов задаются относительно координат левого верхнего угла текущего графического окна. Контур выводится линией текущего цвета и стиля. Цвет контура устанавливается функцией setcolor(). Стиль линии задается функцией setlinestyle().
Заполнение цветом прямоугольной области выполняется с помощью функций setfillstyle и floodfill. Начнем с setfillstyle():
void setfillstyle(int pattern, int color)
Выбирает один из предопределенных стилей заполнения. Значение pattern идентифицирует стиль. Аргумент color задает цвет, используемый для пикселов по заданному шаблону. Задав стиль, перейдем к самому заполнению, выполняемому функцией floodfill():
void floodfill (int x, int y, int border)
Заполняет текущим стилем область экрана, ограниченную непрерывной линией с цветом border, начиная с точки с координатами (х, у). Функция заполняет область либо внутри замкнутой линии, либо вне ее. Это зависит от положения начальной точки: если она лежит внутри области, заполняется внутренняя область; если точка лежит вне замкнутой области, заполняется внешняя область; если точка лежит точно на линии цвета border, заполнение не производится. Заполнение начинается с начальной точки и продолжается во всех направлениях, пока не встретится пиксел с цветом border. Цвет border должен отличаться от цвета заполнения, в противном случае будет заполнен весь экран.
Построение графика функции выполняется с помощью функции drawf():
На вход подаем количество точек по оси X, для которых будет рассчитано значение функции.
Переменная dx отвечает за шаг аргумента x, шаг рассчитывается в соответствии с диапазоном аргумента, представленном в задании. Далее создан цикл, осуществляющий поиск максимума значения функции на представленном диапазоне аргумента x. После того, как максимум найден запускаем цикл отрисовки заданной функции: рассчитываем значение в каждой точке диапазона, и устанавливаем найденную точку на экран с помощью функции putpixel():
void putpixel(int x, int у, int pixelcolor)
Определяет, лежит ли пиксел с координатами (х, у) в текущем графическом окне, и, если лежит, выводит на экран пиксел, код цвета которого равен pixelcolor. В противном случае цвет пиксела не изменяется. Используя функцию putpixel(), можно "стереть" пиксел, если вывести его с кодом цвета фона. Для того, чтобы пиксел лежал в созданном окне необходимо нормировать координату значения функции, привести ее к целочисленному значению, а потом привести эту координату к соответствующим параметрами окна.
Нарисовав график функции, перейдем к отрисовке координатных осей:
За стиль координатных осей отвечает функция setlinestyle(), описанная выше. Чтобы нарисовать оси, необходимо воспользоваться функцией line():
void line( int x1, int y1, int x2, int y2)
Выводит отрезок прямой линии между двумя явно специфицированными точками (x1, y1) и (х2, у2), используя текущие цвет, стиль, толщину и режим вывода линии. Координаты (x1, y1) и (х2, у2) задаются относительно левого верхнего угла текущего графического окна. Функция не изменяет текущую позицию.
Подпись осей выполняется функцией outtextxy():
void outtextxy (int x, int y, char *textstring)
Выводит ASCII-строку текста, на начало которой указывает textstring, используя текущие цвет, установки направления, типа шрифта и выравнивания строки. Аргументы х и у явно специфицируют новую текущую позицию, используемую для вывода строки. Координаты X и Y измеряются относительно координат левого верхнего угла текущего графического окна.
Для разметки осей создает циклы, следующего вида:
for(i=0;i<29;++i)
line(X0+20*i,Y0-220,X0+20*i,Y0-225);
В таких циклах отрисовываем штрихи, находящиеся друг от друга на определенном расстоянии, как это реализовано на обычной линейке. Подписываем штрихи с помощью outtextxy().
После построения графика и координатных осей, осталось вывести
максимальное значение функции на заданном диапазоне значений аргумента.
Максимальное значение находили в функции drawf() описанной выше. Это значение было найдено в формате float, для того чтобы вывести его была создана следующая конструкция:
Вначале используем функцию sprintf(), чтобы записать максимальное значение в массив символов:
int sprintf(char *buf, const char *format, arg-list)
Функция sprintf() идентична printf(), за исключением того, что вывод производится в массив, указанный аргументом buf.
Далее создав еще один массив (который будет содержать текст надписи, выводимой впоследствии на экран), добавим в него текст с помощью функции strcpy():
char *strcpy(char *str1, const char *str2)
Функция strcpy() используется для копирования содержимого str2 в str1. Аргумент str2 должен быть указателем на строку, оканчивающуюся нулем. Функция strcpy() возвращает указатель на str1. Если строки str1 и str2 перекрываются, то поведение функции strcpy() не определено.
Теперь “соединим” массивы с значением максимума функции и с надписью о том, что это максимальное значение. Эту операцию выполнит функция strcat():
char *strcat(char *str1, const char *str2)
Функция strcat() конкатенирует (соединяет в цепочку) строку str1 и копию строки str2. В конце модифицированной строки str1 функция устанавливает нулевой символ. Нулевой символ, первоначально завершавший строку str1, замещается первым символом строки str2. Строка str2 остается в первоначальном виде.
Для того, чтобы эти функции работали подключаем библиотеки string.h и stdio.h. Вывод максимального значения непосредственно на экран осуществляет уже известная ранее функция outtextxy().
Т.к. функции графической библиотеки больше не нужны, следует вызвать функцию closegraph() "закрытия" графического режима и возвращения к текстовому режиму.
Эта функция освобождает память, распределенную под драйверы графики, файлы шрифтов и промежуточные данные и восстанавливает режим работы адаптера в то состояние, в котором он находился до выполнения инициализации системы.
Пример работы программы:

Код программы:
#include "stdio.h"
#include "conio.h"
#include "math.h"
#include "dos.h"
#include "graphics.h"
#include "string.h"
int Xmax, Ymax, X0, X1, Y0, Y1;
float R, Rmax=0.;
void drawf(int N)
{ double x, dx=(16*3.14-3*3.14/2)/N;
int i;
for (i=0, x=(3*3.14/2); i<N; i++, x+=dx)
{
R=(float)(pow((cos(x/4)),2.0)+sqrt(x));
if(Rmax<R) Rmax=R;
}
for (i=0, x=(3*3.14/2); i<N; i++, x+=dx)
{
R=(float)(pow((cos(x/4)),2.0)+sqrt(x));
putpixel(i+X0,(Y0-(int)(R/Rmax*(float)(Y0-Y1)))/2-5,GREEN);
}
}
void main()
{ int i, N;
clrscr();
int driver, mode; // драйвер и режим
driver = DETECT; // автоопределение
initgraph(&driver,&mode,"c:\\borlandc\\bgi");
Xmax=getmaxx(); Ymax=getmaxy(); // Установили размеры экрана
X0=40; Y0=Ymax-30; // Левый нижний угол графика
X1=Xmax-30; Y1=30; // Правый верхний угол графика
N = X1-X0; // Количество точек по оси X
setlinestyle(0,1,3); // Установили параметры линий
setcolor(BLUE);
rectangle(2,0,Xmax-2,Ymax-15); // Вывели рамку
setfillstyle(SOLID_FILL, BLACK);
floodfill(20,20, BLUE);
drawf(N); // Рисуем график функции
setlinestyle(0,1,1); // Рисуем координатные оси
line(X0+20, Y0-5, X0+20, Y1-20);
line(X0-2, Y0-220, X1+15, Y0-220);
outtextxy(X0+40,Y1+40,"cos^2(x/4)+sqrt(x)"); // Подписываем оси
outtextxy(X1+3,Y0-219,"x");
for(i=1;i<23;++i) //Разметка осей координат
line(X0+20,Y0-i*20,X0+25,Y0-i*20);
for(i=0;i<29;++i)
line(X0+20*i,Y0-220,X0+20*i,Y0-225);
outtextxy(X0+23,Y0-218,"0");
outtextxy(X0+20*5,Y0-218,"4");
outtextxy(X0+20*9,Y0-218,"6");
outtextxy(X0+20*13,Y0-218,"8");
outtextxy(X0+20*17,Y0-218,"10");
outtextxy(X0+20*21,Y0-218,"12");
outtextxy(X0+20*25,Y0-218,"14");
char cRmax[10]; //Вывод максимального значения функции
sprintf(cRmax,"%f",Rmax);
char str[24];
strcpy(str,"MAX(f(x)) = ");
strcat(str,cRmax);
setcolor(BLACK);
rectangle(X0+25,Y0-5,X0+200,Y0+10); //Создание окна для максимального значения ф-ии
setfillstyle(SOLID_FILL, LIGHTCYAN);
floodfill(X0+30,Y0, BLACK);
setcolor(WHITE);
outtextxy(X0+30,Y0,str);
getch();
closegraph();
}
