Міністерство освіти і науки України
Національний університет “Львівська політехніка”
Звіт
до розрахунково-графічної роботи
з курсу “Програмування комп’ютерної графіки”
Львів - 2016
1.1 Завдання
Варіант 7-19-7
Побудувати графік функції
,
Графік має відображати результати розрахунків, які записані у файлі на диску, а масштаб розмітки осей координат графіка – реальним результатам розрахунків. Параметри для побудови графіка:
Колір
Тип лінії для побудови кривої графіка
Товщина лінії
(пікселів)
blue
4
Необхідно передбачити “плаваючий” центр координат, – основну частину екрану мають займати ті чверті, в яких знаходиться графік функції.
1.2 Розрахунок функціональних залежностей для побудови графіка.
Оскільки реальні координати графіка функції, що виводиться на екран можуть бути або значно більшими, або значно меншими за машинні координати екрану монітору, необхідно визначити значення масштабних коефіцієнтів стискання або розтягу для функції, що виводиться на екран.
Позначимо максимальні та мінімальні значення реальних координат по осях X та Y – Xmin, Xmax, Ymin, Ymax.
Визначаємо розміри нашого вікна через функцію GetClientRect. Тоді масштабні коефіцієнти для графіка по осях X та Y дорівнюють, відповідно:
При виведенні графіка функції на екран монітору значення реальних координат заданої функції домножуємо на масштабні коефіцієнти і додаємо координати машинного центру координат (X0,Y0):
2.1. Завдання.
Створити на екрані комп’ютера графічне вікно і сформувати в ньому рухоме зображення.
Параметри зображення задані в пікселах. Графік і вікно з рухомим зображенням повинні бути присутні на екрані одночасно.
Структура зображення
Пояснення
Кулька діаметром d котиться по внутрішній частині дуги радіусу R1 проти годинникової стрілки. Після досягнення кінцевої точки дуги кулька обертається відносно цієї точки і продовжує рухатися по зовнішній частині дуги радіусу R2. Відстань між центрами дуг а. кольори дуг і кульки різні.
Параметри: d=30, R1=120, R2=110, a=70
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. Текст програми.
#include "stdafx.h"
#include "laba.h"
#include "ChildView.h"
#include <math.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
CChildView::CChildView()
{
}
CChildView::~CChildView()
{
}
BEGIN_MESSAGE_MAP(CChildView, CWnd)
ON_WM_PAINT()
END_MESSAGE_MAP()
BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs)
{
if (!CWnd::PreCreateWindow(cs))
return FALSE;
cs.dwExStyle |= WS_EX_CLIENTEDGE;
cs.style &= ~WS_BORDER;
cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS,
::LoadCursor(NULL, IDC_ARROW), reinterpret_cast<HBRUSH>(COLOR_WINDOW+1), NULL);
return TRUE;
}
void CChildView::OnPaint()
{
CPaintDC dc(this);
double pi = 3.1415;
CRect rectClient;
GetClientRect(rectClient);
CPen penBlack2;
penBlack2.CreatePen(PS_DASHDOT, 4, RGB(0, 0, 255));
dc.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);
}
dc.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);
dc.LineTo(x*kx + x0, y*ky + y0);
}
CPen penBlack1; //осі
penBlack1.CreatePen(PS_SOLID, 3, RGB(0, 0, 0));
dc.SelectObject(&penBlack1);
dc.MoveTo(0, y0);
dc.LineTo(rectClient.right, y0);
dc.MoveTo(x0, 0);
dc.LineTo(x0, rectClient.bottom);
dc.MoveTo(x0, 0);
dc.LineTo(x0 + 5, 5);
dc.MoveTo(x0, 0);
dc.LineTo(x0 - 5, 5);
dc.MoveTo(rectClient.right, y0);
dc.LineTo(rectClient.right - 5, y0 + 5);
dc.MoveTo(rectClient.right, y0);
dc.LineTo(rectClient.right - 5, y0 - 5);
CPen penBlack3;
penBlack3.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
dc.SelectObject(&penBlack3);
for (double i = x0; i < rectClient.right; i += kx*1)
{
dc.MoveTo(i, y0 + 5);
dc.LineTo(i, y0 - 5);
}
for (double i = x0; i > 0; i -= kx*1)
{
dc.MoveTo(i, y0 + 5);
dc.LineTo(i, y0 - 5);
}
for (double i = y0; i < rectClient.bottom; i += ky * 200)
{
dc.MoveTo(x0 + 5, i);
dc.LineTo(x0 - 5, i);
}
for (double i = y0; i > 0; i -= ky * 200)
{
dc.MoveTo(x0 + 5, i);
dc.LineTo(x0 - 5, i);
}
CString str;
str = "0";
dc.TextOut(10 + x0, -10 + y0, str);
str = "200";
dc.TextOut(10 + x0, -7 - ky * 200 + y0, str);
str = "400";
dc.TextOut(10 + x0, -7 - ky * 200 * 2 + y0, str);
str = "600";
dc.TextOut(10 + x0, -7 - ky * 200 * 3 + y0, str);
str = "800";
dc.TextOut(10 + x0, -7 - ky * 200 * 4+ y0, str);
str = "1000";
dc.TextOut(10 + x0, -7 - ky * 200 * 5 + y0, str);
str = "-200";
dc.TextOut(10 + x0, -7 - -ky * 200 + y0, str);
str = "-400";
dc.TextOut(10 + x0, -7 - -ky * 200 * 2 + y0, str);
str = "-600";
dc.TextOut(10 + x0, -7 - -ky * 200 * 3 + y0, str);
str = "-800";
dc.TextOut(10 + x0, -7 - -ky * 200 * 4 + y0, str);
str = "-1000";
dc.TextOut(10 + x0, -7 - -ky * 200 * 5 + y0, str);
str = "-1200";
dc.TextOut(10 + x0, -7 - -ky * 200 * 6 + y0, str);
str = "1";
dc.TextOut( kx + x0, -20 + y0, str);
str = "2";
dc.TextOut( kx * 2 + x0, -20 + y0, str);
str = "3";
dc.TextOut( kx * 3 + x0, -20 + y0, str);
str = "4";
dc.TextOut( kx * 4 + x0, -20 + y0, str);
str = "5";
dc.TextOut( kx * 5 + x0, -20 + y0, str);
str = "-1";
dc.TextOut( -kx + x0, -20 + y0, str);
str = "-2";
dc.TextOut( -kx * 2 + x0, -20 + y0, str);
str = "-3";
dc.TextOut( -kx * 3 + x0, -20 + y0, str);
str = "-4";
dc.TextOut( -kx * 4 + x0, -20 + y0, str);
str = "-5";
dc.TextOut( -kx * 5 + x0, -20 + y0, str);
str = "y";
dc.TextOut(6 + x0, 5 - rectClient.bottom/2 + y0, str);
str = "x";
dc.TextOut(-10 + rectClient.right, -22 + y0, str);
CBrush brush_black1, brush_black2;
brush_black1.CreateSolidBrush(RGB(255, 255, 255));
brush_black2.CreateSolidBrush(RGB(255, 0, 0));
double Xc = rectClient.right - 300, Yc = rectClient.CenterPoint().y + 20;
double X1 = rectClient.right - 150, Y1 = rectClient.CenterPoint().y + 10;
double X2 = rectClient.right - 150, Y2 = rectClient.CenterPoint().y + 80;
while (true)
{
double r = 15, x = X1 - 94, y = Y2 - 25;
double pi = 3.1415;
for (int i = 0; i < 132; i++)
{
dc.Rectangle(Xc, Yc, Xc + 300, Yc + 210);
dc.Arc(X1 - 120, Y1 - 120, X1 + 120, Y1 + 120, X1 - 107, Y2 - 20, X1 + 107, Y2 - 20);
dc.Arc(X2 - 110, Y2 - 110, X2 + 110, Y2 + 110, X1 - 107, Y2 - 20, X1 + 107, Y2 - 20);
dc.SelectObject(brush_black2);
dc.Ellipse(x - r, y - r, x + r, y + r);
dc.SelectObject(brush_black1);
double x1p = (x - X1)*cos(pi / 180) + (y - Y1)*sin(pi / 180);
double y1p = -(x - X1)*sin(pi / 180) + (y - Y1)*cos(pi / 180);
x = x1p + X1; y = y1p + Y1;
Sleep(30);
}
for (int i = 0; i < 130; i++)
{
dc.Rectangle(Xc, Yc, Xc + 300, Yc + 210);
dc.Arc(X1 - 120, Y1 - 120, X1 + 120, Y1 + 120, X1 - 107, Y2 - 20, X1 + 107, Y2 - 20);
dc.Arc(X2 - 110, Y2 - 110, X2 + 110, Y2 + 110, X1 - 107, Y2 - 20, X1 + 107, Y2 - 20);
dc.SelectObject(brush_black2);
dc.Ellipse(x - r, y - r, x + r, y + r);
dc.SelectObject(brush_black1);
double x1p = (x - (X1 + 107))*cos(pi * 1 / 180) - (y - (Y2 - 20))*sin(pi * 1 / 180);
double y1p = (x - (X1 + 107))*sin(pi * 1 / 180) + (y - (Y2 - 20))*cos(pi * 1 / 180);
x = x1p + (X1 + 107); y = y1p + (Y2 - 20);
Sleep(10);
}
for (int i = 0; i < 200; i++)
{
dc.Rectangle(Xc, Yc, Xc + 300, Yc + 210);
dc.Arc(X1 - 120, Y1 - 120, X1 + 120, Y1 + 120, X1 - 107, Y2 - 20, X1 + 107, Y2 - 20);
dc.Arc(X2 - 110, Y2 - 110, X2 + 110, Y2 + 110, X1 - 107, Y2 - 20, X1 + 107, Y2 - 20);
dc.SelectObject(brush_black2);
dc.Ellipse(x - r, y - r, x + r, y + r);
dc.SelectObject(brush_black1);
double x1p = (x - X2)*cos(pi / 180) - (y - Y2)*sin(pi / 180);
double y1p = (x - X2)*sin(pi / 180) + (y - Y2)*cos(pi / 180);
x = x1p + X2; y = y1p + Y2;
Sleep(30);
}
for (int i = 0; i < 150; i++)
{
dc.Rectangle(Xc, Yc, Xc + 300, Yc + 210);
dc.Arc(X1 - 120, Y1 - 120, X1 + 120, Y1 + 120, X1 - 107, Y2 - 20, X1 + 107, Y2 - 20);
dc.Arc(X2 - 110, Y2 - 110, X2 + 110, Y2 + 110, X1 - 107, Y2 - 20, X1 + 107, Y2 - 20);
dc.SelectObject(brush_black2);
dc.Ellipse(x - r, y - r, x + r, y + r);
dc.SelectObject(brush_black1);
double x1p = (x - (X1 - 107))*cos(pi * 1 / 180) - (y - (Y2 - 20))*sin(pi * 1 / 180);
double y1p = (x - (X1 - 107))*sin(pi * 1 / 180) + (y - (Y2 - 20))*cos(pi * 1 / 180);
x = x1p + (X1 - 107); y = y1p + (Y2 - 20);
Sleep(10);
}
}
}
6. Результат виконання програми
Висновок.
В даній розрахунковій роботі розроблено алгоритми та написана програма мовою C++, що виводить на екран монітору графік функції.
Програма визначається універсальністю для побудови графіка функції в будь-якій чверті системи координат за рахунок використання «плаваючого» початку координат.
Також в цій розрахунковій роботі розроблено алгоритми та написана програма мовою C++, що виводить на екран монітору рухоме зображення.
В програмі використовуються матричні перетворення. Результуюча матриця руху формується з добутку трьох матриць переносу та однієї матриці повороту.