[计算机图形学经典算法] Cohen-Sutherland 算法 (附Matlab代码)
2018-01-27 11:49
399 查看
刚学习了计算机图形学这门课程,为奠定根基的算法所倾倒,特此记录一二。
为介绍 Cohen-Sutherland 算法,我们先描述对窗体所在平面的编码。
窗口内部的点根据两端点编码的“或”运算直接判定:
0000 0000 -> 0000 逻辑或
大部分窗口外侧的直线段可以根据两端点编码的“与”运算直接判定:
1010 0010 -> 0010 逻辑与
在 Cohen-Sutherland 算法中,计算交点是根据编码信息确定的,只有当“或”运算结果为 1 的编码位对应的窗口边界才需要计算交点。
如前面的例子中,蓝色直线段不能直接排除,需要计算交点。此时观察其两个端点的编码:
需要进行上述替换并继续计算交点的原因,是计算出的交点可能是虚交点。
只有当最后进行逻辑或判定的两个交点(或端点)最后的或运算结果为 0000 时,整个过程结束。
Cohen-Sutherland 算法
编码
Cohen-Sutherland 算法是早期图形学算法中的一颗明珠,这种算法使用了一种较少使用的编码方法,较好地解决了直线段的剪裁问题,在效率和简便性上均表现良好。为介绍 Cohen-Sutherland 算法,我们先描述对窗体所在平面的编码。
与或
Cohen-Sutherland 算法的优点在于,可根据简单的直线端点间的“与”、“或”操作,排除大量无需剪裁的直线段。对这些直线段,因无需进行与边界间的交点计算以及相应的实、虚交点判别,所以大大提高了检测与计算效率。窗口内部的点根据两端点编码的“或”运算直接判定:
0000 0000 -> 0000 逻辑或
大部分窗口外侧的直线段可以根据两端点编码的“与”运算直接判定:
1010 0010 -> 0010 逻辑与
求交
对于不能直接排除的直线段,我们需要计算交点。在 Cohen-Sutherland 算法中,计算交点是根据编码信息确定的,只有当“或”运算结果为 1 的编码位对应的窗口边界才需要计算交点。
如前面的例子中,蓝色直线段不能直接排除,需要计算交点。此时观察其两个端点的编码:
计算
虚实
当计算出一个直线段与窗口边界的交点后,我们需要将新计算出的交点替换掉原来此编码位出现 1 的端点。然后与另一端点继续进行“或”运算来判定是否需要计算交点。需要进行上述替换并继续计算交点的原因,是计算出的交点可能是虚交点。
只有当最后进行逻辑或判定的两个交点(或端点)最后的或运算结果为 0000 时,整个过程结束。
算法
示例
Matlab代码
clear all; n = 100; Xmin = -4; Xmax = 4; Ymin = -3; Ymax = 3; figure; hold on; P1x = rand(1,n)*20 - 10; P2x = rand(1,n)*20 - 10; P1y = rand(1,n)*20 - 10; P2y = rand(1,n)*20 - 10; P1code = zeros(n,4); P2code = zeros(n,4); for i = 1:n if P1x(i) < Xmin P1code(i,1) = 1; end if P1x(i) > Xmax P1code(i,2) = 1; end if P1y(i) < Ymin P1code(i,3) = 1; end if P1y(i) > Ymax P1code(i,4) = 1; end if P2x(i) < Xmin P2code(i,1) = 1; end if P2x(i) > Xmax P2code(i,2) = 1; end if P2y(i) < Ymin P2code(i,3) = 1; end if P2y(i) > Ymax P2code(i,4) = 1; end plot([P1x(i),P2x(i)],[P1y(i),P2y(i)],'b-'); end hold off; P_label = zeros(1,n); figure; hold on; for i = 1:n P_or = P1code(i,1:4) | P2code(i,1:4); if sum(P_or) == 0 P_label(i) = 1; plot([P1x(i),P2x(i)],[P1y(i),P2y(i)],'r-'); end P_and = P1code(i,1:4) & P2code(i,1:4); if sum(P_and) > 0 P_label(i) = 2; plot([P1x(i),P2x(i)],[P1y(i),P2y(i)],'g-'); end end hold off; figure; hold on; for i = 1:n if P_label(i) == 0 P_or = P1code(i,1:4) | P2code(i,1:4); plot([P1x(i),P2x(i)],[P1y(i),P2y(i)],'g-'); if P_or(1) == 1 Py = P1y(i) + (Xmin-P1x(i))*(P2y(i)-P1y(i))/(P2x(i)-P1x(i)); if P1x(i) < Xmin P1x(i) = Xmin; P1y(i) = Py; elseif P2x(i) < Xmin P2x(i) = Xmin; P2y(i) = Py; end end if P_or(2) == 1 Py = P1y(i) + (Xmax-P1x(i))*(P2y(i)-P1y(i))/(P2x(i)-P1x(i)); if P1x(i) > Xmax P1x(i) = Xmax; P1y(i) = Py; elseif P2x(i) > Xmax P2x(i) = Xmax; P2y(i) = Py; end end if P_or(3) == 1 Px = P1x(i) + (Ymin-P1y(i))/(P2y(i)-P1y(i))*(P2x(i)-P1x(i)); if P1y(i) < Ymin P1x(i) = Px; P1y(i) = Ymin; elseif P2y(i) < Ymin P2x(i) = Px; P2y(i) = Ymin; end end if P_or(4) == 1 Px = P1x(i) + (Ymax-P1y(i))/(P2y(i)-P1y(i))*(P2x(i)-P1x(i)); if P1y(i) > Ymax P1x(i) = Px; P1y(i) = Ymax; elseif P2y(i) > Ymax P2x(i) = Px; P2y(i) = Ymax; end end if P1x(i) >= Xmin & P1x(i) <= Xmax & ... P2x(i) >= Xmin & P2x(i) <= Xmax & ... P1y(i) >= Ymin & P1y(i) <= Ymax & ... P2y(i) >= Ymin & P2y(i) <= Ymax plot([P1x(i),P2x(i)],[P1y(i),P2y(i)],'m-','LineWidth',2); end plot([-4 4 4 -4 -4],[-3 -3 3 3 -3],'b-','LineWidth',2); end end hold off;
相关文章推荐
- [计算机图形学经典算法] 直线段和圆弧在屏幕上的绘制 (附matlab代码)
- [计算机图形学经典算法] Liang-Barsky(梁友栋-Barsky) 算法 (附Matlab代码)
- 在CSDN上共享了7个经典定位算法的MATLAB代码
- 【裁剪】线段的裁剪——Cohen-Sutherland算法及代码实现
- 经典面试题(四)附答案 算法+数据结构+代码 微软Microsoft、谷歌Google、百度、腾讯
- 10个经典的C语言面试基础算法及代码
- 卡尔曼滤波简介及其算法实现代码(C++/C/MATLAB)
- [OpenGL]计算机图形学:直线裁剪算法中Cohen-Sutherland算法和Liang-Barsky算法
- [计算机图形学经典算法] 区域填充
- 经典面试题(一)附答案 算法+数据结构+代码 微软Microsoft、谷歌Google、百度、腾讯
- 双边滤波(bilateral filter)快速算法 matlab实现代码
- 数据挖掘之分类算法---knn算法(Matlab代码)
- Cohen-Sutherland算法(转载)
- 10个经典的 C 语言面试基础算法及代码
- 感知机学习算法对偶形式(Matlab代码)
- 代码面试最常用的10大算法(经典)
- 模式识别经典算法——Kmeans图像聚类分割(以最短的matlab程序实现)
- 复合形算法及matlab代码
- Tubor C 直线裁剪算法 Cohen-Sutherland算法 (可运行代码)
- 【分享】一些经典的C/C++语言基础算法及代码(一)