Файл: Геометрическое моделирование и компьютерная графика.docx

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 09.11.2023

Просмотров: 37

Скачиваний: 3

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.


МИНОБРНАУКИ РОССИИ


федеральное государственное бюджетное образовательное учреждение высшего образования

«Московский государственный технологический университет


«СТАНКИН»

(ФГБОУ ВО «МГТУ «СТАНКИН»)







Кафедра инженерной графики

Лабораторная работа 5


По дисциплине

«Геометрическое моделирование и компьютерная графика»


Выполнил студент группы ИДБ-20-11: Зарубежнов Б.П.

Проверил: к.т.н., доцент, Разумовский А.И.
Москва 2023 г.

ВВЕДЕНИЕ


На данной лабораторной работе мы будем рассматривать вращение объемных фигур, используемые функции и классы, а также принципы построения сплайнов и виды сплайнов.

ХОД РАБОТЫ




Задание 1. Изображение вращающегося куба. Написан код для изображения вращающегося при помощи мыши куба с удаленными гранями и закраской


Код программы:


const int WIDTH = 400; const int HEIGHT = 300;

float v11, v12, v13, v21, v22, v23, v31, v32, v33, v43; float rho = 300., thetta = 75., phi = 30., ScreenDist = 500.; float A, B, C, D, An, Bn, Cn;

float xt[3], yt[3], zt[3]; float Al, Bl, Cl;

float alpha;

float th, ph, costh, cosph, sinth, sinph; float factor = atan(1.0) / 45.; PAINTSTRUCT ps;

static HBRUSH hBrush;
class TFPoint

{

public:

float X; oat Y; float Z;

};

TFPoint CubePoints[] =

{

{-50,-50, -50},

{ 50,-50, -50},

{ 50, 50, -50},

{-50, 50, -50},

{-50, 50, 50},

{-50,-50, 50},

{ 50,-50, 50},

{ 50, 50, 50}

};

int Gran[6][4] =

{

{0,3,4,5},

{0,5,6,1},

{2,7,4,3},

{7,6,5,4},

{0,1,2,3},

{2,1,6,7}

};

void VidMatCoeff(float rho, float thetta, float phi)
{

th = thetta * factor; ph = phi * factor;

costh = cos(th); sinth = sin(th); cosph = cos(ph); sinph = sin(ph); v11 = -sinth; v12 = -cosph * costh; v13 = -sinph * costh;

v21 = costh; v22 = -cosph * sinth; v23 = -sinph * sinth; v31 = 0.; v32 = sinph; v33 = -cosph;

v43 = rho;

}

POINT Perspective(float x, float y, float z)

{

POINT point; float xe, ye, ze;

VidMatCoe(rho, thetta, phi); xe = v11 * x + v21 * y;

ye = v12 * x + v22 * y + v32 * z;

ze = v13 * x + v23 * y + v33 * z + v43; point.x = ScreenDist * xe / ze + 700.; point.y = ScreenDist * ye / ze + 400.; return point;

}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

POINT point1[4]; HDC hdc;

int sx, sy, xPos, yPos, zDelta; switch (message)

{

case WM_DESTROY: PostQuitMessage(0);

break;

case WM_MOUSEMOVE:

sx = LOWORD(lParam); sy = HIWORD(lParam);

thetta += ((sx % 180) - 90) / 10;

phi += ((sy % 180) - 90) / 10;

InvalidateRect(hWnd, NULL, TRUE); break;

case WM_MOUSEWHEEL:

zDelta = (int)wParam; ScreenDist -= zDelta / 1000000.;
InvalidateRect(hWnd, NULL, TRUE);

break;

case WM_PAINT:

hdc = BeginPaint(hWnd, &ps);

th = thetta * factor;

ph = phi * factor;

costh = cos(th); sinth = sin(th); cosph = cos(ph); sinph = sin(ph); A = rho * sinph * costh; B = rho * sinph * sinth; C = rho * cosph; Al = A / (sqrt(A * A + B * B + C * C));

Bl = B / (sqrt(A * A + B * B + C * C)); Cl = C / (sqrt(A * A + B * B + C * C)); for (int i = 0; i < 6; i++)

{

for (int j = 0; j < 3; j++)

{

xt[j] = CubePoints[Gran[i][j]].X;

yt[j] = CubePoints[Gran[i][j]].Y;

zt[j] = CubePoints[Gran[i][j]].Z;

}


- zt[1]);
(zt[0] - zt[1]));
- yt[1]);

