ЛР. ИДБ-20-08_Вихров_ЛР5_Отчет. Отчет по дисциплине Компьютерная геометрия и графика по лабораторной работе 5
Скачать 285.57 Kb.
|
МИНОБРНАУКИ РОССИИ федеральное государственное бюджетное образовательное учреждение высшего образования «Московский государственный технологический университет «СТАНКИН» (ФГБОУ ВО «МГТУ «СТАНКИН»)
Основная образовательная программа 09.03.02 «Информационные системы и технологии» Отчет по дисциплине «Компьютерная геометрия и графика» по лабораторной работе № 5
Москва, 2021 г. ОГЛАВЛЕНИЕВВЕДЕНИЕВ данной лабораторной работе будут изучены аспекты вращением объемных фигур. Будут использованы функции, классы. Также подробно предстоит рассмотреть принципы построения сплайнов, виды сплайнов. ОСНОВНАЯ РАБОТАКод “Вращающийся куб”.LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_COMMAND: { int wmId = LOWORD(wParam); // Parse the menu selections: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } } break; POINT point1[4]; HDC hdc; int sx, sy, xPos, yPos, zDelta; 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; // wheel rotation 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; } // A = yt[0] * (zt[1] - zt[2]) - yt[1] * (zt[0] - zt[2]) + yt[2] * (zt[0] - zt[1]); B = -(xt[0] * (zt[1] - zt[2]) - xt[1] * (zt[0] - zt[2]) + xt[2] * (zt[0] - zt[1])); C = xt[0] * (yt[1] - yt[2]) - xt[1] * (yt[0] - yt[2]) + xt[2] * (yt[0] - yt[1]); 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; } case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } Результат работы программы отображается на рисунке 1: Рис.1 “Вращающийся куб” Код “Кривая Безье”LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static HPEN hDash, hBezier; // два пера static HBRUSH hRect, hSel; // две кисти static POINT pt[20]; // массив хранения плоских точек static POINT point; // структура под одну плоскую точку RECT rt; // структура точек прямоугольника static int count = 0, index = 0; // счётчик точек, static bool capture = 0; // логическая переменная для мыши int i; HDC hdc; PAINTSTRUCT ps; ifstream in; //класс файлового потокового ввода-вывода ofstream out; switch (message) { case WM_COMMAND: { int wmId = LOWORD(wParam); // Parse the menu selections: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } } 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; } // пока запоняется координата x - заполняем y // в переменной count накапливается размер массива точек 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) { ReleaseCapture(); //Освобождение мыши capture = false; } break; case WM_MOUSEMOVE: if (capture) { //Мышь захвачена point.x = LOWORD(lParam); point.y = HIWORD(lParam); DcInLp(point); //Преобразование экранных координат мыши pt[index] = point; // в логические координаты InvalidateRect(hWnd, NULL, TRUE); } break; 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; 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(); default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } Результат работы программы отображается на рисунке 2: Рис 2. “Кривая Безье” Код “Кривая Безье(функция)”void PolySplayn(HDC hdc, POINT pt[], int count) { float a0, a1, a2, a3, b0, b1, b2, b3, t,first = -1; int 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; b3 = (-pt[i - 1].y + 3 * (pt[i].y - pt[i + 1].y) + pt[i + 2].y) / 6; a2 = (pt[i - 1].x - 2 * pt[i].x + pt[i + 1].x) / 2; b2 = (pt[i - 1].y - 2 * pt[i].y + pt[i + 1].y) / 2; a1 = (pt[i + 1].x - pt[i - 1].x) / 2; b1 = (pt[i + 1].y - pt[i - 1].y) / 2; a0 = (pt[i - 1].x + 4 * pt[i].x + pt[i + 1].x) / 6; b0 = (pt[i - 1].y + 4 * pt[i].y + pt[i + 1].y) / 6; 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); } } } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static HPEN hDash, hBezier; // два пера static HBRUSH hRect, hSel; // две кисти static POINT pt[20]; // массив хранения плоских точек static POINT point; // структура под одну плоскую точку RECT rt; // структура точек прямоугольника static int count = 0, index = 0; // счётчик точек, static bool capture = 0; // логическая переменная для мыши int i; HDC hdc; PAINTSTRUCT ps; ifstream in; //класс файлового потокового ввода-вывода ofstream out; switch (message) { case WM_COMMAND: { int wmId = LOWORD(wParam); // Parse the menu selections: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } } 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; } // пока запоняется координата x - заполняем y // в переменной count накапливается размер массива точек 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) { ReleaseCapture(); //Освобождение мыши capture = false; } break; case WM_MOUSEMOVE: if (capture) { //Мышь захвачена point.x = LOWORD(lParam); point.y = HIWORD(lParam); DcInLp(point); //Преобразование экранных координат мыши pt[index] = point; // в логические координаты InvalidateRect(hWnd, NULL, TRUE); } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); transform(hdc); //Переход в логические координаты SelectObject(hdc, hDash); Polyline(hdc, pt, count); //Строим ломанную линию SelectObject(hdc, hBezier); PolySplayn(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: 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(); default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } Результат работы программы отображается на рисунке 3: Рис 3. “Безье функция” ЗАКЛЮЧЕНИЕВ ходе выполнения данной лабораторной работы были выполнены все поставленные задачи. Подробно рассмотрены вопросы вращение объемных фигур, использования функций, использования классов. Рассмотрены также принципы построения сплайнов, виды сплайнов. |