计算机图形学实验(一) 直线+圆
实验一:直线与画圆算法
实验目的:
掌握画线画圆原理,理解几何数据如何经过一系列变换后转化为像素从而呈现在显示设备上。
基本要求:
- 实现DDA和Bresenham画线算法。(80%)
- 实现画圆算法。(90%)
- 请勿直接调用OpenGL库中提供的绘制线段和圆的函数,需手动模拟如何通过绘制像素来显示几何图形,效果可参考下图。(界面显示的是“虚拟的像素”)
- 可通过交互操作来确定线段的起点和终点。(100%)
验收/代码提交时间:2021/09/16——2021/09/30
#include <iostream> #include <cstdio> #include <cmath> #include <cstdlib> #include <Windows.h> #include <gl/GLUT.h> using namespace std; const int window_size = 600; int x_0, y_0, x_1, y_1, r; int click = 0, lastx, lasty; void DDALine(int x_0, int y_0, int x_1, int y_1) { if (x_0 > x_1) { swap(x_0, x_1); swap(y_0, y_1); } double dx, dy, x, y, k; dx = (double)x_1 - x_0; dy = (double)y_1 - y_0; k = dy / dx; if (k <= 1 && k >= -1) { y = y_0; for (int x = x_0; x <= x_1; x++) { glBegin(GL_POINTS); glVertex2f(x, int(y + 0.5)); glEnd(); glFlush(); y = y + k; } } else { if (y_0 > y_1) { swap(x_0, x_1); swap(y_0, y_1); } x = x_0; k = 1.0 / k; for (int y = y_0; y <= y_1; y++) { glBegin(GL_POINTS); glVertex2f(int(x + 0.5), y); glEnd(); glFlush(); x = x + k; } } } void BreLine(int x_0, int y_0, int x_1, int y_1) { if (x_0 > x_1) { swap(x_0, x_1); swap(y_0, y_1); } int x, y, dx, dy, e; dx = x_1 - x_0; dy = y_1 - y_0; x = x_0; y = y_0; if (abs(dx) > abs(dy)) { if (dy >= 0)e = -dx; else e = dx; for (int i = 0; i <= dx; i++) { glBegin(GL_POINTS); glVertex2f(x, y); glEnd(); glFlush(); x++; e = e + 2 * dy; if (dy >= 0) { if (e >= 0) { y++; e = e - 2 * dx; } } else { if (e <= 0) { y--; e = e + 2 * dx; } } } } else { swap(x_0, y_0); swap(x_1, y_1); if (x_0 > x_1) { swap(x_0, x_1); swap(y_0, y_1); } dx = x_1 - x_0; dy = y_1 - y_0; x = x_0; y = y_0; if (dy >= 0)e = -dx; else e = dx; for (int i = 0; i <= dx; i++) { glBegin(GL_POINTS); glVertex2f(y, x); glEnd(); glFlush(); x++; e = e + 2 * dy; if (dy >= 0) { if (e >= 0) { y++; e = e - 2 * dx; } } else { if (e <= 0) { y--; e = e + 2 * dx; } } } } } void CirclePoints(int x, int y) { glBegin(GL_POINTS); glVertex2f(x + x_0, y + y_0); glVertex2f(y + x_0, x + y_0); glVertex2f(-x + x_0, y + y_0); glVertex2f(y + x_0, -x + y_0); glVertex2f(x + x_0, -y + y_0); glVertex2f(-y + x_0, x + y_0); glVertex2f(-x + x_0, -y + y_0); glVertex2f(-y + x_0, -x + y_0); glEnd(); glFlush(); } void Circle() { int x, y, d; x = 0; y = r; d = 5 - 4 * r; CirclePoints(x, y); while (x <= y) { if (d < 0)d += 8 * x + 12; else { d += 8 * (x - y) + 20; y--; } x++; CirclePoints(x, y); } } void myInit(void) { //glColor3f(1.0, 1.0, 0.0); gluOrtho2D(0, window_size, 0, window_size); //glMatrixMode(GL_MODELVIEW); } void myDisplay() { glClear(GL_COLOR_BUFFER_BIT); glFlush(); } void DDAMouse(int button, int state, int x, int y) { if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { click++; if (click % 2 == 0) { glColor3f(1, 0, 0); DDALine(lastx, window_size - lasty, x, window_size - y); } else { lastx = x; lasty = y; glColor3f(1, 0, 0); glBegin(GL_POINTS); glVertex2f(x, window_size - y); glEnd(); glFlush(); } } } void BreMouse(int button, int state, int x, int y) { if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { click++; if (click % 2 == 0) { glColor3f(1, 0, 0); BreLine(lastx, window_size - lasty, x, window_size - y); } else { lastx = x; lasty = y; glColor3f(1, 0, 0); glBegin(GL_POINTS); glVertex2f(x, window_size - y); glEnd(); glFlush(); } } } void circleMouse(int button, int state, int x, int y) { if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { click++; if (click % 2 == 0) { glColor3f(1, 0, 0); r = sqrt((lastx - x) * (lastx - x) + (lasty - y) * (lasty - y)); x_0 = lastx; y_0 = window_size - lasty; Circle(); } else { lastx = x; lasty = y; glColor3f(1, 0, 0); glBegin(GL_POINTS); glVertex2f(x, window_size - y); glEnd(); glFlush(); } } } int main(int argc, char* argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(window_size, window_size); glutInitWindowPosition(300, 100); int op; printf("Choose one of the following options:\n"); printf("1:Draw segment with DDA.\n"); printf("2:Draw segment with Bresenham.\n"); printf("3:Draw circle.\n"); scanf_s("%d", &op); if (op == 1) { glutCreateWindow("DDA-Line"); myInit(); glutMouseFunc(&DDAMouse); } else if (op == 2) { glutCreateWindow("Bresenham-Line"); myInit(); glutMouseFunc(&BreMouse); } else { glutCreateWindow("Circle"); myInit(); glutMouseFunc(&circleMouse); } glutDisplayFunc(&myDisplay); glutMainLoop(); return(0); }