Файл: Геометрическое моделирование и компьютерная графика.docx
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 09.11.2023
Просмотров: 234
Скачиваний: 5
МИНОБРНАУКИ РОССИИ
федеральное государственное бюджетное образовательное учреждение высшего образования
«Московский государственный технологический университет
«СТАНКИН»
(ФГБОУ ВО «МГТУ «СТАНКИН»)
Кафедра инженерной графики
Лабораторная работа 5
По дисциплине
«Геометрическое моделирование и компьютерная графика»
Выполнил студент группы ИДБ-20-11: Зарубежнов Б.П.
Проверил: к.т.н., доцент, Разумовский А.И.
Москва – 2023 г.
ВВЕДЕНИЕ
Наданнойлабораторнойработемыбудемрассматриватьвращениеобъемныхфигур, используемые функции и классы, а также принципы построениясплайновивидысплайнов.ХОД РАБОТЫ
Задание1.Изображениевращающегосякуба.НаписанкоддляизображениявращающегосяприпомощимышикубасудаленнымигранямиизакраскойКод программы:
const int WIDTH = 400;constintHEIGHT=300;float v11, v12, v13, v21, v22, v23, v31, v32, v33, v43;floatrho=300.,thetta=75.,phi=30.,ScreenDist=500.;floatA,B,C,D,An,Bn,Cn;floatxt[3],yt[3],zt[3];floatAl,Bl,Cl;floatalpha;floatth,ph,costh,cosph,sinth,sinph;float factor = atan(1.0) / 45.;PAINTSTRUCTps;staticHBRUSHhBrush;class TFPoint
{
public:
float X; float 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;
VidMatCoeff(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(inti=0;i<6;i++){for(intj=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++)
- 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#define _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
#define _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 для построения В-сплайна.