1. 实验内容
采用Ivan Sutherland算法(编码裁剪算法)实现二维线段裁剪。要求:以金刚石图案中圆周的最上点和最右点构成的窗口对该图案进行裁剪。
2. 实验环境
Visual Studio 2022、图形学实验程序框架、Windows11系统
3. 问题分析
4. 算法设计
5. 源代码
//编码 int CDiamondView::Encode(int x,int y) { int res = 0; if (x < RectP1.x) res = res | 1; if (x > RectP2.x) res = res | 2; if (y < RectP1.y) res = res | 8; if (y > RectP2.y) res = res | 4; return res; } void CDiamondView::cutLine(POINT p1, POINT p2) { CDC* pDC = GetDC(); CPen newPen, * oldPen; newPen.CreatePen(PS_SOLID, 2, RGB(0, 255, 0)); oldPen = pDC->SelectObject(&newPen); int done = 0, accept = 0, reject = 0; while (done != 1) { int c1 = Encode(p1.x, p1.y); int c2 = Encode(p2.x, p2.y); if ((c1 & c2) != 0) { reject = 1; done = 1; } else if (c1 == 0 && c2 == 0) { accept = 1; done = 1; } else { if (c1 == 0) { POINT t = p1; p1 = p2; p2 = t; int temp = c1; c1 = c2; c2 = temp; } if (c1 & 1) { int x = RectP1.x; int y = (p2.y - p1.y) * 1.0 / ((p2.x - p1.x) * 1.0) * (x - p1.x) + p1.y; p1.x = x; p1.y = y; } if (c1 & 2) { int x = RectP2.x; int y = (p2.y - p1.y) * 1.0 / ((p2.x - p1.x) * 1.0) * (x - p1.x) + p1.y; p1.x = x; p1.y = y; } if (c1 & 4) { int y = RectP2.y; int x = (p2.x - p1.x) * 1.0 / ((p2.y - p1.y) * 1.0) * (y - p1.y) + p1.x; p1.x = x; p1.y = y; } if (c1 & 8) { int y = RectP1.y; int x = (p2.x - p1.x) * 1.0 / ((p2.y - p1.y) * 1.0) * (y - p1.y) + p1.x; p1.x = x; p1.y = y; } } } if (accept) { pDC->MoveTo(p1.x, p1.y); pDC->LineTo(p2.x, p2.y); } pDC->SelectObject(oldPen); return; } //线段裁剪 //裁剪窗口左上角顶点为RectP1,右下角顶点为RectP2,是CDiamondView的成员 void CDiamondView::Cut() { IsCutting = FALSE; //以下添加您的代码 int nVertex = 21; int radius = 150; POINT* pnt = new POINT[nVertex]; const double PI = 3.14159265; double theta = 2 * PI / nVertex; for (int i = 0; i < nVertex; i++) { pnt[i].x = radius * cos(i * theta) + MaxX() / 2; pnt[i].y = radius * sin(i * theta) + MaxY() / 2; } for (int i = 0; i < nVertex; i++) { for (int j = i + 1; j < nVertex; j++) { cutLine(pnt[i], pnt[j]); } } }
6.程序运行结果
如图,正确地绘制出了金刚石图案。
如图,正确地对金刚石图形进行了裁剪。选取金刚石的中间部分作为裁剪窗口,裁剪窗口区域内的线条变为绿色。