A = yt[0] * (zt[1] - zt[2]) - yt[1] * (zt[0] - zt[2]) + yt[2] * (zt[0]
B = -(xt[0] * (zt[1] - zt[2]) - xt[1] * (zt[0] - zt[2]) + xt[2] *

C = xt[0] * (yt[1] - yt[2]) - xt[1] * (yt[0] - yt[2]) + xt[2] * (yt[0] An = A / (sqrt(A * A + B * B + C * C));

Bn = B / (sqrt(A * A + B * B + C * C)); Cn = C / (sqrt(A * A + B * B + C * C));
alpha = (An * Al + Bn * Bl + Cn * Cl); for (int j = 0; j < 4; j++)

{

point1[j] = Perspective(CubePoints[Gran[i][j]].X, CubePoints[Gran[i][j]].Y,

CubePoints[Gran[i][j]].Z);

}

D = point1[0].x * (point1[1].y - point1[2].y) -

point1[1].x * (point1[0].y - point1[2].y) +

point1[2].x * (point1[0].y - point1[1].y); if (D < 0)

{

hBrush = CreateSolidBrush(RGB((1 - alpha) * 255, (1 - alpha) * 255, (1
- alpha) * 255));

SelectObject(hdc, hBrush); Polygon(hdc, point1, 4);

}

}

EndPaint(hWnd, &ps);
break;

default:

return DefWindowProc(hWnd, message, wParam, lParam);

}

return 0;

}


Результат работы программы:






Рис.1-вращающийсякуб

Задание 2. Приложение «Кривая Безье». Написан код приложения «Кривая Безье»

Код программы:


#include #include

#dene _USE_MATH_DEFINES #include

#include

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

TCHAR WinName[] = _T("MainFrame");

int APIENTRY WinMain(HINSTANCE This, HINSTANCE Prev, LPSTR cmd, int

mode)

{

HWND hWnd; MSG msg; WNDCLASS wc;

wc.hInstance = This; wc.lpszClassName = WinName; wc.lpfnWndProc = WndProc;

wc.style = CS_HREDRAW | CS_VREDRAW; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.lpszMenuName = NULL;

wc.cbClsExtra = 0;

wc.cbWndExtra = 0;

wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); if (!RegisterClass(&wc)) return 0;

hWnd = CreateWindow(WinName, _T("Каркас Windows-приложения"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,

CW_USEDEFAULT,

CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, NULL, This,

NULL);

ShowWindow(hWnd, mode);

while (GetMessage(&msg, NULL, 0, 0))

{

TranslateMessage(&msg); DispatchMessage(&msg);

}
return 0;

}

static int sx, sy;

const int SCALE = 1000; const int MARK = 4;

void DcInLp(POINT& point)

{

point.x = point.x * SCALE / sx;

point.y = SCALE - point.y * SCALE / sy;

}

void transform(HDC& hdc)

{

SetMapMode(hdc, MM_ANISOTROPIC); SetWindowExtEx(hdc, SCALE, -SCALE, NULL); SetViewportExtEx(hdc, sx, sy, NULL); SetViewportOrgEx(hdc, 0, sy, NULL);

}

PAINTSTRUCT ps;

static HPEN hDash, hBezier; static HBRUSH hRect, hSel; static POINT pt[20];

static POINT point; RECT rt;

static int count, index; static bool capture;

int i; std::ifstream in; std::ofstream out;

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

HDC hdc;

switch (message)

