Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Курсач / курсовая (отчёт)

.docx
Скачиваний:
69
Добавлен:
09.12.2013
Размер:
373.49 Кб
Скачать

20

Цель работы: Необходимо разработать программу на языке С++, основываясь на функционале библиотеки GRX, в соответствии с заданием варианта.

Задание: Реализовать прототип графического редактора, обладающего следующими характеристиками. Предполагается создание и редактирование, в частности, вращение следующих графических объектов: линия, прямоугольник, эллипс. При нажатии клавиши L создается линия, при нажатии клавиши R создается прямоугольник, при нажатии клавиши E создается эллипс. Клавиша Tab выбирает очередной графический объект. Выбор приводит к изменению цвета графического объекта. Клавиши со стрелками перемещают выбранный графический объект. Клавиши Page Up, Page Down, Home, End изменяют размеры выбранного графического объекта. Клавиши F1 и F2 обеспечивают вращение графического объекта относительно его центра. Клавиша Delete удаляет выбранный графический объект. Выход из программы осуществляется по нажатию клавиши Esc.

Разработка программы

Данная программа разработана в среде программирования Code::Blocks (v.10.05) с использованием встраиваемой библиотеки GRX Graphics Library (v. 2.0), необходимой для включения графического режима.

Для разработки программы требовалось обеспечить создание различных типов объектов со сходными, применяемыми к ним, действиями. Было приято решение создать базовый класс ключевой фигуры и с помощью наследования описать оставшиеся. Базовым классом была выбрана "Точка" (TPoint), т.к. является наиболее простым в создании объектом и не имеет дополнительных параметров, учитываемых при построении:

struct TPoint {

int x;

int y;

int color;

bool IsSelected;

TPoint(int ix, int iy, int icolor);

virtual ~TPoint();

virtual void Draw(int color);

void Select(bool selected);

virtual void Hide();

void Move(int dx, int dy);

virtual void TurnL();

virtual void TurnR();

virtual void WU();

virtual void WD();

virtual void HU();

virtual void HD();

};

И описаны все вызываемые данным классом функции.

Потом были созданы классы "Линия" (TLine), "Прямоугольник" (TBox), "Элипс" (TEllips) используя метод наследования. Т.е. новый объект "унаследовал" элементы существующего класса (называемого базовым классом), добавив в них свои параметры, характерные исключительно для него.

Древо иерархии объектов:

В них были расписаны такие дополнительные параметры, как новые переменные, необходимые для построения, поворот объекта TurnL/TurnR (на косинус или синус, в зависимости от направления, дискретного шага обозначенного), изменение длины объекта HU/HD (на дискретный шаг), изменение ширины объекта WU/WD (на дискретный шаг). Данные части программы можно подробно посмотреть ниже, где приведён полный вариант кода.

Для упрощения работы с цветом была введена функция RGB позволяющая задавать цвета в привычном трёхканальном (красный-зелёный-синий) режиме:

int RGB (int r, int g, int b)

