Программа 48. многоугольники

В программе разработан класс Plgn для моделирования многоугольников на плоскости. В конструкторе этого класса динамически выделяется память под координаты вершин, а в деструкторе освобождается память, выделенная в конструкторе. В классе предусмотрены функции – члены для изображения многоугольника на экране, для его стирания с экрана, а также для перемещения и вращения многоугольника.

При решении задачи надо решить вопрос о совмещении математической плоскости, с помощью которой мы будем моделировать многоугольник, с физической плоскостью экрана. На рис.39 показана схема экрана и действующая на нем физическая экранная система координат xs, ys. Совместим начало математической системы координат x, y с центром экрана (x0, y0). Будем считать, что математическая плоскость отображается на плоскость экрана в масштабе 1:1, то есть математическая единица длины соответствует расстоянию между соседними пикселями на экране. Приведенные соображения реализованы в программе. В функциях рисования нужны физические координаты пикселей. Переход от математических координат к физическим производится по формулам:

xs = x0 + x, ys = y0 – y.

Знак минус учитывает разное направление вертикальных осей в физической и математической системах координат.

программа 48. многоугольники - student2.ru

Рис.39. Плоскость экрана и математическая система координат

// Файл Polygon.cpp

class Plgn // Класс многоугольников

{

int n; // Число вершин

float *x; // Указатель на массив абсцисс

float *y; // Указатель на массив ординат

static int x0, y0; // Координаты центра экрана

public:

Plgn(int n = 3); // Конструктор с аргументом по умолчанию

~Plgn(); // Деструктор

void Show(); // Функция рисования многоугольника

void Hide(); // Функция, убирающая изображение

void Move(int dx, int dy); // Смещение многоугольника на dx, dy

void Rotate(float angle); // Поворот на угол angle градусов

void Movement(); // Движение, пока не нажата Esc

static void SetBegCoord(int xn, int yn) // Установка координат центра

{ x0 = xn; y0 = yn; }

};

# include <iostream.h>

# include <graphics.h> // Графика

# include <stdlib.h> // Доступ к random

# include <conio.h>

# include <math.h>

Plgn::Plgn(int nn) // Конструктор

{

n = nn;

x = new float [n]; // Выделение памяти под массив абсцисс

y = new float [n]; // Выделение памяти под массив ординат

for(int i = 0; i < n; i++){ // Заполнение массивов координат

x[i] = x0 - random(x0 * 2); // случайными числами

y[i] = y0 - random(y0 * 2);

}

}

Для простоты координаты вершин многоугольника задаются в конструкторе случайными числами с использованием функции

int random(int num);

которая генерирует случайное целое число из диапазона от 0 до num – 1; Таким образом, случайные координаты вершин многоугольника будут находиться в диапазонах [-x0, x0] и [-y0, y0] и, следовательно, не выйдут за пределы экрана.

Plgn::~Plgn() // Деструктор

{

delete [] x; // Освобождение

delete [] y; // памяти

}

void Plgn::Show() // Рисует многоугольник, рядом

{ // с вершиной выводит ее номер

char num[20]; // Память под номер вершины

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

line(x0 + x[i], y0 - y[i], // Изображение

x0 + x[(i + 1) % n], y0 - y[(i + 1) % n]); // i-й стороны

itoa(i, num, 10); // Получение номера вершины

outtextxy(x0 + x[i], y0 - y[i], num); // Вывод номера вершины

}

}

Функция line рисует отрезки, соединяющие соседние вершины. Возле вершин многоугольника выводятся их номера. Для вывода текста на экран в графическом режиме использована функция

void outtextxy(int x, int y, char *textstring);

которая выводит строку символов textstring, начиная с пикселя экрана с координатами x, y.

Для получения строки с номером вершины использована функция (заголовочный файл stdlib.h)

char *ltoa(long value, char *string, int radix);

которая преобразует число value в строку цифр string, дающую представление числа в системе счисления с основанием radix.

void Plgn::Hide() // Стереть изображение

{

int clr = getcolor(); // Запоминаем цвет рисования

setcolor(getbkcolor()); // Цветом рисования делаем цвет фона

Show(); // Рисуем цветом фона, изображение исчезает

setcolor(clr); // Восстанавливаем прежний цвет рисования

}

void Plgn::Move(int dx, int dy) // Смещение многоугольника на dx

{ // по горизонтали и на dy по вертикали

Hide(); // Убираем изображение

for(int i = 0; i < n; i++) // Смещение

x[i] += dx, y[i]+=dy; // каждой вершины

Show(); // Снова показываем многоугольник

}

Выпишем формулы, нужные для программирования поворота многоугольника вокруг центра масс. На рис.40 показан многоугольник и одна из его вершин M в исходном положении и после его поворота вокруг точки C на угол β. Новое положение вершины обозначено M1.

В качестве центра масс можно взять точку C с координатами:

программа 48. многоугольники - student2.ru .

Здесь n – число вершин многоугольника, xi, yi, i=1,…, n – координаты вершин. Данная формула действительно будет давать координаты центра масс, если вся масса многоугольника сосредоточена в его вершинах и массы вершин одинаковы.