{

case WM_DESTROY: DeleteObject(hDash); DeleteObject(hBezier); DeleteObject(hRect); DeleteObject(hSel); out.open("dat.txt");

for (i = 0; i < count; i++) out << pt[i].x << '\t' << pt[i].y <<

'\n'; out.close();
break; case WM_CREATE:

in.open("dat.txt");

if (in.fail())

{

MessageBox(hWnd, _T("Файл dat.txt не найден"),

_T("Открытие файла"), MB_OK | MB_ICONEXCLAMATION);

PostQuitMessage(0); return 1;

}

for (count = 0; in >> pt[count].x; count++) in >> pt[count].y; in.close();

hDash = CreatePen(PS_DASH, 1, 0);

hBezier = CreatePen(PS_SOLID, 4, RGB(0, 0,

255)); hRect = CreateSolidBrush(RGB(128, 0, 128));

hSel = CreateSolidBrush(RGB(255, 0, 0)); break;

case WM_SIZE:

sx = LOWORD(lParam); sy = HIWORD(lParam); break;

case WM_LBUTTONDOWN:

point.x = LOWORD(lParam); point.y = HIWORD(lParam); DcInLp(point);

for (i = 0; i <= count; i++)

{

SetRect(&rt, pt[i].x - MARK, pt[i].y -

MARK, pt[i].x + MARK, pt[i].y + MARK);

if (PtInRect(&rt, point))

{

index = i; capture = true;

hdc = GetDC(hWnd); transform(hdc); FillRect(hdc, &rt, hSel); ReleaseDC(hWnd, hdc); SetCapture(hWnd); return 0;

}

}

break;

case WM_LBUTTONUP:
if (capture)

{



}

break;

ReleaseCapture(); capture = false;

case WM_MOUSEMOVE:

if (capture)

{


}

break;

point.x = LOWORD(lParam); point.y = HIWORD(lParam); DcInLp(point);

pt[index] = point; InvalidateRect(hWnd, NULL, TRUE);

case WM_PAINT:

hdc = BeginPaint(hWnd, &ps); transform(hdc); SelectObject(hdc, hDash); Polyline(hdc, pt, count); SelectObject(hdc, hBezier); PolyBezier(hdc, pt, count);

for (i = 0; i < count; i++)

{

SetRect(&rt, pt[i].x - MARK, pt[i].y - MARK,

pt[i].x + MARK, pt[i].y + MARK);

FillRect(hdc, &rt, hRect);

}

break; default:

return DefWindowProc(hWnd, message, wParam, lParam);

}

return 0;

}


Результат работы программы:







Рис.2-криваяБезье

Задание 3. Построение кривой B-сплайна.

Написан код для построения кривой B-сплайна


Код программы:


#include #include

#dene _USE_MATH_DEFINES #include

#include

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

TCHAR WinName[] = _T("MainFrame");

int APIENTRY WinMain(HINSTANCE This, HINSTANCE Prev, LPSTR cmd, int

mode)

{

HWND hWnd; MSG msg; WNDCLASS wc;

wc.hInstance = This; wc.lpszClassName = WinName;

wc.lpfnWndProc = WndProc;

wc.style = CS_HREDRAW | CS_VREDRAW; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.lpszMenuName = NULL;

wc.cbClsExtra = 0;

wc.cbWndExtra = 0;

wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); if (!RegisterClass(&wc)) return 0;

hWnd = CreateWindow(WinName, _T("Каркас Windows-приложения"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,

CW_USEDEFAULT,

CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, NULL, This,

NULL);

ShowWindow(hWnd, mode);

while (GetMessage(&msg, NULL, 0, 0))

{

TranslateMessage(&msg); DispatchMessage(&msg);

}

return 0;

}

const int WIDTH = 400; const int HEIGHT = 300;

float v11, v12, v13, v21, v22, v23, v31, v32, v33, v43; float rho = 300., thetta = 75., phi = 30., ScreenDist = 500.; float A, B, C, D, An, Bn, Cn;

float xt[3], yt[3], zt[3]; float Al, Bl, Cl; float alpha;

float th, ph, costh, cosph, sinth, sinph; float factor = atan(1.0) / 45.; static int sx, sy;

const int SCALE = 1000; //размер логического окна

const int MARK = 4; //размер прямоугольного маркера точек

void DcInLp(POINT& point)

{

point.x = point.x * SCALE / sx;

point.y = SCALE - point.y * SCALE / sy;

}

void transform(HDC& hdc)

{

SetMapMode(hdc, MM_ANISOTROPIC);

SetWindowExtEx(hdc, SCALE, -SCALE, NULL);
SetViewportExtEx(hdc, sx, sy, NULL); SetViewportOrgEx(hdc, 0, sy, NULL);

}

void PolyBSplayn(HDC hdc, POINT pt[], int count)