{

return (((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff));

}

Далее был реализован вызов консоли с заданными параметрами (разрешение 1024*900 с заливкой фона чёрным цветом), функция, позволяющая исключить появление "не случайных" случайных чисел (в противном случае все случайные параметры повторялись бы при каждом новом запуске программы) и реализован массив, в котором будут хранится данные о созданных фигурах:

GrSetMode(GR_width_height_color_graphics,1024,900,0x1000000);

srand(time(0));

TPoint* p[N];

int i, n = 0;

После этого с помощью циклов с условием (If <...> {...} else {...};) были созданы условия для ввода новых фигур, а именно:

  • по нажатию на "P" (с зажатым "Ctrl") появляется в произвольном месте "точка";

  • по нажатию на "L" (с зажатым "Ctrl") появляется в произвольном месте вертикальная "линия" с произвольной длиной;

  • по нажатию на "R" (с зажатым "Ctrl") появляется в произвольном месте "прямоугольник" с произвольными длинами сторон;

  • по нажатию на "E" (с зажатым "Ctrl") появляется в произвольном месте "эллипс" с произвольными высотой и шириной.

Для выполнения операций над созданными фигурами, подобными циклами были созданы команды, обращающиеся к функциям описанным в разделе классов - поворот объекта TurnL/TurnR, изменение длины объекта HU/HD, изменение ширины объекта WU/WD:

  • Повороту влево (против часовой стрелки) соответствует клавиша F2;

  • Повороту вправо (по часовой стрелке) соответствует клавиша F1;

  • увеличению ширины (на дискретный шаг) соответствует клавиша Page Up;

  • уменьшению ширины (на дискретный шаг) соответствует клавиша Page Down;

  • увеличению высоты (на дискретный шаг) соответствует клавиша Home;

  • уменьшению высоты (на дискретный шаг) соответствует клавиша End.

А также переключение между созданными фигурами и выбор одной из них с помощью клавиши Tab (выбирается следующая по очереди создания фигура. Если таковой нет, то выбирается первая по очереди создания) и перемещение выбранной фигуры с помощью курсорных стрелок (было выбрано расстояние в 10 пикселей для более точного размещения фигур на экране):

if (key == GrKey_Up) p[cur]->Move(0, -10);

if (key == GrKey_Down) p[cur]->Move(0, 10);

if (key == GrKey_Left) p[cur]->Move(-10, 0);

if (key == GrKey_Right) p[cur]->Move(10, 0);

if (key == GrKey_Tab) {

p[cur]->Select(false);

cur = cur + 1;

if (cur > n - 1) cur = 0;

p[cur]->Select(true);

}

Кроме того, было предусмотрено удаление выбранной фигуры при нажатии клавиши Delete. В подобном случае данные о фигуре удаляются из памяти, а выбор фигуры переключается на следующую по очереди создания. Если таковой нет, то на первую созданную.

Для оптимизации использования памяти была использована функция очистки (delete), удаляющая по нажатию на клавишу Esc данные о созданных фигурах из памяти компьютера и последующим выключением программы.

Далее представлена блок-схема основной части программы. Она наглядно раскрывает алгоритм работы программы. В данной схеме, ради упрощения восприятия, были опущены части, где идёт работа с созданием и редактированием фигур, т.к. они могут быть заменены на аналогичные, но организованные по другому, т.е. не влияют на понимание устройства программы. Отсутствующие фрагменты можно подробно посмотреть ниже, где приведён полный вариант кода.

Блок-схема основной части программы:

Происходит выбор создаваемой фигуры. Ожидается одна из комбинаций: Ctrl+P, Ctrl+L, Ctrl+R, Ctrl+E. Есть возможность завершения программы без ввода фигур

Нет

Происходит выбор действия для активной фигуры. Ожидаются клавиши: F1, F2, PageUp, PageDown, Home, End, Left, Right, Up, Down, Delete. Есть возможность завершения программы или перехода к созданию новой фигуры без изменения активной

Нет

Ожидание клавиши Esc. Есть возможность, в случае не нажатия, продолжить работу с программой.

Нет

Исходный код программы:

#include <grx20.h>

#include <grxkeys.h>

#include <time.h>

#include <stdlib.h>

#include <math.h>

#define BACK_COLOR 0

int RGB (int r, int g, int b)

{

return (((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff));

}

struct TPoint {

int x;

int y;

int color;

bool IsSelected;

TPoint(int ix, int iy, int icolor);

virtual ~TPoint();

virtual void Draw(int color);

void Select(bool selected);

virtual void Hide();

void Move(int dx, int dy);

virtual void TurnL();

virtual void TurnR();

virtual void WU();

virtual void WD();

virtual void HU();

virtual void HD();

};

TPoint::TPoint(int ix, int iy, int icolor)

{

x = ix;

y = iy;

color = icolor;

}

void TPoint::Hide()

{

GrFilledCircle(x, y, 3, BACK_COLOR);

}

TPoint::~TPoint()

{

Hide();

}

void TPoint::Draw(int icolor)

{

GrFilledCircle(x, y, 3, icolor);

if (IsSelected){

GrFilledCircle(x, y, 3, RGB(255,0,0));

}

}

void TPoint::Select(bool selected)

{

Draw(BACK_COLOR);

IsSelected = selected;

Draw(color);

}

void TPoint::Move(int dx, int dy)

{

Hide();

x += dx;

y += dy;

Draw(color);

}

void TPoint::TurnL()

{

Draw(color);

}

void TPoint::TurnR()

{

Draw(color);

}

void TPoint::WU()

{

Draw(color);

}

void TPoint::WD()

{

Draw(color);

}

void TPoint::HD()

{

Draw(color);

}void TPoint::HU()

{

Draw(color);

}

struct TLine:public TPoint {

int l;

float b;

TLine(int ix, int iy, int icolor, int il, float ib);

virtual ~TLine();

virtual void Draw(int color);

virtual void Hide();

virtual void TurnL();

virtual void TurnR();

virtual void HU();

virtual void HD();

};

TLine::TLine(int ix, int iy, int icolor, int il, float ib):

TPoint(ix, iy, icolor)

{

l = il;

b = ib;

}

void TLine::Hide()

{

{

GrFilledBox(x-10*floor(cos(b)),y-10*floor(sin(b)),x+floor(l*(sin(b)))+10*floor(cos(b)),y-10*floor(sin(b))-floor(l*(cos(b))), BACK_COLOR);

}

}

TLine::~TLine()

{

Hide();

}

void TLine::Draw(int icolor)

{

GrLine(x, y, floor(x+l*(sin(b))), floor(y-l*(cos(b))), icolor);

if (IsSelected){

GrLine(x, y, floor(x+l*(sin(b))), floor(y-l*(cos(b))), RGB(255,0,0));

}

}

void TLine::TurnL()

{

Hide();

b -= 0.1;

Draw(color);

}

void TLine::TurnR()

{

Hide();

b += 0.1;

Draw(color);

}

void TLine::HU()

{

Hide();

l += 10;

Draw(color);

}

void TLine::HD()

{

Hide();

l -= 10;

Draw(color);

}

struct TBox:public TPoint {

int w;

int h;

float b;

TBox(int ix, int iy, int icolor, int iw, int ih, float ib);

virtual ~TBox();

virtual void Draw(int color);

virtual void TurnL();

virtual void TurnR();

virtual void WU();

virtual void WD();

virtual void HU();

virtual void HD();

};

TBox::TBox(int ix, int iy, int icolor, int iw, int ih, float ib):

TPoint(ix, iy, icolor)

{

w = iw;

h = ih;

b = ib;

}

TBox::~TBox()

{

Hide();

}

void TBox::Draw(int icolor)

{

GrLine(x, y, floor(x+w*(cos(b))), floor(y+w*(sin(b))), icolor);

GrLine(x, y, floor(x+h*(sin(b))), floor(y-h*(cos(b))), icolor);

GrLine(floor(x+w*(cos(b))+h*(sin(b))), floor(y+w*(sin(b))-h*(cos(b))), floor(x+h*(sin(b))), floor(y-h*(cos(b))), icolor);

GrLine(floor(x+w*(cos(b))+h*(sin(b))), floor(y+w*(sin(b))-h*(cos(b))), floor(x+w*(cos(b))), floor(y+w*(sin(b))), icolor);

if (IsSelected){

GrLine(x, y, floor(x+w*(cos(b))), floor(y+w*(sin(b))), RGB(255,0,0));

GrLine(x, y, floor(x+h*(sin(b))), floor(y-h*(cos(b))), RGB(255,0,0));

GrLine(floor(x+w*(cos(b))+h*(sin(b))), floor(y+w*(sin(b))-h*(cos(b))), floor(x+h*(sin(b))), floor(y-h*(cos(b))), RGB(255,0,0));

GrLine(floor(x+w*(cos(b))+h*(sin(b))), floor(y+w*(sin(b))-h*(cos(b))), floor(x+w*(cos(b))), floor(y+w*(sin(b))), RGB(255,0,0));

}

}

void TBox::TurnL()

{

Hide();

b -= 0.1;

Draw(color);

}

void TBox::TurnR()

{

Hide();

b += 0.1;

Draw(color);

}

void TBox::WU()

{

Hide();

w += 10;

Draw(color);

}

void TBox::WD()

{

Hide();

w -= 10;

Draw(color);

}

void TBox::HU()

{

Hide();

h += 10;

Draw(color);

}

void TBox::HD()

{

Hide();

h -= 10;

Draw(color);

}

struct TEllips:public TPoint {

int a;

int r;

float b;

TEllips(int ix, int iy, int icolor, int ir, int ia, float ib);

virtual ~TEllips();

virtual void Draw(int color);

virtual void TurnL();

virtual void TurnR();

virtual void WU();

virtual void WD();

virtual void HU();

virtual void HD();

};

TEllips::TEllips(int ix, int iy, int icolor, int ir, int ia, float ib):

TPoint(ix, iy, icolor)

{

r = ir;

a = ia;

b = ib;

}

void TEllips::Draw(int icolor)

{

int i;

if (IsSelected){for (i=0;i<=361;i++){

GrPlot(floor(x+sin(i+b)*((a*r)/sqrt(r*r*cos(i)*cos(i)+a*a*sin(i)*sin(i)))), floor(y-cos(i+b)*((a*r)/sqrt(r*r*cos(i)*cos(i)+a*a*sin(i)*sin(i)))), RGB(255,0,0));

}} else

for (i=0;i<=361;i++){

GrPlot(floor(x+sin(i+b)*((a*r)/sqrt(r*r*cos(i)*cos(i)+a*a*sin(i)*sin(i)))), floor(y-cos(i+b)*((a*r)/sqrt(r*r*cos(i)*cos(i)+a*a*sin(i)*sin(i)))), icolor);

}

}

TEllips::~TEllips()

{

Hide();

}

void TEllips::TurnL()

{

Hide();

b -= 0.1;

Draw(color);

}

void TEllips::TurnR()

{

Hide();

b += 0.1;

Draw(color);

}

void TEllips::WU()

{

Hide();

r += 10;

Draw(color);

}

void TEllips::WD()

{

Hide();

r -= 10;

Draw(color);

}

void TEllips::HU()

{

Hide();

a += 10;

Draw(color);

}

void TEllips::HD()

{

Hide();

a -= 10;

Draw(color);

}

#define N 100

int main()

{

GrSetMode(GR_width_height_color_graphics,1024,900,0x1000000);

srand(time(0));

TPoint* p[N];

int i, n = 0, cur = 0;

GrKeyType key;

do{

key = GrKeyRead();

if (key == GrKey_Control_P)

//создание точки

{

if (n < N - 1) {

p[n] = new TPoint(rand()%GrMaxX(), rand()%GrMaxY(), RGB(0, 255, 0));

p[n]->Draw(p[n]->color);

n++;

p[cur]->Select(false);

cur = n - 1;

p[cur]->Select(true);

}

}

if (key == GrKey_F2) {

// поворот влево

p[cur]-> TurnL();

}

if (key == GrKey_F1) {

//поворот вправо

p[cur]-> TurnR();

}

if (key == GrKey_PageUp) {

// Увеличение ширины

p[cur]-> WU();

}

if (key == GrKey_PageDown) {

// Уменьшение ширины

p[cur]-> WD();

}

if (key == GrKey_Home) {

// Увеличение высоты

p[cur]-> HU();

}

if (key == GrKey_End) {

// Уменьшение высоты

p[cur]-> HD();

}

if (key == GrKey_Control_L)

//создание линии

{

if (n < N - 1) {

p[n] = new TLine(rand()%(GrMaxX()-60), rand()%(GrMaxY()-60), RGB(0, 255, 0), rand()%50+10, 0);

p[n]->Draw(p[n]->color);

n++;

p[cur]->Select(false);

cur = n - 1;

p[cur]->Select(true);

}

}

if (key == GrKey_Control_E

// создание элипса

{

if (n < N - 1) {

p[n] = new TEllips(rand()%(GrMaxX()-60), rand()%(GrMaxY()-60), RGB(0, 255, 0), rand()%50+10, rand()%50+10, 0);

p[n]->Draw(p[n]->color);

n++;

p[cur]->Select(false);

cur = n - 1;

p[cur]->Select(true);

}

}

if (key == GrKey_Control_R

// создание прямоугольника

{

if (n < N - 1) {

p[n] = new TBox(rand()%GrMaxX()-70, rand()%GrMaxY()-70, RGB(0, 255, 0), rand()%50+10, rand()%50+10, 0);

p[n]->Draw(p[n]->color);

n++;

p[cur]->Select(false);

cur = n - 1;

p[cur]->Select(true);

}

}

if (key == GrKey_Delete

// удаление активной фигуры

{

if (n > 1) {

delete p[cur];

for (i = cur; i < n-1; i++) {

p[i] = p[i+1];

}

n--;

if (cur > n - 1) cur = n - 1;

p[cur]->Select(true);

}

}

if (key == GrKey_Up) p[cur]->Move(0, -10); //перемещение активной фигуры вверх

if (key == GrKey_Down) p[cur]->Move(0, 10); //перемещение активной фигуры вниз

if (key == GrKey_Left) p[cur]->Move(-10, 0); //перемещение активной фигуры влево

if (key == GrKey_Right) p[cur]->Move(10, 0); //перемещение активной фигуры вправо

if (key == GrKey_Tab)

//переключение между созданными фигурами

{

p[cur]->Select(false);

cur = cur + 1;

if (cur > n - 1) cur = 0;

p[cur]->Select(true);

}

GrFilledBox(0,0,GrMaxX(),GrMaxY(),BACK_COLOR);

for (i = 0; i < n; i++) {

p[i]->Draw(p[i]->color);

}

}

while(key != GrKey_Escape);

for (i = 0; i < n; i++) {

delete p[i]; //очистка памяти

}

}

Описание разработанной программы

В результате выполнения задания была разработана программа, описание которой включает в себя: иерархию объектов, используемых в программе; схему основной части программы; исходный текст программы; Программа функционирует и выполняет все поставленные условия задания.

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

Соседние файлы в папке Курсач