Как видно из рис.40, координаты точки M относительно центра масс C равны:

программа 48. многоугольники - student2.ru .

программа 48. многоугольники - student2.ru

Рис.40. Поворот многоугольника вокруг центра масс

Так как программа 48. многоугольники - student2.ru , то относительные координаты точки M1 после поворота выразятся формулами:

программа 48. многоугольники - student2.ru

Таким образом, новые абсолютные координаты точки M будут:

программа 48. многоугольники - student2.ru

Эти формулы используются в функции вращения многоугольника:

void Plgn::Rotate(float angle) // Функция поворота многоугольника

{ // на угол angle (задается в градусах)

float xC = 0, yC = 0, xr, yr;

int i;

angle = angle*M_PI/180; // Перевод угла в радианы

Hide(); // Убираем изображение

for(i = 0; i < n; i++){ // Вычисление координат

xC += x[i]; yC += y[i]; // центра масс

}

xC /= n; yC /= n;

for(i = 0; i < n; i++){ // Получение координат вершин после поворота

xr = x[i] - xC; // Координаты вершины

yr = y[i] - yC; // относительно центра масс

x[i] = xC + xr * cos(angle) - yr * sin(angle); // Координаты вершины

y[i] = yC + xr * sin(angle) + yr * cos(angle); // после поворота

}

Show(); // Показываем многоугольник

}

void Plgn::Movement() // Движение при нажатии клавиш

{ // со стрелками, пока не нажата Esc

const int UP = 72, DOWN = 80, LFTUP = 76, // Константы

RIGHT = 77, LEFT = 75, ESC = 27; // для кодов клавиш

char c = 32; // Начальное значение для c должно отличаться от ESC

while(c != ESC){ // Пока не нажата клавиша esc

c = getch(); // Читаем код клавиши

if(c == 0) // Если у клавиши двухбайтовый код,

c = getch(); // читаем второй байт

switch(c){

case LEFT: Move(-1, 0); break; // Нажата стрелка влево

case RIGHT: Move(1, 0); break; // Нажата стрелка вправо

case UP: Move(0, 1); break; // Нажата стрелка вверх

case DOWN: Move(0, -1); break; // Нажата стрелка вниз

case LFTUP: Rotate(5); break;

}

}

}

Перемещение многоугольника производится нажатием клавиш со стрелками. Вращение – нажатием клавиши 5 на дополнительной цифровой клавиатуре. При этом не должна гореть лампочка NumLock, чтобы клавиши дополнительной цифровой клавиатуры работали как управляющие, а не как цифровые.

// Определение статических членов класса – координат центра экрана

int Plgn::x0, Plgn::y0;

void main()

{

int gd = DETECT, gmode, n, x;

char c;

randomize(); // Инициализация датчика случайных чисел

initgraph(&gd, &gmode, "C:\\TC30\\BGI"); // Установка граф. режима

// Задаем координаты центра экрана

Plgn::SetBegCoord(getmaxx() / 2, getmaxy() / 2);

cout << "Введите число вершин: ";

cin >> n; // Ввод числа вершин

Plgn mnog(n); // Многоугольник

setcolor(WHITE); // Установка цвета

mnog.Show(); // Вывод многоугольника

mnog.Movement(); // Перемещения многоугольника

mnog.Hide(); // Убираем многоугольник

Plgn triangle; // Многоугольник по умолчанию (треугольник)

triangle.Show(); // Показываем треугольник

triangle.Movement(); // Движение треугольника

triangle.Hide(); // Скрываем треугольник

closegraph(); // Переход в текстовый режим

}

Вызов статической функции

Plgn::SetBegCoord(getmaxx() / 2, getmaxy() / 2);

устанавливает для статических членов класса Plgn::x0, Plgn::y0 значения координат центра экрана.

В главной функции сначала создается многоугольник mnog, число вершин которого следует ввести. Затем для mnog вызывается функция Movement, которая позволяет его двигать и вращать. Далее создается треугольник triangle с использованием конструктора по умолчанию. Треугольником также можно «поиграть».

Для чтения кодов нажимаемых клавиш использована функция
int getch() (заголовочный файл conio.h), которая возвращает для обычных алфавитно-цифровых клавиш однобайтовый код, равный коду соответствующего символа, а для управляющих и функциональных клавиш – двухбайтовый код. Для таких клавиш при первом вызове getch() возвращает 0, а при втором – некоторый код, свой для каждой клавиши. Коды, возвращаемые getch(), можно узнать с помощью программы:

// Файл CodeKeys.cpp

// Получение кодов клавиш функцией getch()

#include <iostream.h>

#include <conio.h>

void main()

{

cout << "\nНажмите клавишу\n";

int c = getch();

if(0 == c){

c = getch();

cout << "\nУ клавиши двухбайтовый код: 0 " << c << endl;

}

else

cout << "\nУ клавиши однобайтовый код: " << c ;

getch();

}

Наши рекомендации