Міністерство освіти і науки, молоді та спорту України
Національний університет «Львівська політехніка»
Графічно-розрахункова робота № 1
з курсу «Програмування комп’ютерної графіки»
Мета: набути практичних навиків в складанні програми для побудови зображень на екрані комп’ютера в середовищі Microsoft Visual Studio C++ 2008.
Завдання:
Побудувати графік функції (таблиця 1), заданої таблично. Масштаб розмітки осей координат повинен відповідати реальним результатам розрахунків. Параметри для побудови графіка визначені в таблиці 2. Варіант завдання визначає викладач.
Необхідно передбачати плаваючий центр координат – основну частину екрану мають займати ті чверті, в яких знаходиться графік функції.
Таблиця 1.
/
Таблиця 2.
/
Зміст звіту:
Повний текст завдання.
Блок-схема алгоритму програми.
Розрахунок функціональних залежностей для побудови графіка.
Список ідентифікаторів констант, змінних, процедур і функцій, використовуваних в програмі та їх пояснення.
Остаточно відлагоджений текст програми згідно з отриманим завданням.
Результат виконання програми.
Висновок.
2. Блок-схема алгоритму програми.
Рис. 1
/
/
/
/
3. Розрахунок функціональних залежностей для побудови графіка.
xd = b-a;
xmashd = rect.right - rect.left;
yd = ymax-ymin;
ymashd = rect.bottom - rect.top;
ky = (ymashd - y_retreat_bottom - y_retreat_top)/yd;
kx = (xmashd - x_retreat_left - x_retreat_right)/xd;
x_axis = x_retreat_left - kx * a;
y_axis = y_retreat_top + ky * ymax;
4. Список ідентифікаторів констант, змінних, процедур і функцій, використовуваних в програмі та їх пояснення.
hPen – перо товщиною 3 рх;
CPen – функція для створення пера;
LineTo – проводить лінію з поточної вершини до точки, координати якої задані;
MoveToEx – переміщує поточну вершину;
FloodFill – зафарбовує замкнуту область;
SelectObject – вибирає потрібний пензль або перо;
DeleteObject - видаляє потрібний пензль або перо;
GetClientRect – визначення параметрів екрану користувача;
CString – оголошення змінної для виведення тексту;
kx, ky – змінні коефіціентів перетворення;
xd, yd, xmashd, ymashd - різниця мінімальних і максимальних координат;
xmash, ymash – машинні координати;
x, y - реальні координати;
h – інтервал;
ymax, ymin, – мінімальні і максимальні значення функції;
a = -50; - Початкове значення проміжку;
b = 50; - Кінцеве значення проміжку ;
x_retreat_left, x_retreat_right, y_retreat_bottom, y_retreat_top - Відступи по краях;
x_axis, y_axis – машинны координати осей;
F – змінна функції;
Y, X, O, d, ss, ssss, A – змінні для виведення розмітки осей.
5. Остаточно відлагоджений текст програми згідно з отриманим завданням.
// ChildView.cpp : implementation of the CChildView class
//
#include "stdafx.h"
#include "lr1.h"
#include "ChildView.h"
#include <cmath>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CChildView
CChildView::CChildView()
{
}
CChildView::~CChildView()
{
}
BEGIN_MESSAGE_MAP(CChildView, CWnd)
ON_WM_PAINT()
END_MESSAGE_MAP()
// CChildView message handlers
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;
}
double F(double x) {
return atan(x); // Задаємо функцію
}
void CChildView::OnPaint()
{
SEGdc dcc(this); // device context for painting
RECT rect;
GetClientRect(&rect);
// Змінні для побудови графіку - ПОЧАТОК
int xmash, ymash, x_axis, y_axis, x_retreat_left, x_retreat_right, y_retreat_bottom, y_retreat_top;
double y, kx, ky, xmashd, xd, ymashd, yd, a, b, h, ymax, ymin;
x_retreat_left = x_retreat_right = y_retreat_bottom = 70; // Відступи по краях
y_retreat_top = 250;
a = -50; // Початкове значення проміжку
b = 50; // Кінцеве значення проміжку
h = 0.01; // Крок
// Змінні для побудови графіку - КІНЕЦЬ
//Визначення мінімального і максимального значення - ПОЧАТОК
ymax = F(a);
ymin = F(a);
for (double x = a; x < b; x = x + h) {
y = F(x);
if (ymax < y)
ymax = y;
else;
if (ymin > y)
ymin = y;
else;
}
//Визначення мінімального і максимального значення - КІНЕЦЬ
//Визначення параметрів для побудови графіку
xd = b-a; xmashd = rect.right - rect.left;
yd = ymax-ymin; ymashd = rect.bottom - rect.top;
ky = (ymashd - y_retreat_bottom - y_retreat_top)/yd;
kx = (xmashd - x_retreat_left - x_retreat_right)/xd;
x_axis = x_retreat_left - kx * a;
y_axis = y_retreat_top + ky * ymax;
int x_axis1 = x_axis, y_axis1 = y_axis;
if(x_axis1 < x_retreat_left)
x_axis1 = x_retreat_left;
if(x_axis1 > rect.right - x_retreat_right)
x_axis1 = rect.right - x_retreat_right;
if(y_axis1 < y_retreat_top)
y_axis1 = y_retreat_top;
if(y_axis1 > rect.bottom - y_retreat_bottom)
y_axis1 = rect.bottom - y_retreat_bottom;
//Будуємо осі координат - ПОЧАТОК
dcc.MoveTo(x_axis1, y_axis1);
dcc.LineTo(x_axis1, y_retreat_top - 15);
dcc.MoveTo(x_axis1 - 3, y_retreat_top - 5);
dcc.LineTo(x_axis1, y_retreat_top - 15);
dcc.MoveTo(x_axis1 + 3, y_retreat_top - 5);
dcc.LineTo(x_axis1, y_retreat_top - 15);
dcc.MoveTo(x_axis1, y_axis1);
dcc.LineTo(x_axis1, rect.bottom-y_retreat_bottom + 5);
const CString Y("Y");
dcc.TextOutW(x_axis1 - 15, y_retreat_top - 10, Y);
dcc.MoveTo(x_axis1, y_axis1);
dcc.LineTo(x_retreat_left - 5, y_axis1);
dcc.MoveTo(x_axis1, y_axis1);
dcc.LineTo(rect.right - x_retreat_right + 15, y_axis1);
dcc.MoveTo(rect.right - x_retreat_right + 5, y_axis1 - 3);
dcc.LineTo(rect.right - x_retreat_right + 15, y_axis1);
dcc.MoveTo(rect.right - x_retreat_right + 5, y_axis1+3);
dcc.LineTo(rect.right - x_retreat_right + 15, y_axis1);
const CString X("X");
dcc.TextOutW(rect.right - x_retreat_right + 10, y_axis1 - 25, X);
const CString O("O");
if (x_axis1 <= x_retreat_left || x_axis1 >= rect.right - x_retreat_right || y_axis1 <= y_retreat_top || y_axis1 >= rect.bottom - y_retreat_bottom);
else dcc.TextOutW(x_axis1 - 15, y_axis1 + 5, O);
//Розмітка по осі Х - ПОЧАТОК
double d = b;
char str[20];
sprintf_s(str, 20, "%5.2lf", d);
CString ss(str);
dcc.TextOutW(x_axis + d*kx - 10, y_axis1 + 5, ss);
dcc.MoveTo(x_axis + b*kx, y_axis1 - 2);
dcc.LineTo(x_axis + b*kx, y_axis1 + 2);
double H = (b - a)/8;
d = a;
int w = b/5;
for(int i = 0; i < 8; i++) {
sprintf_s(str, 20, "%3.2lf", d);
CString A(str);
dcc.TextOutW(x_axis + d*kx, y_axis1 + 5, A);
dcc.MoveTo(x_axis + d*kx, y_axis1 - 2);
dcc.LineTo(x_axis + d*kx, y_axis1 + 2);
d += H;
}
//Розмітка по осі Х - КІНЕЦЬ
//Розмітка по осі У - ПОЧАТОК
d = ymax;
sprintf_s(str, 20, "%5.2lf", d);
CString ssss(str);
dcc.TextOutW(x_axis1 - 55, y_axis - ymax*ky, ssss);
dcc.MoveTo(x_axis1 - 2, y_axis - ymax*ky);
dcc.LineTo(x_axis1 + 2, y_axis - ymax*ky);
H = (ymax - ymin)/5;
d = ymin;
for (int i = 0; i < 5; i++) {
sprintf_s(str, 20, "%3.2lf", d);
CString A(str);
dcc.TextOutW(x_axis1 - 50, y_axis - d*ky - 5,A);
dcc.MoveTo(x_axis1 - 2,y_axis - d*ky);
dcc.LineTo(x_axis1 + 2, y_axis - d*ky);
d += H;
}
//Розмітка по осі У - КІНЕЦЬ
//Будуємо осі координат - КІНЕЦЬ
//Власне сама побудова графіку - ПОЧАТОК
HPEN hPen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0));
HGDIOBJ hOldPen = SelectObject(dcc, hPen);
dcc.MoveTo(x_axis + a*kx, y_axis - ky*F(a));
dcc.LineTo(x_axis + a*kx, y_axis - ky*F(a));
for (double x = a; x < b; x = x + h) {
xmash = x_axis + x*kx;
y = F(x);
ymash = y_axis - y*ky;
dcc.LineTo(xmash, ymash);
}
SelectObject(dcc, hOldPen);
DeleteObject(hPen);
//Власне сама побудова графіку – КІНЕЦЬ
}
6. Результат виконання програми.
Рис. 2
/
Висновок.
Виконавши завдання даної роботи я набув практичних навиків в складанні програми для побудови зображень на екрані комп’ютера в середовищі Microsoft Visual Studio C++ 2008.
Міністерство освіти і науки, молоді та спорту України
Національний університет «Львівська політехніка»
Графічно-розрахункова робота № 2
з курсу «Програмування комп’ютерної графіки»
Виконав:
студент групи СІ-23
sonye ©
Перевірив:
Лопачак О. М.
Львів 2011
Мета: набути практичних навиків в складанні програми для побудови зображень на екрані комп’ютера в середовищі Microsoft Visual Studio C++ 2008.
Завдання:
Створити на екрані комп’ютера графічне вікно та сформувати в ньому рухоме зображення. Вікно розмістити у верхньому правому куті екрану. Навести межі вікна. Параметри рухомого зображення визначені в таблиці 3. Параметри зображення задані в пік селях. Варіант завдання визначає викладач.
Графік та вікно з рухомим зображення повинні бути присутні на екрані одночасно, причому вікно немає перекривати графік. (Рис. 3).
/
Рис. 3. Розташування графіка і рухомого зображення на екрані комп’ютера
Таблиця 3.
/
Зміст звіту:
Повний текст завдання.
Блок-схема алгоритму програми.
Розрахунок матриці перетворень для рухомого зображення.
Список ідентифікаторів констант, змінних, процедур і функцій, використовуваних в програмі та їх пояснення.
Остаточно відлагоджений текст програми згідно з отриманим завданням.
Результат виконання програми.
Висновок.
2. Блок-схема алгоритму програми.
Рис. 4
/
/
/
/
/
/
3. Розрахунок матриці перетворень для рухомого зображення.
struct Vec
{
double x;
double y;
};
// Center - центр повороту
// Angle - в радіанах кут повороту
Vec Rotate(const Vec& Center, double Angle, const Vec& Point)
{
double dx = Point.x - Center.x;
double dy = Point.y - Center.y;
Vec Res;
Res.x = Center.x + cos(Angle) * dx + sin(Angle) * dy;
Res.y = Center.y - sin(Angle) * dx + cos(Angle) * dy;
return Res;
}
4. Список ідентифікаторів констант, змінних, процедур і функцій, використовуваних в програмі та їх пояснення.
h_brush – пензель;
hPen – перо товщиною 2 рх;
CPen – функція для створення пера;
LineTo – проводить лінію з поточної вершини до точки, координати якої задані;
MoveTo – переміщує поточну вершину;
FloodFill – зафарбовує замкнуту область;
SelectObject – вибирає потрібний пензль або перо;
DeleteObject - видаляє потрібний пензль або перо;
GetClientRect – визначення параметрів екрану користувача;
Vec – структура для повороту координати;
Rotate – функція повороту координати;
Flood – функція зафарбовування шустикутника;
unFlood – функція приховування кольору заливки шестикутника;
Center - центр повороту;
Angle - кут повороту в радіанах;
x, y – машинні координати;
sleeptime - час спання;
rect_pos_x1 - Координата Х верхнього лівого кута прямокутника;
rect_pos_y1 - Координата У верхнього лівого кута прямокутника;
rect_pos_x2 - Координата Х нижнього правого кута прямокутника;
rect_pos_y2 - Координата У нижнього правого кута прямокутника;
rect_сpos_x - Координата Х центру прямокутника;
rect_сpos_y - Координата У центру прямокутника;
R_small = 60 - Радіус малого півкола;
R = 100 - Радіус великого півкола
point_x[40][6] - Координати вершин шеcтикутника
point_y[40][6] – пронумеровано вершини шестикутника 0 - а, 1 - b, 2 - c, 3 - d, 4 - e, 5 – f;
seg_angle = 60 * 3.1415926535897932384626433832795/180; - Величина кута;
color_R[7] = {0, 0, 204, 204, 0, 255, 255}; - масив з палітрою R для заливки шеcтикутника;
color_G[7] = {51, 204, 204, 0, 204, 0, 255}; - масив з палітрою G для заливки шеcтикутника;
color_B[7] = {204, 51, 0, 204, 204, 51, 0}; - масив з палітрою B для заливки шеcтикутника;
color_pos_x[40]; - координата для заливки Х;
color_pos_y[40]; - координата для заливки У;
5. Остаточно відлагоджений текст програми згідно з отриманим завданням.
Вміст файлу ChildView.cpp
// ChildView.cpp : implementation of the CChildView class
//
#include "stdafx.h"
#include "lr1.h"
#include "ChildView.h"
#include <cmath>
#include "seg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
/* Функція розрахунку координат для повороту фігури*/
struct Vec
{
double x;
double y;
};
// Center - центр повороту
// Angle - в радіанах
Vec Rotate(const Vec& Center, double Angle, const Vec& Point)
{
double dx = Point.x - Center.x;
double dy = Point.y - Center.y;
Vec Res;
Res.x = Center.x + cos(Angle) * dx + sin(Angle) * dy;
Res.y = Center.y - sin(Angle) * dx + cos(Angle) * dy;
return Res;
}
// CChildView
CChildView::CChildView()
{
}
CChildView::~CChildView()
{
}
BEGIN_MESSAGE_MAP(CChildView, CWnd)
ON_WM_PAINT()
END_MESSAGE_MAP()
// CChildView message handlers
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()
{
SEGdc dcc(this); // device context for painting
RECT rect;
GetClientRect(&rect);
int rect_pos_x1 = rect.right - 350; // Координата Х верхнього лівого кута прямокутника
int rect_pos_y1 = rect.top + 20; // Координата У верхнього лівого кута прямокутника
int rect_pos_x2 = rect.right - 50; // Координата Х нижнього правого кута прямокутника
int rect_pos_y2 = rect.top + 220; // Координата Х нижнього правого кута прямокутника
int rect_сpos_x = (rect_pos_x2 - rect_pos_x1)/2 + rect_pos_x1; // Координата Х центру прямокутника
int rect_сpos_y = (rect_pos_y2 - rect_pos_y1)/2 + rect_pos_y1; // Координата У центру прямокутника
int R_small = 60; //Радіус малого півкола
int R = 100; //Радіус великого півкола
int point_x[40][6]; // Координати точок шеcтикутника
int point_y[40][6]; // 0 - а, 1 - b, 2 - c, 3 - d, 4 - e, 5 - f.
int sleeptime = 300; // час спання
double seg_angle = 60 * 3.1415926535897932384626433832795/180; //Величина кута.
int color_R[7] = {0, 0, 204, 204, 0, 255, 255}; // масив з палітрою R для заливки шестикутника
int color_G[7] = {51, 204, 204, 0, 204, 0, 255}; // масив з палітрою G для заливки шестикутника
int color_B[7] = {204, 51, 0, 204, 204, 51, 0}; // масив з палітрою B для заливки шестикутника
int color_pos_x[40]; // координата для заливки Х
int color_pos_y[40]; // координата для заливки У
dcc.Rectangle(rect_pos_x1, rect_pos_y1, rect_pos_x2, rect_pos_y2);
// Будуємо підкову - ПОЧАТОК
hPen = CreatePen(PS_SOLID, 2, RGB(0, 0, 0));
hOldPen = SelectObject(dcc, hPen);
dcc.MoveTo (rect_сpos_x + R_small, rect_pos_y2 - 30);
dcc.AngleArc (rect_сpos_x, rect_pos_y2 - 30, R, 0, 180);
dcc.MoveTo (rect_сpos_x + R_small, rect_pos_y2 - 30);
dcc.AngleArc (rect_сpos_x, rect_pos_y2 - 30, R_small, 0, 180);
dcc.LineTo (rect_сpos_x - R, rect_pos_y2 - 30);
SelectObject(dcc, hOldPen);
DeleteObject(hPen);
dcc.Flood (rect_сpos_x, rect_сpos_y, RGB(254,0,0));
// Будуємо підкову - КІНЕЦЬ
// 1 - ий шестикутник: визначаємо координати його врешин - ПОЧАТОК
point_x[0][0] = rect_сpos_x + R;
point_y[0][0] = rect_pos_y2 - 30;
int sc_oldpos_x = point_x[0][0], sc_oldpos_y = point_y[0][0]; // змінні кородинат
for (int i = 0; i < 5; i++) {
Vec Center = { point_x[0][0] + 20, point_y[0][0] };
Vec OldPos = { point_x[0][i], point_y[0][i] };
Vec NewPos = Rotate(Center, seg_angle, OldPos);
point_x[0][i+1] = NewPos.x;
point_y[0][i+1] = NewPos.y;
}
// 1 - ий шестикутник: визначаємо координати його врешин - КІНЕЦЬ
//Рзраховуємо і заносимо в масив координати вершин решти шестикутників - ПОЧАТОК
//це будуть шестикутники гострі
for (int i = 2; i < 12; i = i+2) {
for (int j = 0; j < 6; j++) {
Vec Center = { rect_сpos_x, rect_pos_y2 - 30 };
Vec OldPos = { point_x[i-2][j], point_y[i-2][j] };
Vec NewPos = Rotate(Center, seg_angle/2, OldPos);
point_x[i][j] = NewPos.x;
point_y[i][j] = NewPos.y;
}
}
//Рзраховуємо і заносимо в масив координати вершин решти шестикутників - КІНЕЦЬ
//Розраховуємо 1 - й тупий шестикутник - ПОЧАТОК
//перенос центру і розрахунок шестикутника
sc_oldpos_x = point_x[0][0] + 18, sc_oldpos_y = point_y[0][0];
for (int i = 1; i < 12; i++) {
Vec Center = { rect_сpos_x, rect_pos_y2 - 30 };
Vec OldPos = { sc_oldpos_x, sc_oldpos_y };
Vec NewPos = Rotate(Center, seg_angle/4, OldPos);
sc_oldpos_x = NewPos.x;
sc_oldpos_y = NewPos.y;
if (i == 1) {
point_x[1][0] = NewPos.x + 4;
point_y[1][0] = NewPos.y + 18;
color_pos_x[0] = point_x[0][0] + 18;
color_pos_y[0] = point_y[0][0];
}
color_pos_x[i] = NewPos.x;
color_pos_y[i] = NewPos.y;
}
sc_oldpos_x = point_x[0][0] + 18, sc_oldpos_y = point_y[0][0];
// тут буде перший тупий шестикутник
for (int i = 0; i < 5; i++) {
Vec Center = { point_x[1][0]-4, point_y[1][0]-18};
Vec OldPos = { point_x[1][i], point_y[1][i] };
Vec NewPos = Rotate(Center, seg_angle, OldPos);
point_x[1][i+1] = NewPos.x;
point_y[1][i+1] = NewPos.y;
}
//Розраховуємо 1 - й тупий шестикутник - КІНЕЦЬ
//Рзраховуємо і заносимо в масив координати вершин решти шестикутників - ПОЧАТОК
//це будуть шестикутники тупі
for (int i = 3; i < 12; i = i+2) {
for (int j = 0; j < 6; j++) {
Vec Center = { rect_сpos_x, rect_pos_y2 - 30 };
Vec OldPos = { point_x[i-2][j], point_y[i-2][j] };
Vec NewPos = Rotate(Center, seg_angle/2, OldPos);
point_x[i][j] = NewPos.x;
point_y[i][j] = NewPos.y;
}
}
//Рзраховуємо і заносимо в масив координати вершин решти шестикутників - КІНЕЦЬ
//Власне сама анімація.
Sleep(sleeptime);
int j = 0;
for (int i = 0; i < 12; i = i++) {
if (j == 7)
j = 0;
dcc. Sixtagon(point_x[i][0], point_y[i][0], point_x[i][1], point_y[i][1], point_x[i][2], point_y[i][2], point_x[i][3], point_y[i][3], point_x[i][4], point_y[i][4], point_x[i][5], point_y[i][5],RGB(0,0,0));
dcc. Flood (color_pos_x[i], color_pos_y[i], RGB(color_R[j],color_G[j],color_B[j]));
j++;
Sleep(sleeptime);
dcc.unFlood (color_pos_x[i], color_pos_y[i]);
dcc. Sixtagon(point_x[i][0], point_y[i][0], point_x[i][1], point_y[i][1], point_x[i][2], point_y[i][2], point_x[i][3], point_y[i][3], point_x[i][4], point_y[i][4], point_x[i][5], point_y[i][5],RGB(255,255,255));
//В звязку з тим, при побудові зображень використовується тип даних integer,
//виникають втрати даних, і зображення шестикутника спотворює арку.
// Видалення старої підкови - ПОЧАТОК
dcc.unFlood (rect_сpos_x, rect_сpos_y);
hPen = CreatePen(PS_SOLID, 2, RGB(255, 255, 255));
hOldPen = SelectObject(dcc, hPen);
dcc.MoveTo (rect_сpos_x + R_small, rect_pos_y2 - 30);
dcc.AngleArc (rect_сpos_x, rect_pos_y2 - 30, R, 0, 180);
dcc.MoveTo (