Міністерство освіти і науки України
Національний університет “Львівська політехніка”
Звіт
до розрахунково-графічної роботи
з курсу “Програмування комп’ютерної графіки”
1.1 Завдання
Варіант 15-15-11
Побудувати графік функції
заданої таблично. Графік має відображати результати розрахунків, які записані у файлі на диску, а масштаб розмітки осей координат графіка – реальним результатам розрахунків. Параметри для побудови графіка:
№ варіанта
Тип лінії для побудови осей графіка
Товщина лінії
(пікселів)
15
_.._.._.._.._
5
Необхідно передбачити “плаваючий” центр координат, – основну частину екрану мають займати ті чверті, в яких знаходиться графік функції.
Структура зображення
Пояснення
/
Плавне обертання квадрата зі спицями в кожній вершині навколо власного центру проти годинникової стрілки. Спиці кіл обертаються навколо центрів кіл. Напрямки обертання спиць кіл однієї діагоналі квадрата та іншої різні. Кольори квадрата і кіл зі спицями різні.
Параметри: d=25, A=120.
1.2 Розрахунок функціональних залежностей для побудови графіка.
Оскільки реальні координати графіка функції, що виводиться на екран можуть бути або значно більшими, або значно меншими за машинні координати екрану монітору, необхідно визначити значення масштабних коефіцієнтів стискання або розтягу для функції, що виводиться на екран.
Позначимо максимальні та мінімальні значення реальних координат по осях X та Y - mахx, minx, maxy, miny.
Приймаємо машинний робочий діапазон для графіка функції 540 пікселів по осі X та 400 пікселів по осі Y. Тоді масштабні коефіцієнти для графіка по осях X та Y дорівнюють, відповідно:
При виведенні графіка функції на екран монітору значення реальних координат заданої функції домножуємо на масштабні коефіцієнти і додаємо координати машинного центру координат (X0,Y0):
2.1. Завдання.
Створити на екрані комп’ютера графічне вікно і сформувати в ньому рухоме зображення.
Параметри зображення задані в пікселах. Графік і вікно з рухомим зображенням повинні бути присутні на екрані одночасно.
2.2 Розрахунок матриці перетворень для рухомого зображення.
Результуюча матриця М, руху є добутком трьох матриць: переносу T1, T2 і повороту R, причому перша матриця відповідає перенесенню центру повороту в початок координат на відстань -dx та -dy, друга – повороту об’єкта на кут φ, третя – поверненню об’єкта з початку координат на площину зображення (координати dx та dy).
Перемноживши матрицю-рядок із старими координатами на результуючу матрицю руху, одержимо матрицю з новими координатами рухомої точки.
3. Список ідентифікаторів програми.
y- поточне значення функції
dXmash,dXreal,dYmash,dYreal, Kx,Ky масштабні коефіцієнти
a –початок відрізку табуляції
b- кінець відрізку табуляції
h– крок зміни реального значення аргументу;
Ymax, Ymin - максимальне та мінімальне реальні значення аргументу;
4. Блок-схеми основної програми побудови графіка та анімації.
4.1. Блок-схема графіка
1
2
3
4
5
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
4.2. Блок-схема анімації
1
2
5. Текст програми.
Файл: ChildView.cpp
// ChildView.cpp : реализация класса CChildView
//
#include "stdafx.h"
#include "ChildView.h"
#include "Math.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CChildView
CChildView::CChildView()
{
}
CChildView::~CChildView()
{
}
BEGIN_MESSAGE_MAP(CChildView, CWnd)
ON_WM_PAINT()
END_MESSAGE_MAP()
// обработчики сообщений CChildView
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 ToRadian(double);
class Vector2
{
public:
double X;
double Y;
Vector2(double x, double y)
{
X = x;
Y = y;
}
Vector2(int a)
{
X=a;
Y=a;
}
Vector2()
{
X=0;
Y=0;
}
friend Vector2& operator+(const double&, const Vector2&);
friend Vector2& operator+(const Vector2&, const Vector2&);
};
Vector2& operator+(const double& value, const Vector2& vec)
{
return Vector2(vec.X + value, vec.Y + value);
}
Vector2& operator+(const Vector2& vec1, const Vector2& vec2)
{
return Vector2(vec1.X + vec2.X, vec1.Y + vec2.Y);
}
class Matrix
{
public:
static Vector2 CreateRotation(Vector2 position, double angle, bool rotateLeft)
{
position.X /= sqrt(2.0);
position.Y /= sqrt(2.0);
double matrix[4];
matrix[0] = cos(angle);
matrix[1] = rotateLeft ? -sin(angle) : sin(angle);
matrix[2] = rotateLeft ? sin(angle) : -sin(angle);
matrix[3] = cos(angle);
return Vector2(position.X * matrix[0] + position.Y * matrix[1], position.X * matrix[2] + position.Y * matrix[3]);
}
};
const double PI = 3.1415;
const double kx = 10, ky = 0.008;
const int Cx = 350, Cy = 350;
const double r = 25.0/2.0;
double ToRadian(double x)
{
return (x * PI) / 180;
}
class Wheel
{
public:
Vector2 Center;
Vector2 needle[4];
int D;
Wheel(Vector2 center)
{
Center = center;
}
Vector2* NeedleRotation(double angle, bool left)
{
angle*=2;
needle[0] = Center + Matrix::CreateRotation(Vector2(r), angle, left);
needle[1] = Center + Matrix::CreateRotation(Vector2(r), angle + ToRadian(180), left);
needle[2] = Center + Matrix::CreateRotation(Vector2(r), angle + ToRadian(90), left);
needle[3] = Center + Matrix::CreateRotation(Vector2(r), angle + ToRadian(270), left);
return needle;
}
};
double F(double x){ return sqrt(x)+25; } //функція
void CChildView::OnPaint()
{
CPaintDC dc(this);
int Xmashn,Ymashn,Xo,Yo,VXL,VXR,VYB,VYT;
double y,Kx,Ky,dXmash,dXreal,dYmash,dYreal,a,b,h,Ymax,Ymin;
VXL=VXR=VYB=VYT=70;
a=0;
b=45000;
h=2000;
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;
}
RECT rect;
GetClientRect (&rect);
dXreal=b-a;dXmash=rect.right-rect.left;
dYreal=Ymax-Ymin;dYmash=rect.bottom-rect.top;
Ky=(dYmash-VXL-VXR)/dYreal;Kx=(dXmash-VYB-VYT)/dXreal;
Xo=VXL-Kx*a;
Yo=VYT+Ky*Ymax;
int Xo1=Xo,Yo1=Yo;
if(Xo1<VXL)Xo1=VXL;if(Xo1>rect.right-VXR)Xo1=rect.right-VXR;
if(Yo1<VYT)Yo1=VYT;if(Yo1>rect.bottom-VYB)Yo1=rect.bottom-VYB;
// Osi kokrdinat pochatok
dc.MoveTo(Xo1,Yo1);
dc.LineTo(Xo1,VYT-25);
dc.MoveTo(Xo1-5,VYT);
dc.LineTo(Xo1,VYT-25);
dc.MoveTo(Xo1+5,VYT);
dc.LineTo(Xo1,VYT-25);
const CString Y("Y");
dc.TextOutW(Xo1-15,VYT-25, Y);
dc.MoveTo(Xo1,Yo1);
dc.LineTo(Xo1,rect.bottom-VYB);
dc.MoveTo(Xo1,Yo1);
dc.LineTo(VXL,Yo1);
dc.MoveTo(Xo1,Yo1);
dc.LineTo(rect.right-VXR+25,Yo1);
dc.MoveTo(rect.right-VXR,Yo1-5);
dc.LineTo(rect.right-VXR+25,Yo1);
dc.MoveTo(rect.right-VXR,Yo1+5);
dc.LineTo(rect.right-VXR+25,Yo1);
const CString X("X");
dc.TextOutW(rect.right-VXR-15+25,Yo1-25, X);
const CString O("O");
if (Xo1<=VXL||Xo1>=rect.right-VXR||Yo1<=VYT||Yo1>=rect.bottom-VYB);
else dc.TextOutW(Xo1-15,Yo1+5, O);
/////////a i b////////
double d=b;
char str[20];
sprintf_s (str,20,"%5.4lf",d);
CString ss(str);
dc.TextOutW(Xo+d*Kx-10,Yo1+5,ss);
dc.MoveTo(Xo+b*Kx,Yo1-2);
dc.LineTo(Xo+b*Kx,Yo1+2);
double H=(b-a)/8;
d=a;
int w=b/5;
for(int i=0;i<8;i++)
{
sprintf_s(str,20,"%3.4lf",d);
CString A(str);
dc.TextOut(Xo+d*Kx+2,Yo1+5,A);
dc.MoveTo(Xo+d*Kx,Yo1-2);
dc.LineTo(Xo+d*Kx,Yo1+2);
d+=H;
}
////////a i b kinets/////////
////////Ymax i Ymin///////////
d=Ymax;
sprintf_s (str,20,"%5.2lf",d);
CString ssss(str);
dc.TextOutW(Xo1-65,Yo-Ymax*Ky,ssss);
dc.MoveTo(Xo1-2,Yo-Ymin*Ky);
dc.LineTo(Xo1+2,Yo-Ymin*Ky);
H=(Ymax-Ymin)/5;
d=Ymin;
for(int i=0;i<5;i++)
{
sprintf_s(str,20,"%3.2lf",d);
CString A(str);
dc.TextOut(Xo1-65,Yo-d*Ky-5,A);
dc.MoveTo(Xo1-2,Yo-d*Ky);
dc.LineTo(Xo1+2,Yo-d*Ky);
d+=H;
}
////////Ymax i Ymin kinetc///////////
////////Osi koordinat kinetc/////////
//CPen one;
//one.CreatePen(PS_DOT,1,RGB(0,0,200));
//dc.SelectObject(&one);
CRect rc;
GetClientRect(rc);
int width = 5; // задає товщину ліній функції
LOGBRUSH logBrush;
logBrush.lbStyle = BS_SOLID;
logBrush.lbColor = RGB(255, 0, 0);
CPen pen1(PS_DASHDOTDOT|PS_GEOMETRIC|PS_ENDCAP_ROUND, width,&logBrush);
CPen *pPrevPen = dc.SelectObject(&pen1);
dc.MoveTo(Xo+a*Kx,Yo-Ky*F(a));
dc.LineTo(Xo+a*Kx,Yo-Ky*F(a));
for(double x=a;x<b;x=x+h)
{
Xmashn=Xo+x*Kx;
y=F(x);
Ymashn=Yo-y*Ky;
dc.LineTo(Xmashn,Ymashn);
}
// one.DeleteObject();
CPen pen(PS_SOLID,1,RGB(0,0,0));
dc.SelectObject(&pen);
//-------------------------
///////////////////ANIM////////////////////////////////////////////////////////////////////////
Wheel wheel[4] = {Wheel(Vector2(700, 100)), Wheel(Vector2(700, 100)), Wheel(Vector2(700, 100)), Wheel(Vector2(700, 100))};
int phi = 0;
double impuls = 0, velocity = 0;
bool jump = false;
Vector2 linePosition;
double angle = ToRadian(45);
bool left = false;
int A = 120;
Vector2 verts[4] = { Vector2(700, 150), Vector2(700 + A, 150), Vector2(700 + A, 150 + A), Vector2(700, 150 + A)};
while(true)
{
for(int i=0; i<2; i++)
{
if(i==0)
{
dc.SelectStockObject(BLACK_PEN);
}
else
{
dc.SelectStockObject(WHITE_PEN);
}
double teta = ToRadian(5);
CPen greenPen;
greenPen.CreatePen(PS_SOLID, 1, RGB(255,0,0));//колір кіл зі спицями
verts[0] = Vector2(700 + A/2.0, 150 + A/2.0) + Matrix::CreateRotation(Vector2(A/2 * sqrt(2.0)), ToRadian(-phi), true);
verts[1] = Vector2(700 + A/2.0, 150 + A/2.0) + Matrix::CreateRotation(Vector2(A/2 * sqrt(2.0)), ToRadian((-phi + 90)), true);
verts[2] = Vector2(700 + A/2.0, 150 + A/2.0) + Matrix::CreateRotation(Vector2(A/2 * sqrt(2.0)), ToRadian((-phi + 180)), true);
verts[3] = Vector2(700 + A/2.0, 150 + A/2.0) + Matrix::CreateRotation(Vector2(A/2 * sqrt(2.0)), ToRadian((-phi + 270)), true);
for(int j=0; j<4; j++)
wheel[j].Center = verts[j];
dc.MoveTo(verts[0].X, verts[0].Y);
for(int j = 3; j>=0; j--)
dc.LineTo(verts[j].X, verts[j].Y);
if(i==0)
{
dc.SelectObject(greenPen);
}
for(int j = 0; j<4; j++)
{
dc.MoveTo(wheel[j].Center.X + r, wheel[j].Center.Y);
dc.AngleArc(wheel[j].Center.X, wheel[j].Center.Y, r, 0, 360);
}
for(int j=0; j<4; j++)
{
wheel[j].NeedleRotation(ToRadian(phi), j%2==0 ? true : false);
dc.MoveTo(wheel[j].needle[0].X, wheel[j].needle[0].Y);
dc.LineTo(wheel[j].needle[1].X, wheel[j].needle[1].Y);
dc.MoveTo(wheel[j].needle[2].X, wheel[j].needle[2].Y);
dc.LineTo(wheel[j].needle[3].X, wheel[j].needle[3].Y);
}
if(i==0)
{
Sleep(65);
}
else
{
phi += 5;
phi %= 360;
angle += teta;
}
}
}
}
6. Результат виконання програми
/
Висновок.
В даній розрахунковій роботі розроблено алгоритми та написана програма мовою C++, що виводить на екран монітору графік функції.
Програма визначається універсальністю для побудови графіка функції в будь-якій чверті системи координат за рахунок використання «плаваючого» початку координат.
Також в цій розрахунковій роботі розроблено алгоритми та написана програма мовою C++, що виводить на екран монітору рухоме зображення.