Cohen-Sutherland算法裁剪线段
来源:互联网 发布:天下3龙巫捏脸数据图表 编辑:程序博客网 时间:2024/05/17 12:20
如何裁剪一条线
(《计算机图形学——openGL版(第三版)》)
Cohen-Sutherland裁剪器计算端点为p1和p2的线段的哪一部分在世界窗口中,并返回那个部分的端点。
考虑开发一个函数:
int clipSegment(Point2& p1, Point2 &p2, RealRect window);
它接受两个二维的点,以及一个对齐的矩形,将以p1和p2为端点的线段裁剪到窗口边界处。如果线段的某一部分在窗口内,则将新的断点存放在p1和p2中,并且函数返回1,说明线段的某些部分是可见的。如果这条线完全被裁剪掉了,函数返回0,说明没有任何部分可见。
裁剪器可能遇到的四种情况
- 如CD, 两端点均在窗口内,不裁剪,返回1
- 如BC, 一个端点在窗口外,裁剪一个点,返回1
- 如AB,两个端点均在窗口外,且在窗口内没有线段,返回0
- 如AE,两端点均在窗口外,且在窗口内有线段,裁剪两个点,返回1
对于一个窗口,线段的摆放可能有多种形式,一个通常的图画可能包含上千条线段,每条线段都必须依照窗口裁剪,所以效率很重要,Cohen-Sutherland算法针对这个问题提供了一个快速的分治算法。
Cohen-Sutherland算法
Cohen-Sutherland算法给线段的每个端点计算一个“窗口内部/外部编码”,将窗口看作四个半平面的交。
编码由四个二进制位组成,如果点P在window的某条边界之外(和直线比较),则编码对应的一位取T。显然,若点P的编码为“FFFF”,则P位于window中。
平凡接受和平凡拒绝
若线段AB两端点都在窗口内,则线段也在窗口内,称平凡接受。若线段AB两端点都在窗口的一条边外,则线段也在窗口外,称平凡拒绝。其编码的监测方法为:
- 平凡接受:两个编码都是FFFF
- 平凡拒绝:两个编码在某一位上都是T
没有平凡接受或平凡拒绝时的截断
Cohen-Sutherland算法采用分治策略,若线段不是被平凡接受或平凡拒绝,则它会被窗口的某一个边界分成两个部分,其中一部分在窗口外,会被丢掉。剩下的部分有潜在可能性,对另一个边界重复操作。这个算法最多四次(四条边界)就会终止,出现平凡接受或平凡拒绝。
如上图,线段P1P2被窗口截断,需要对P1重新计算。它的x坐标显然是窗口右边界的位置,y坐标需要利用三角形相似性计算(向量计算)。
可以用类似的方法对窗口其他三个边界裁剪。
必须考虑除以0的情况,事实上,对于垂直的线,delx是0,对于水平线,dely是0,0仅出现在分子上。当分母是0时,不会执行到这行代码,所以不会发生除以0的情况。
算法伪代码
int clipSegment(Point2& p1, Point2 &p2, RealRect W);{ do{ if (平凡接受) return 1; // 部分可见 if (平凡拒绝) return 0; // 完全不可见 if (p1在窗口外面){ if (p1在窗口左边) 用左边界截断,更新p1; else if (p1在窗口右边) 用右边界截断,更新p1; else if (p1在窗口上面) 用上边界截断,更新p1; else if (p1在窗口下面) 用下边界截断,更新p1; } else{ // p2在窗口外面 if (p2在窗口左边) 用左边界截断,更新p2; else if (p2在窗口右边) 用右边界截断,更新p2; else if (p2在窗口上面) 用上边界截断,更新p2; else if (p2在窗口下面) 用下边界截断,更新p2; } }}
C++实现
#define LEFT 8#define TOP 4#define RIGHT 2#define BUTTOM 1unsigned char getCode(Point2& p, RealRect& window){ unsigned char code = 0; if (p.x < window.l) code |= LEFT; if (p.y > window.t) code |= TOP; if (p.x > window.r) code |= RIGHT; if (p.y < window.b) code |= BUTTOM; return code;}// 裁剪线段void chopLine(Point2& p, RealRect& window, unsigned char code, int delx, int dely){ if (code & LEFT) { // 使用左边界裁剪 p.y += (window.l - p.x) * dely / delx; p.x = window.l; } else if (code & RIGHT) { // 使用右边界裁剪 p.y += (window.r - p.x) * dely / delx; p.x = window.r; } else if (code & BUTTOM) { // 使用下边界裁剪 p.x += (window.b - p.y) * delx / dely; p.y = window.b; } else if (code & TOP) { // 使用上边界裁剪 p.x += (window.t - p.y) * delx / dely; p.y = window.t; }}int clipSegment(Point2& p1, Point2& p2, RealRect& window){ while (true){ unsigned char code1 = getCode(p1, window), code2 = getCode(p2, window); // 如果平凡接受, return 1 if ((code1|code2) == 0) return 1; // 如果平凡拒绝, return 0 if ((code1&code2) != 0) return 0; // if p1在外面 if (code1 != 0) { int delx = p2.x - p1.x, dely = p2.y - p1.y; chopLine(p1, window, code1, delx, dely); } // else p2在外面 else { int delx = p1.x - p2.x, dely = p1.y - p2.y; chopLine(p2, window, code2, delx, dely); } }}
- Cohen-Sutherland线段裁剪算法
- Cohen-Sutherland算法线段裁剪
- Cohen-Sutherland线段裁剪算法
- Cohen-Sutherland线段裁剪算法
- Cohen-Sutherland算法裁剪线段
- Cohen-Sutherland线段裁剪算法
- Cohen-Sutherland 窗口裁剪线段算法
- 计算机图形学 - 线段裁剪 - Cohen Sutherland算法
- Cohen-Sutherland裁剪算法
- Cohen-Sutherland裁剪算法
- Cohen Sutherland线段裁剪算法(C#实现)
- Cohen-SutherLand 裁剪算法 (vc++)
- opengl 直线裁剪Cohen-Sutherland算法
- Cohen-Sutherland直线段的裁剪算法
- 【裁剪】线段的裁剪——Cohen-Sutherland算法及代码实现
- 计算机图形学-直线裁剪(Cohen-Sutherland编码裁剪算法)
- 直线矩形视口裁剪算法 Cohen–Sutherland algorithm
- 裁剪算法 - Cohen Sutherland Clipping的原理及Java实现
- 标准版Eclipse搭建PHP环境的详细步骤
- 将Maven项目转换成普通的web项目
- Oracle建立、删除表空间和用户
- 更新完成?以太坊新的系统还不是很稳定
- springboot 常用配置
- Cohen-Sutherland算法裁剪线段
- MXnet实战之线性回归
- python3 用sanic时 import ssl 报错
- 编译指令#pragma详解
- 微信开发关于$GLOBALS["HTTP_RAW_POST_DATA"]获取不到数据解决
- 单例碰到多线程
- MySQL对表的操作及单表数据操作
- 【Java笔记】Week04 -- 面向对象
- .Net操作excel(使用NPOI)