梁友栋-Barsky裁剪算法
2012-12-28 15:58
225 查看
Cyrus和Beck用参数化方法提出了比Cohen-Sutherland更有效的算法。后来梁友栋和Barsky独立地提出了更快的参数化线段裁剪算法,也称为Liany-Barsky(LB)算法。
一、梁友栋-Barsky裁剪算法思想:
我们知道,一条两端点为P1(x1,y1)、P2(x2,y2)的线段可以用参数方程形式表示:
式中,Δx=x2-x1,Δy=y2-y1,参数u在0~1之间取值,P(x,y)代表了该线段上的一个点,其值由参数u确定,由公式可知,当u=0时,该点为P1(x1,y1),当u=1时,该点为P2(x2,y2)。如果点P(x,y)位于由坐标(xwmin,ywmin)和(xwmax,ywmax)所确定的窗口内,那么下式成立:
这四个不等式可以表示为:
其中,p、q定义为:
从(3-12)式可以知道:任何平行于窗口某边界的直线,其pk=0(但并不是所有的Pk均为0,是存在pk=0的意思。平行于窗口某边界的图片,会出现 (p1&&p2)||(p3&&p4)=0的情况),k值对应于相应的边界(k=1,2,3,4对应于左、右、下、上边界)。如果还满足qk<0(默认x1为最左点?默认斜率大于0小于1?),则线段完全在边界外,应舍弃该线段。如果pk=0并且qk≥0,则线段平行于窗口某边界并在窗口内,见图中所示。公式(3-12)式还告诉我们:
1、当pk<0时,线段从裁剪边界延长线的外部延伸到内部;
2、当pk>0时,线段从裁剪边界延长线的内部延伸到外部;
例如,当Δx≥0时,对于左边界p1<0(p1=-Δx),线段从左边界的外部到内部;
对于右边界p2>0(p2=Δx),线段从右边界的内部到外部。
当Δy<0时,对于下边界p3>0(p3=-Δy),线段从下边界的内部到外部;
对于上边界p4<0(p4=Δy),线段从上边界的外部到内部。
当pK≠0时,可以计算出参数u的值,它对应于无限延伸的直线与延伸的窗口边界k的交点,即:
对于每条直线,可以计算出参数u1和u2,该值定义了位于窗口内的线段部分:
1、u1的值由线段从外到内遇到的矩形边界所决定(pk<0),对这些边界计算rk=qk/pk,u1取0和各个r值之中的最大值。
2、u2的值由线段从内到外遇到的矩形边界所决定(pk>0),对这些边界计算rk=qk/pk,u2取0和各个r值之中的最小值。
3、如果u1>u2,则线段完全落在裁剪窗口之外,应当被舍弃;否则,被裁剪线段的端点可以由u1和u2计算出来。
二、梁友栋-Barsky裁剪算法实现:
1、初始化线段交点的参数:u1=0,u2=1;
2、计算出各个裁剪边界的pk、qk值(k=1,2,3,4);
3、[调用函数clipTest()],在函数中根据p、q来判断:是舍弃线段还是改变交点的参数。(计算rk=qk/pk,根据(1)、(2)··· 执行)
(1) 当p<0时,参数r用于更新u1; (u1=max{u1,…,rk})
(2) 当p>0时,参数r用于更新u2。 (u2=min{u2,…,rk})
(3)如果更新了u1或u2后,使u1>u2,则舍弃该线段。
(4)当p=0且q<0时,因为线段平行于边界并且位于边界之外,则舍弃该线段。见下图所示。
4、p、q的四个值经判断后,如果该线段未被舍弃,则裁剪线段的端点坐标由参数u1和u2的值决定。
三、梁友栋-Barsky裁剪算法特点:
梁友栋-Barsky算法只能应用于矩形窗口的情形。通常梁友栋-Barsky算法比Cohen-Sutherland算法效率更高,因为需要计算的交点数目减少了。更新参数u1、u2仅仅需要一次除法;线段与窗口边界的交点仅计算一次,就计算出u1、u2最后的值。相比之下,即使一条线段完全落在裁剪窗口之外,Cohen-Sutherland算法也要对它反复求交点,而且每次求交计算都需要做乘除法。
梁友栋-Barsky和Cohen-Sutherland算法还可以扩展为三维裁剪算法。
四、梁友栋-Barsky裁剪算法程序:
MFC编写的应用程序(包含源代码):http://download.csdn.net/detail/marcnuth/4938143
梁友栋算法核心源代码:
本文来源: http://course.cug.edu.cn/cugThird/CGOL_NET/CLASS/course/3-2-3-a.htm
一、梁友栋-Barsky裁剪算法思想:
我们知道,一条两端点为P1(x1,y1)、P2(x2,y2)的线段可以用参数方程形式表示:
x= x1+ u·(x2-x1)= x1+ u·Δx y= y1+ u·(y2-y1)= y1+ u·Δy | 0≤u≤1 | (3-9) |
xwmin≤x1+ u·Δx≤xwmax ywmin≤y1+ u·Δy≤ywmax | (3-10) |
u·pk ≤qk , k=1,2,3,4 | (3-11) |
p1=-Δx, q1=x1-xwmin p2=Δx, q2=xwmax-x1 p3=-Δy, q3=y1-ywmin p4=Δy, q4=ywmax-y1 | (3-12) |
1、当pk<0时,线段从裁剪边界延长线的外部延伸到内部;
2、当pk>0时,线段从裁剪边界延长线的内部延伸到外部;
例如,当Δx≥0时,对于左边界p1<0(p1=-Δx),线段从左边界的外部到内部;
对于右边界p2>0(p2=Δx),线段从右边界的内部到外部。
当Δy<0时,对于下边界p3>0(p3=-Δy),线段从下边界的内部到外部;
对于上边界p4<0(p4=Δy),线段从上边界的外部到内部。
当pK≠0时,可以计算出参数u的值,它对应于无限延伸的直线与延伸的窗口边界k的交点,即:
(3-13) |
1、u1的值由线段从外到内遇到的矩形边界所决定(pk<0),对这些边界计算rk=qk/pk,u1取0和各个r值之中的最大值。
2、u2的值由线段从内到外遇到的矩形边界所决定(pk>0),对这些边界计算rk=qk/pk,u2取0和各个r值之中的最小值。
3、如果u1>u2,则线段完全落在裁剪窗口之外,应当被舍弃;否则,被裁剪线段的端点可以由u1和u2计算出来。
二、梁友栋-Barsky裁剪算法实现:
1、初始化线段交点的参数:u1=0,u2=1;
2、计算出各个裁剪边界的pk、qk值(k=1,2,3,4);
3、[调用函数clipTest()],在函数中根据p、q来判断:是舍弃线段还是改变交点的参数。(计算rk=qk/pk,根据(1)、(2)··· 执行)
(1) 当p<0时,参数r用于更新u1; (u1=max{u1,…,rk})
(2) 当p>0时,参数r用于更新u2。 (u2=min{u2,…,rk})
(3)如果更新了u1或u2后,使u1>u2,则舍弃该线段。
(4)当p=0且q<0时,因为线段平行于边界并且位于边界之外,则舍弃该线段。见下图所示。
4、p、q的四个值经判断后,如果该线段未被舍弃,则裁剪线段的端点坐标由参数u1和u2的值决定。
三、梁友栋-Barsky裁剪算法特点:
梁友栋-Barsky算法只能应用于矩形窗口的情形。通常梁友栋-Barsky算法比Cohen-Sutherland算法效率更高,因为需要计算的交点数目减少了。更新参数u1、u2仅仅需要一次除法;线段与窗口边界的交点仅计算一次,就计算出u1、u2最后的值。相比之下,即使一条线段完全落在裁剪窗口之外,Cohen-Sutherland算法也要对它反复求交点,而且每次求交计算都需要做乘除法。
梁友栋-Barsky和Cohen-Sutherland算法还可以扩展为三维裁剪算法。
四、梁友栋-Barsky裁剪算法程序:
MFC编写的应用程序(包含源代码):http://download.csdn.net/detail/marcnuth/4938143
梁友栋算法核心源代码:
#include "graphics.h" int clipTest(float p,float q,float *u1,float *u2) { int flag=1; /*flag为标志变量,0:表示舍弃;1:表示可见。*/ float r; if(p<0.0) { r=q/p; if(r>*u2) flag=0; else if(r>*u1) *u1=r; /*u1取"进入"点的最大参数值*/ } else if(p>0.0) { r=q/p; if(r<*u1) flag=0; else if(r<*u2) *u2=r; /*u2取"离开" 点的最小参数值*/ } else if(q<0.0) /*p=0,且q<0。平行于边界,而且在界外的线*/ flag=0; return(flag); } void clipLine(int xwmin,int ywmin,int xwmax,int ywmax, int x1,int y1,int x2,int y2) { float u1=0.0,u2=1.0,dx=x2-x1,dy; if(clipTest(-dx,x1-xwmin,&u1,&u2)) if(clipTest(dx,xwmax-x1,&u1,&u2)) { dy=y2-y1; if(clipTest(-dy,y1-ywmin,&u1,&u2)) if(clipTest(dy,ywmax-y1,&u1,&u2)) { if(u2<1.0) { x2=x1+u2*dx; /*通过u2求得裁剪后的p2端点*/ y2=y1+u2*dy; } if(u1>0.0) { x1=x1+u1*dx; /*通过u1求得裁剪后的p1端点*/ y1=y1+u1*dy; } line(x1,y1,x2,y2); /*裁剪后的线段输出*/ } } }
本文来源: http://course.cug.edu.cn/cugThird/CGOL_NET/CLASS/course/3-2-3-a.htm
相关文章推荐
- 动易2006序列号破解算法公布
- C#数据结构与算法揭秘二
- Visual C++中MFC消息的分类
- JavaScript 组件之旅(二)编码实现和算法
- IE8引发 VS2005/2008 MFC向导出错的解决方案
- 将15位身份证补全为18位身份证的算法示例详解
- C++算法系列之日历生成的算法代码
- 1 2 3 4 5 6 7 8 9 = 110的java实现
- Sedgewick之巨著《算法》,与高德纳TAOCP一脉相承
- 算法的时间复杂度
- 算法导论:选择排序的原理与实现
- PHP实现四种常用的排序算法
- 图解插入排序算法
- 一些常见算法的JavaScript实现
- 平方根sqrt()函数的底层算法效率
- 二叉搜索树的一些相关算法介绍
- 欧几里德算法(辗转相处法)练手
- 面试中常见的一些算法问题
- 计算机编程中一些重要的算法
- 合并排序算法解说与例子