{

float a0, a1, a2, a3, b0, b1, b2, b3, t; int first = -1, X, Y, eps = 20;

for (int i = 1; i <= count - 1; i++) {

MoveToEx(hdc, pt[i].x - eps, pt[i].y - eps, NULL);

LineTo(hdc, pt[i].x + eps, pt[i].y + eps); MoveToEx(hdc, pt[i].x + eps, pt[i].y + eps, NULL); LineTo(hdc, pt[i].x - eps, pt[i].y - eps);

}

for (int i = 1; i <= count - 2; i++)

{

a3 = (-pt[i - 1].x + 3 * (pt[i].x - pt[i + 1].x) + pt[i + 2].x) / 6.0;

b3 = (-pt[i - 1].y + 3 * (pt[i].y - pt[i + 1].y) + pt[i + 2].y) / 6.0;

a2 = (pt[i - 1].x - 2 * pt[i].x + pt[i + 1].x) / 2.0;

b2 = (pt[i - 1].y - 2 * pt[i].y + pt[i + 1].y) / 2.0;

a1 = (pt[i + 1].x - pt[i - 1].x) / 2.0;

b1 = (pt[i + 1].y - pt[i - 1].y) / 2.0;

a0 = (pt[i - 1].x + 4 * pt[i].x + pt[i + 1].x) / 6.0;

b0 = (pt[i - 1].y + 4 * pt[i].y + pt[i + 1].y) / 6.0; for (int j = 0; j <= 30; j++)

{

t = (float)j / 30.;

X = ((a3 * t + a2) * t + a1) * t + a0; Y = ((b3 * t + b2) * t + b1) * t + b0; if (first)

{

first = 0; MoveToEx(hdc, X, Y, NULL);

}

else LineTo(hdc, X, Y);

}

}

}

static HPEN hDash, hBezier; static HBRUSH hRect, hSel; static POINT pt[20];

static POINT point; RECT rt;

static int count, index; static bool capture;

int i; std::ifstream in; std::ofstream out;

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

PAINTSTRUCT ps;

HDC hdc;

switch (message)

{

case WM_CREATE:

in.open("dat.txt");

if (in.fail())

{

MessageBox(hWnd, _T("Файл dat.txt не найден"),

_T("Открытие файла"), MB_OK | MB_ICONEXCLAMATION);

PostQuitMessage(0); return 1;

}

for (count = 0; in >> pt[count].x; count++) in >> pt[count].y;

in.close();

hDash = CreatePen(PS_DASH, 1, 0);

hBezier = CreatePen(PS_SOLID, 4, RGB(0, 0, 255));

hRect = CreateSolidBrush(RGB(128, 0, 128));

hSel = CreateSolidBrush(RGB(255, 0, 0)); break;

case WM_SIZE:

sx = LOWORD(lParam); sy = HIWORD(lParam); break;

case WM_LBUTTONDOWN:

point.x = LOWORD(lParam); point.y = HIWORD(lParam);
DcInLp(point);

for (i = 0; i <= count; i++)

{
SetRect(&rt, pt[i].x - MARK, pt[i].y - MARK, pt[i].x +

MARK,

pt[i].y + MARK);

if (PtInRect(&rt, point))

{

}

}

break;

index = i; capture = true;

hdc = GetDC(hWnd); transform(hdc); FillRect(hdc, &rt, hSel);

ReleaseDC(hWnd, hdc); SetCapture(hWnd);

return 0;

case WM_LBUTTONUP:

if (capture)

{



}

break;

ReleaseCapture(); capture = false;

case WM_MOUSEMOVE:

if (capture)

{


}

break;

point.x = LOWORD(lParam); point.y = HIWORD(lParam); DcInLp(point);

pt[index] = point; InvalidateRect(hWnd, NULL, TRUE);

case WM_PAINT:

hdc = BeginPaint(hWnd, &ps); transform(hdc); SelectObject(hdc, hDash); Polyline(hdc, pt, count); SelectObject(hdc, hBezier); PolyBSplayn(hdc, pt, count); for (i = 0; i < count; i++)

{

SetRect(&rt, pt[i].x - MARK, pt[i].y - MARK, pt[i].x + MARK, pt[i].y + MARK);

FillRect(hdc, &rt, hRect);

}

break;

case WM_DESTROY: PostQuitMessage(0); DeleteObject(hDash); DeleteObject(hBezier); DeleteObject(hRect); DeleteObject(hSel); out.open("dat.txt");

for (i = 0; i < count; i++) out << pt[i].x << '\t' << pt[i].y << '\n'; out.close();

PostQuitMessage(0); break;

default: return DefWindowProc(hWnd, message, wParam, lParam);

}

return 0;

}
Результат работы программы:





ВЫВОД


Рис.3-криваяB-сплайна


Сегодня мы рассмотрели вращение объемных фигур, построение сплайнов, виды сплайнов. Изобразили вращающийся при помощи мыши куб с удалёнными гранями и закраской, «Кривая Безье». По примеру кода «Безье» адаптировали код программы, написанной в MS-DOS для построения В-сплайна.