Министерство образования и науки Российской Федерации
Федеральное государственное бюджетное образовательное учреждение высшего профессионального образования
«Санкт-Петербургский Государственный Электротехнический Университет «ЛЭТИ» им. В.И. Ульянова (Ленина)»
Кафедра вычислительной техники
Лабораторная работа №3
по дисциплине «Организация ЭВМ и систем»
на тему «Исследование видеосистемы (графический режим)»
Студент гр. 5392 |
|
Нургазы Б.К |
Студент гр. 5392 |
|
Юсупов Н.Г. |
Преподаватель |
|
Иванов Д.М. |
Санкт-Петербург
2017
Цель работы
Изучение работы с видеосистемой в графическом режиме, вывод графика заданной функции с масштабированием и разметкой осей.
Задание
Разработать программу для вывода на экран графика заданной функции.
Номер |
Функция |
Диапазон аргумента |
|
Начало |
Конец |
14 |
sin3(x)+cos3(x) |
π/2 |
6π |
Произвести разметку осей и проставить истинные значения точек.
Найти максимальное значение функции на заданном интервале и вывести в отдельное окно на экране.
Краткие сведения о видеосистемах пэвм, графическом режиме их работы и функциях обслуживания графического режима.
Использование графики в языке С++ - это многошаговый процесс. Прежде всего необходимо определить тип видеоадаптера. Затем устанавливается подходящий режим его работы и выполняется инициализация графической системы в выбранном режиме. После этого становятся доступными для использования функции графической библиотеки <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 <graphics.h>
#include <stdio.h>
#include <math.h>
#include <conio.h>
const int xStart = 10;
struct point
{
int X;
int Y;
};
point getCoords(float x, float y, float xValue, float yValue)
{
int maxX = getmaxx();
int maxY = getmaxy();
int avrgX = maxX/2;
int avrgY = maxY/2;
point result;
int currX = xStart;
float realValue = 0;
if(x < 0)
for(; realValue > x; realValue -= xValue, --currX);
else
for(; realValue < x; realValue += xValue, ++currX);
result.X = currX;
realValue = 0;
int currY = avrgY;
if(y < 0)
for(; realValue > y; realValue -= yValue, ++currY);
else
for(; realValue < y; realValue += yValue, --currY);
result.Y = currY;
return result;
}
const float start = 3.14 / 2;
const float end = 3.14 * 6;
const int numberOfSteps = 200;
float max(float *arr, int size)
{
float result = arr[0];
for(int i = 1; i < size; ++i)
if(arr[i]>result)
result = arr[i];
return result;
}
float min(float *arr, int size)
{
float result = arr[0];
for(int i = 0; i < size; ++i)
if(arr[i] < result)
result = arr[i];
return result;
}
float myFunction(float x)
{
return pow(sin(x),3)-pow(cos(x),3);
}
void putAxis(float xValue, float yValue)
{
int maxX = getmaxx();
int maxY = getmaxy();
int avrgX = maxX/2;
int avrgY = maxY/2;
line(0,avrgY, maxX, avrgY);
//line(avrgX, 0, avrgX, maxY);
line(xStart, 0, xStart, maxY);
for(int k = 1; k < 7; ++k)
{
point p1 = getCoords(3.14*k, 0, xValue, yValue);
line(p1.X, p1.Y-5, p1.X, p1.Y+5);
char c[] = {k + '0', 'p', 'i', '\0'};
outtextxy(p1.X - 10, p1.Y + 20, c);
}
for(k = 1; k <= 11; k += 2)
{
point p = getCoords(3.15*k/2, 0, xValue, yValue);
line(p.X, p.Y -5, p.X, p.Y + 5);
char c[] = " pi/2";
c[1] = k%10 + '0';
if(k >= 10)
c[0] = k / 10+'0';
outtextxy(p.X - 15, p.Y + 15, c);
}
for(k = 1; k < 10; ++k)
{
point p1 = getCoords(0, float(k) / 10, xValue, yValue);
point p2 = getCoords(0, -float(k) / 10, xValue, yValue);
line(p1.X-5, p1.Y, p1.X +5, p1.Y);
line(p2.X-5, p2.Y, p2.X + 5, p2.Y);
char c1[] = "0. ";
char c2[] = "-0. ";
c1[2] = c2[3] = k+'0';
outtextxy(p1.X + 10, p1.Y, c1);
outtextxy(p2.X + 10, p2.Y, c2);
}
}
void drawGraph(float *X, float *Y, float xValue, float yValue)
{
for(int i = 0; i < numberOfSteps -1 ; ++i)
{
point p1 = getCoords(X[i], Y[i], xValue, yValue);
point p2 = getCoords(X[i+1], Y[i+1], xValue, yValue);
line(p1.X, p1.Y, p2.X, p2.Y);
}
point p = getCoords(3.14/2, 0.5, xValue, yValue);
char c[] = "Max = 1";
outtextxy(p.X, p.Y, c);
}
int main()
{
clrscr();
int grMode, grDriver;
grDriver = DETECT;
grMode = 0;
initgraph(&grDriver, &grMode, "C:\\TurboC3\\BGI");
float *X = new float[numberOfSteps];
float step = (end - start)/numberOfSteps;
float *Y = new float[numberOfSteps];
X[0] = 3.14/2;
Y[0] = myFunction(3.14/2);
for(int i = 1; i < numberOfSteps; ++i)
{
X[i] = X[i-1]+step;
Y[i] = myFunction(X[i]);
}
float xValue = end/getmaxx();
float yValue = (max(Y, numberOfSteps)-min(Y, numberOfSteps))/getmaxy();
putAxis(xValue, yValue);
drawGraph(X, Y, xValue, yValue);
getch();
delete[] X;
delete[] Y;
closegraph();
return 0;
}
Пример работы программы