Міністерство освіти і науки України
Національний університет “Львівська політехніка”
Звіт
до розрахунково-графічної роботи
з курсу “Програмування комп’ютерної графіки”
Львів 2016
1.1 Завдання
Варіант 7-19-6
Побудувати графік функції
,
Графік має відображати результати розрахунків, які записані у файлі на диску, а масштаб розмітки осей координат графіка – реальним результатам розрахунків. Параметри для побудови графіка:
Колір
Тип лінії для побудови кривої графіка
Товщина лінії
(пікселів)
blue
4
Необхідно передбачити “плаваючий” центр координат, – основну частину екрану мають займати ті чверті, в яких знаходиться графік функції.
Структура зображення
Пояснення
Рух квадрата зі стороною а по видимому круговому контуру радіусу R проти годинникової стрілки з одночасним обертанням квадрата відносно центру перетину власних діагоналей проти годинникової стрілки.
Параметри: а=24, R=90
1.2 Розрахунок функціональних залежностей для побудови графіка.
Оскільки реальні координати графіка функції, що виводиться на екран можуть бути або значно більшими, або значно меншими за машинні координати екрану монітору, необхідно визначити значення масштабних коефіцієнтів стискання або розтягу для функції, що виводиться на екран.
Позначимо максимальні та мінімальні значення реальних координат по осях X та Y – Xmin, Xmax, Ymin, Ymax.
Визначаємо розміри нашого вікна через функцію GetClientRect. Тоді масштабні коефіцієнти для графіка по осях X та Y дорівнюють, відповідно:
При виведенні графіка функції на екран монітору значення реальних координат заданої функції домножуємо на масштабні коефіцієнти і додаємо координати машинного центру координат (X0,Y0):
2.1. Завдання.
Створити на екрані комп’ютера графічне вікно і сформувати в ньому рухоме зображення.
Параметри зображення задані в пікселах. Графік і вікно з рухомим зображенням повинні бути присутні на екрані одночасно.
2.2 Розрахунок матриці перетворень для рухомого зображення.
Результуюча матриця М, руху є добутком трьох матриць: переносу T1, T2 і повороту R, причому перша матриця T1 відповідає перенесенню центру повороту в початок координат на відстань -dx та -dy, друга R – повороту об’єкта на кут φ, третя T2 – поверненню об’єкта з початку координат на площину зображення (координати dx та dy).
Перемноживши матрицю-рядок із старими координатами на результуючу матрицю руху, одержимо матрицю з новими координатами рухомої точки.
3. Список ідентифікаторів програми.
Xmin, Xmax, Ymin, Ymax – крайні значення функції;
x, y – значення функції;
x0, y0 – початок координат;
kx, ky – масштабні коефіцієнти;
str – строка символів;
X1, Y1 – верхній лівий кут вікна з анімацією;
Xc, Yc – центр кола;
x, y – центр квадрата;
x1, x2, x3, x4, y1, y2, y3, y4, xс1, xс2, xс3, xс4, yс1, yс2, yс3, yс4 – координати сторін квадрату і його внутрішніх точок;
x1p, y1p – перехідні координати спиць;
і – градуси повороту квадрата;
pi – константа π.
4. Блок-схеми основної програми побудови графіка та анімації.
Графік
Анімація
5. Текст програми.
void Crozrah_7_19_6View::OnDraw(CDC* pDC)
{
Crozrah_7_19_6Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
double pi = 3.1415;
CRect rectClient;
GetClientRect(rectClient);
CPen penBlack2;
penBlack2.CreatePen(PS_DASHDOT, 4, RGB(0, 0, 255));
pDC->SelectObject(&penBlack2);
double Xmax = 3, Ymax = -100, Xmin = -5, Ymin = 100;
for (double x = -5; x <= 3; x += 0.01)
{
double y = 9*pow(x,3)-1;
if (y > Ymax) Ymax = y;
if (y < Ymin) Ymin = y;
}
double x0, y0, kx, ky;
if (Xmin*Xmax < 0)
{
x0 = rectClient.right / 2;
kx = (rectClient.right/2 - 20) / (- Xmin);
}
else
if (Xmin < 0)
{
x0 = rectClient.right - 10;
kx = (rectClient.right - 20) / (-Xmin);
}
else
{
x0 = 10;
kx = (rectClient.right - 60) / (Xmax);
}
if (Ymin*Ymax < 0)
{
y0 = rectClient.bottom / 2;
ky = (rectClient.bottom/2-20) / (- Ymin);
}
else
if (Ymin < 0)
{
y0 = 10;
ky = (rectClient.bottom - 20) / (-Ymin);
}
else
{
y0 = rectClient.bottom - 10;
ky = (rectClient.bottom - 20) / (Ymax);
}
pDC->MoveTo(Xmin*kx + x0, -(9*pow(Xmin,3)-1)*ky + y0);
for (double x = -5; x <= 3; x += 0.01)
{
double y = -(9*pow(x,3)-1);
pDC->LineTo(x*kx + x0, y*ky + y0);
}
CPen penBlack1;
penBlack1.CreatePen(PS_SOLID, 3, RGB(0, 0, 0));
pDC->SelectObject(&penBlack1);
pDC->MoveTo(0, y0);
pDC->LineTo(rectClient.right, y0);
pDC->MoveTo(x0, 0);
pDC->LineTo(x0, rectClient.bottom);
pDC->MoveTo(x0, 0);
pDC->LineTo(x0 + 5, 5);
pDC->MoveTo(x0, 0);
pDC->LineTo(x0 - 5, 5);
pDC->MoveTo(rectClient.right, y0);
pDC->LineTo(rectClient.right - 5, y0 + 5);
pDC->MoveTo(rectClient.right, y0);
pDC->LineTo(rectClient.right - 5, y0 - 5);
CPen penBlack3;
penBlack3.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
pDC->SelectObject(&penBlack3);
for (double i = x0; i < rectClient.right; i += kx*1)
{
pDC->MoveTo(i, y0 + 5);
pDC->LineTo(i, y0 - 5);
}
for (double i = x0; i > 0; i -= kx*1)
{
pDC->MoveTo(i, y0 + 5);
pDC->LineTo(i, y0 - 5);
}
for (double i = y0; i < rectClient.bottom; i += ky * 200)
{
pDC->MoveTo(x0 + 5, i);
pDC->LineTo(x0 - 5, i);
}
for (double i = y0; i > 0; i -= ky * 200)
{
pDC->MoveTo(x0 + 5, i);
pDC->LineTo(x0 - 5, i);
}
CString str;
str = "0";
pDC->TextOut(3 + x0, -17 + y0, str);
str = "200";
pDC->TextOut(3 + x0, 5 - ky * 200 + y0, str);
str = "400";
pDC->TextOut(3 + x0, -19 - ky * 200 * 2 + y0, str);
str = "600";
pDC->TextOut(3 + x0, 5 - ky * 200 * 3 + y0, str);
str = "800";
pDC->TextOut(3 + x0, -19 - ky * 200 * 4 + y0, str);
str = "1000";
pDC->TextOut(3 + x0, 5 - ky * 200 * 5 + y0, str);
str = "-200";
pDC->TextOut(3 + x0, 5 - -ky * 200 + y0, str);
str = "-400";
pDC->TextOut(3 + x0, -19 - -ky * 200 * 2 + y0, str);
str = "-600";
pDC->TextOut(3 + x0, 5 - -ky * 200 * 3 + y0, str);
str = "-800";
pDC->TextOut(3 + x0, -19 - -ky * 200 * 4 + y0, str);
str = "-1000";
pDC->TextOut(3 + x0, 5 - -ky * 200 * 5 + y0, str);
str = "-1200";
pDC->TextOut(3 + x0, -19 - -ky * 200 * 6 + y0, str);
str = "1";
pDC->TextOut(6 + kx * 1 + x0, -20 + y0, str);
str = "2";
pDC->TextOut(6 + kx * 1 * 2 + x0, -20 + y0, str);
str = "3";
pDC->TextOut(6 + kx * 1 * 3 + x0, -20 + y0, str);
str = "4";
pDC->TextOut(6 + kx * 1 * 4 + x0, -20 + y0, str);
str = "5";
pDC->TextOut(-7 + kx * 1 * 5 + x0, -20 + y0, str);
str = "-1";
pDC->TextOut(6 + -kx * 1 + x0, -20 + y0, str);
str = "-2";
pDC->TextOut(6 + -kx * 1 * 2 + x0, -20 + y0, str);
str = "-3";
pDC->TextOut(6 + -kx * 1 * 3 + x0, -20 + y0, str);
str = "-4";
pDC->TextOut(6 + -kx * 1 * 4 + x0, -20 + y0, str);
str = "-5";
pDC->TextOut(-7 + -kx * 1 * 5 + x0, -20 + y0, str);
str = "y";
pDC->TextOut(6 + x0, 5 - rectClient.bottom/2 + y0, str);
str = "x";
pDC->TextOut(-10 + rectClient.right, -22 + y0, str);
double X1 = 130, Y1 = 10;
double Xc = X1 + 110, Yc = Y1 + 110;
double x = Xc, y = Yc - 90;
CBrush brush_black, brush_black2;
brush_black.CreateSolidBrush(RGB(0, 0, 0));
brush_black2.CreateSolidBrush(RGB(255, 255, 255));
int i = 0;
while (true)
{
double R = 12 / cos(pi / 4);
double r = 10 / cos(pi / 4);
pDC->Rectangle(X1, Y1, X1 + 220, Y1 + 220);
pDC->Ellipse(Xc - 90, Yc - 90, Xc + 90, Yc + 90);
double xc1 = x + R*cos(-pi * 3 * i / 180 + 2 * pi * 1 / 4.0);
double xc2 = x + R*cos(-pi * 3 * i / 180 + 2 * pi * 2 / 4.0);
double xc3 = x + R*cos(-pi * 3 * i / 180 + 2 * pi * 3 / 4.0);
double xc4 = x + R*cos(-pi * 3 * i / 180 + 2 * pi * 4 / 4.0);
double yc1 = y + R*sin(-pi * 3 * i / 180 + 2 * pi * 1 / 4.0);
double yc2 = y + R*sin(-pi * 3 * i / 180 + 2 * pi * 2 / 4.0);
double yc3 = y + R*sin(-pi * 3 * i / 180 + 2 * pi * 3 / 4.0);
double yc4 = y + R*sin(-pi * 3 * i / 180 + 2 * pi * 4 / 4.0);
double x1 = x + r*cos(-pi * 3 * i / 180 + 2 * pi * 1 / 4.0);
double x2 = x + r*cos(-pi * 3 * i / 180 + 2 * pi * 2 / 4.0);
double x3 = x + r*cos(-pi * 3 * i / 180 + 2 * pi * 3 / 4.0);
double x4 = x + r*cos(-pi * 3 * i / 180 + 2 * pi * 4 / 4.0);
double y1 = y + r*sin(-pi * 3 * i / 180 + 2 * pi * 1 / 4.0);
double y2 = y + r*sin(-pi * 3 * i / 180 + 2 * pi * 2 / 4.0);
double y3 = y + r*sin(-pi * 3 * i / 180 + 2 * pi * 3 / 4.0);
double y4 = y + r*sin(-pi * 3 * i / 180 + 2 * pi * 4 / 4.0);
pDC->MoveTo(xc1, yc1);
pDC->LineTo(xc2, yc2);
pDC->LineTo(xc3, yc3);
pDC->LineTo(xc4, yc4);
pDC->LineTo(xc1, yc1);
pDC->SelectObject(brush_black);
pDC->FloodFill(x1, y1, RGB(0, 0, 0));
pDC->FloodFill(x2, y2, RGB(0, 0, 0));
pDC->FloodFill(x3, y3, RGB(0, 0, 0));
pDC->FloodFill(x4, y4, RGB(0, 0, 0));
pDC->SelectObject(brush_black2);
double x1p = (x - Xc)*cos(pi / 180) + (y - Yc)*sin(pi / 180);
double y1p = -(x - Xc)*sin(pi / 180) + (y - Yc)*cos(pi / 180);
x = x1p + Xc; y = y1p + Yc;
i++;
Sleep(30);
}
}
6. Результат виконання програми
Висновок.
В даній розрахунковій роботі розроблено алгоритми та написана програма мовою C++, що виводить на екран монітору графік функції.
Програма визначається універсальністю для побудови графіка функції в будь-якій чверті системи координат за рахунок використання «плаваючого» початку координат.
Також в цій розрахунковій роботі розроблено алгоритми та написана програма мовою C++, що виводить на екран монітору рухоме зображення.
В програмі використовуються матричні перетворення. Результуюча матриця руху формується з добутку трьох матриць переносу та однієї матриці повороту.