Скачиваний:
45
Добавлен:
04.11.2020
Размер:
57.83 Кб
Скачать

Министерство образования и науки Российской Федерации

Федеральное государственное бюджетное образовательное учреждение высшего профессионального образования

«Санкт-Петербургский Государственный Электротехнический Университет «ЛЭТИ» им. В.И. Ульянова (Ленина)»

Кафедра вычислительной техники

Лабораторная работа №3

по дисциплине «Организация ЭВМ и систем»

на тему «Исследование видеосистемы (графический режим)»

Студент гр. 5392

Нургазы Б.К

Студент гр. 5392

Юсупов Н.Г.

Преподаватель

Иванов Д.М.

Санкт-Петербург

2017

Цель работы

Изучение работы с видеосистемой в графическом режиме, вывод графика заданной функции с масштабированием и разметкой осей.

Задание

Разработать программу для вывода на экран графика заданной функции.

Номер

Функция

Диапазон аргумента

Начало

Конец

14

sin3(x)+cos3(x)

π/2

Произвести разметку осей и проставить истинные значения точек.

Найти максимальное значение функции на заданном интервале и вывести в отдельное окно на экране.

Краткие сведения о видеосистемах пэвм, графическом режиме их работы и функциях обслуживания графического режима.

Использование графики в языке С++ - это многошаговый процесс. Прежде всего необходимо определить тип видеоадаптера. Затем устанавливается подходящий режим его работы и выполняется инициализация графической системы в выбранном режиме. После этого становятся доступными для исполь­зования функции графической библиотеки <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;

}

Пример работы программы

Соседние файлы в папке Всякие лабы