梁友栋-Barsky直线裁剪算法计算机图形学课程设计

合集下载

OpenGL计算机图形学梁友栋裁剪算法实验代码及运行结果

OpenGL计算机图形学梁友栋裁剪算法实验代码及运行结果

《计算机图形学实验》报告任课教师:钱文华2016年春季学期实验:梁友栋裁剪实验时间:2016年11月17日实验地点:信息学院2204实验目的:掌握梁友栋裁剪程序代码:#include <stdio.h>#include <glut.h>#include <stdlib.h>#include <math.h>class wcPt2D{public:GLfloat x,y;void setCoords(GLfloat xCoord,GLfloat yCoord){x=xCoord;y=yCoord;}GLfloat getx() const{return x;}GLfloat gety() const{return y;}};inline GLint round(const GLfloat a){return GLint(a+0.5);}void setPixel(int x,int y){glBegin(GL_POINTS);glVertex2i(x,y);glEnd();}void init(){glClearColor(1.0,1.0,1.0,0.0);glMatrixMode (GL_PROJECTION);gluOrtho2D(-200.0,200.0,-200.0,200.0);}void lineBres(GLfloat x0,GLfloat y0,GLfloat xEnd,GLfloat yEnd){ int dx = fabs(xEnd - x0),dy = fabs(yEnd - y0);int p = 2*dy - dx;int twoDy = 2*dy,twoDyMinusDx = 2*(dy - dx);int x,y;if(x0>xEnd){x = xEnd;y = yEnd;xEnd = x0;}else{x = x0;y = y0;}setPixel(x,y);while(x<xEnd){x++;if(p<0)p+=twoDy;else{y++;p+=twoDyMinusDx;}setPixel(x,y);}}GLint clipTest(GLfloat p,GLfloat q,GLfloat *u1,GLfloat *u2){ GLfloat r;GLint returnValue = true;if(p<0.0){r = q/p;if(r>*u2)returnValue = false;elseif(r>*u1)*u1 = r;}elseif(p>0.0){r = q/p;if(r<*u1)returnValue = false;else if(r<*u2)*u2 = r;}elseif(q<0.0)returnValue = false;return(returnValue);}void lineClipLiangBarsk(wcPt2D winMin,wcPt2D winMax,wcPt2D p1,wcPt2D p2){GLfloat u1 = 0.0,u2 = 1.0,dx = p2.getx()-p1.getx(),dy;GLfloat x1 = p1.getx(),y1 = p1.gety();GLfloat x2 = p2.getx(),y2 = p2.gety();if(clipTest(-dx,p1.getx()-winMin.getx(),&u1,&u2))if(clipTest(dx,winMax.getx()-p1.getx(),&u1,&u2)){dy = p2.gety()-p1.gety();if(clipTest(-dy,p1.gety()-winMin.gety(),&u1,&u2)){if(clipTest(dy,winMax.gety()-p1.gety(),&u1,&u2)){if(u2<1.0){p2.setCoords(p1.getx()+u2*dx,p1.gety()+u2*dy);}if(u1>0.0){p1.setCoords(p1.getx()+u1*dx,p1.gety()+u1*dy);}glColor3f(0.0,0.0,0.0);lineBres(x1,y1,p1.getx(),p1.gety());lineBres(p2.getx(),p2.gety(),x2,y2);glColor3f(1.0,0.0,0.0);lineBres(p1.getx(),p1.gety(),p2.getx(),p2.gety());}}else{glColor3f(0.0,0.0,0.0);lineBres(x1,y1,x2,y2);}}}void displayliangyoudongcaijian(){glClear(GL_COLOR_BUFFER_BIT);glLineWidth(5.0);glColor3f(0.0,0.0,0.0);glBegin(GL_LINE_LOOP);glVertex2i(100,100);glVertex2i(100,-100);glVertex2i(-100,-100);glVertex2i(-100,100);glEnd();glPointSize(4);wcPt2D test1[4] = {{-100.0,-100.0},{100.0,100.0},{-150.0,-200.0},{200.0,120.0}};wcPt2D test2[4] = {{-100.0,-100.0},{100.0,100.0},{-150.0,-120.0},{0.0,0.0}};wcPt2D test3[4] = {{-100.0,-100.0},{100.0,100.0},{-50.0,50.0},{150.0,150.0}};wcPt2D test4[4] = {{-100.0,-100.0},{100.0,100.0},{-50.0,0.0},{60.0,50.0}};wcPt2D test5[4] = {{-100.0,-100.0},{100.0,100.0},{-170.0,-200.0},{200.0,-120.0}};lineClipLiangBarsk(test1[0],test1[1],test1[2],test1[3]);lineClipLiangBarsk(test2[0],test2[1],test2[2],test2[3]);lineClipLiangBarsk(test3[0],test3[1],test3[2],test3[3]);lineClipLiangBarsk(test4[0],test4[1],test4[2],test4[3]);lineClipLiangBarsk(test5[0],test5[1],test5[2],test5[3]);glFlush();}void main(int argc, char* argv[]){glutInit(&argc,argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowPosition(50,100);glutInitWindowSize(400,300);glutCreateWindow("梁友栋裁剪算法");init();glutDisplayFunc(displayliangyoudongcaijian);glutMainLoop();}实验结果:。

实验报告文档

实验报告文档
accept=TRUE;
done=TRUE;
}else if((code0.all&code1.all)!=0){
done=TRUE;
}else{
if(code0.all!=0){
x = x0; y = y0;
dx = x1 - x0; dy = y1 - y0;
d = dx - 2 * dy;
UpIncre=2*dx-2*dy;DownIncre=-2*dy;
while(x<=x1)
{
putpixel(x,y);
printf("x = %d , y = %d \n",x,y);
对剩余部分,把它作为新的线段看待,又从头开始考虑。两遍循环之后,就能确定该线段是部分截留下来,还是全部舍弃。
1、分区编码
延长裁剪边框将二维平面分成九个区域,每个区域各用一个四位二进制代码标识。各区代 码值如图中所示。
2、判别
根据C1和C2的具体值,可以有三种情况:
(1)C1=C2=0,表明两端点全在窗口内,因而整个线段也在窗内,应予保留。
(2)C1&C2≠0(两端点代码按位作逻辑乘不为0),即C1和C2至少有某一位同时为1,表明两端点必定处于某一边界的同一外侧,因而整个线段全在窗外,应予舍弃。
(3)不属于上面两种情况,均需要求交点。
3、求交点
假设算法按照:左、右、下、上边界的顺序进行求交处理,对每一个边界求完交点,并相关处理后,算法转向第2步,重新判断,如果需要接着进入下一边界的处理。
实验
类型
设计型
综合型
创新型








1.实验内容

计算机图形学裁剪

计算机图形学裁剪
《计算机图形学》实验报告
学院:理学院专业:信息与计算科学班级:
姓名
学号
指导教师
实验时间
4.
实验地点
计算机实验室
成绩
实验项目名称
裁剪
实验环境
VC++ 6.0
实验内容
(1)理解直线裁剪的原理(Cohen-Surtherland算法、梁友栋算法)
(2)利用VC+OpenGL实现直线的编码裁剪算法,在屏幕上用一个封闭矩形裁剪任意一条直线。
};
Rectangle rect;
int x0,y0,x1,y1;
int CompCode(int x,int y,Rectangle rect)
{
int code=0x00;
if(y<rect.ymin)
code=code|4;
if(y>rect.ymax)
code=code|8;
if(x>rect.xmax)
x0=450,y0=0,x1=0,y1=450;
printf("Press key'c'to Clip!\nPress key'r'to Rrstore!\n");
}
void Reshape(int w,int h)
{
glViewport(0,0,(GLsizei)w,(GLsizei)h);
glMatrixMode(GL_PROJECTION);
accept=0;
done=0;
int code0,code1,codeout;
code0=CompCode(x0,y0,rect);
code1=CompCode(x1,y1,rect);

计算机图形学——梁友栋-Barsky算法

计算机图形学——梁友栋-Barsky算法

计算机图形学——梁友栋-Barsky算法梁算法是计算机图形学上最经典的⼏个算法,也是⽬前唯⼀⼀个以中国⼈命名的出现在国内外计算机图形学课本的算法,我之前在介绍裁剪算法的时候介绍过这个算法这⼏天复习图形学,发现当时那篇博客写的很空洞,⼀些关键性的推理式⼦讲的不是很清楚,于是在这⾥仔细介绍⼀下。

最近发现中国⼤学MOOC上中国农业⼤学的赵明教授讲的很不错,课程短⼩精悍,感兴趣的同学可以去看⼀下⼀、直线的参数⽅程梁算法表⽰直线是通过直线的参数⽅程来确定的,也就是说给出两个点,利⽤参数表⽰直线。

这⾥对U的理解就是(x,y)点在所给两点之间线段上的位置。

⼆、出边和⼊边把被裁剪的红⾊直线段看 成是⼀条有⽅向的线段,把窗⼝ 的四条边分成两类:⼊边和出边⼊边:直线由窗⼝外向窗⼝内移动时和窗⼝边界相交的边(左边界和下边界)。

出边:直线由窗⼝内向窗⼝外移动时和窗⼝边界相交的边(右边界和上边界)。

裁剪结果的线段起点是直线和两条⼊边的交点以及始端点三 个点⾥最前⾯的⼀个点,即参数u最⼤的那个点;裁剪线段的终点是和两条出边的交点以及端点最后⾯的⼀个 点,取参数u最⼩的那个点。

值得注意的是,当u从-∞到+∞遍历直线时,⾸先对裁剪窗⼝的两条边界直线(下边和左边)从外⾯向⾥⾯移动,再对裁剪窗⼝两条边界直线(上边和右边)从⾥⾯向外⾯移动。

如果⽤u1,u2分别表⽰ 线段(u1≤u2)可见部分的开始和结束上⾯就是梁友栋先⽣的发现,但⼜有了新的问题:如何判断出边和⼊边?四个U值是如何求出来的?判断线段某⼀部分是否在窗⼝内,可以简化为判断直线上⼀个点是否在窗⼝内的问题。

我们知道梁友栋算法的基本出发点是直线的参数⽅程,那么对于那些不会被裁剪掉的点⼀定会满⾜下⾯的不等式:三、运算所⽤的量将上⾯的不等式移项得:在这⾥可以确定那些直线与裁剪窗⼝的交点中P K<0的点输⼊⼊边,P K>0的点属于出边1)分析P k=0的情况如果还满⾜q k<0则线段完全在边界外,应舍弃该线段如果q k≥0则进⼀步判断(2)当p k≠0时:当p k<0时线段从裁剪边界延长线的外部 延伸到内部,是⼊边交点当p k> 0时线段从裁剪边界延长线的内部 延伸到外部,是出边交点线段和窗⼝边界⼀共有四个交点,根据p k的符号,就知道 哪两个是⼊交点,哪两个是出交点当p k< 0时:对应⼊边交点当p k> 0时:对应出边交点⼀共四个u值,再加上u=0、u=1两个端点值,总共六个值把pk<0的两个u值和0⽐较去找最⼤的,把pk>0的两个u值 和1⽐较去找最⼩的,这样就得到两个端点的参数值四、⼩结直线参数化直线段看成是有⽅向的把窗⼝的四条边分为⼊边和出边。

梁友栋-Barsky直线裁剪算法计算机图形学课程设计

梁友栋-Barsky直线裁剪算法计算机图形学课程设计

河南理工大学万方科技学院课程设计报告2011 — 2012学年第二学期课程名称计算机图形学设计题目计算机图形学基本算法演示系统设计学生姓名学号专业班级网络11升—1班指导教师徐文鹏2012 年5 月28 日目录第1章设计内容与要求 (1)1.1 总体目标和要求 (1)1.2内容与要求 (1)1.2.1 直线的生成 (1)1.2.2 圆弧的生成 (1)1.2.3 线段裁剪 (2)1.2.4 多边形裁剪 (2)1.2.5 综合 (2)第2章总体设计 (3)2.1 Bresenham算法画直线 (3)2.1.1 Bresenham算法画直线理论基础 (3)2.1.2 Bresenham算法画直线原理 (3)2.2 Bresenham算法画圆 (4)2.2.1 Bresenham算法画圆理论基础 (4)2.2.2 Bresenham算法画圆原理 (5)2.3 梁友栋-Barsky算法进行线段裁剪 (6)2.3.1梁友栋-Barsky算法进行线段裁剪基本原理 (6)2.4 Sutherland-Hodgman算法进行多边形裁剪 (8)2.4.1 Sutherland—Hodgman多边形裁剪算法思想 (8)2.4.2 点在边界内侧的判断方法 (8)2.4.4 Sutherland-Hodgeman多边形裁剪算法特点 (8)第3章详细设计 (9)3.1 Bresenham算法画直线 (9)3.1.1 Bresenham 算法画线算法具体实现过程 (9)3.2 Bresenham算法画圆 (9)3.2.1 Bresenham 算法画圆核心代码 (9)3.3 梁友栋-Barsky算法进行线段裁剪 (10)3.3.1梁友栋-Barsky算法推导过程 (10)3.3.2梁友栋-Barsky算法进行线段裁剪的步骤 (11)3.4 Sutherland-Hodgman算法进行多边形裁剪 (11)3.4.1 Sutherland—Hodgman多边形裁剪算法步骤 (11)3.5将画线、画圆、线段裁剪和多边形裁剪综合 (12)第4章功能实现 (14)4.1用Bresenham算法画线测试结果 (14)4.2用Bresenham算法画圆测试结果 (14)4.3梁友栋-Barsky算法进行线段裁剪测试结果 (15)4.4 Sutherland-Hodgman算法进行多边形裁剪测试结果 (16)4.5将四种算法综合测试结果 (16)第5章总结 (17)参考文献 (18)第1章设计内容与要求1.1 总体目标和要求目标:以图形学算法为目标,深入研究。

计算机图形学——Liang-Barsky

计算机图形学——Liang-Barsky
➢ 线段的参数方程与点裁剪条件结合,得到不等式 xmin≤x0+u∆x≤xmax ymin≤y0+u∆y≤ymax
算法思想
➢用upK≤qK(k=1,2,3,4)表示上式,则参数p、q定义为: p1=-∆x, q1=x0-xmin p2=∆x, q2=xmax-x0 p3=-∆y, q3=y0-ymin p4=∆y, q4=ymax-y0
算法思想
➢ u1----线段从外到内遇到的矩形边界决定(p<0) 计算rk=qk/pk u1=max{0,r}
➢ u2----线段从内到外遇到的矩形边界决定(p>0) 计算rk=qk/pk u2=min{r,1}
算法剪窗口外; 否则,由参数u1和u2计算出裁剪后的线段端点
例题演示
Step1: 写出参数方程,计算∆x和∆y。
x=x0+u∆x
y
y=y0+u∆y
∆x=5 ∆y=5
(0,0) F1(1,-2)
F2(6,3)
(8,4)
x
例题演示
Step2:计算pk、qk和rk的值,并确定u1、u2的值。
p1=-∆x=-5, q1=x0-xmin=1, r1=q1/p1=-1/5 p2=∆x=5, q2=xmax-x0=7, r2=q2/p2=7/5 p3=-∆y=-5, q3=y0-ymin=-2, r3=q3/p3=2/5 p4=∆y=5, q4=ymax-y0=6, r4=q4/p4=6/5
算法思想
➢ 根据pk的值判断线段的方向:
• pk=0 线段平行于裁剪边界 qk<0 线段完全位于边界外 qk≥0 线段位于平行边界内
• pk<0 线段从裁剪边界延长线的外到内 • pk>0 反之

计算机图形学第7章二维图形的裁剪(2_3)

计算机图形学第7章二维图形的裁剪(2_3)

7.3.1 Sutherland-Hodgeman多边形裁剪 3、对多边形的n条边进行处理,对当前点号的考虑为:0~n-1。
for(i=0;i<n;i++) { if(当前第i个顶点是在边界内侧) /*对左边界:p[i][0]>=xmin */ { if(flag!=0) /*前一个点在外侧吗?*/ { flag=0;/*从外到内的情况,将标志置0,作为下一次循环的前一点标志*/ j++; q[j][0]=求出交点的x方向分量; /*将交点q放入新多边形*/ q[j][1]=求出交点的y方向分量; } j++; q[j][0]= p[i][0]; /*将当前点p放入新多边形*/ q[j][1]= p[i][1]; } else { if(flag==0) /*前一个点在内侧吗?*/ { flag=1;/*从内到外的情况,将标志置1,作为下一次循环的前一点标志*/ j++; q[j][0]=求出交点的x方向分量; /*将交点q放入新多边形*/ q[j][1]=求出交点的y方向分量; } } s[0]=p[i][0]; /*将当前点作为下次循环的前一点*/ s[1]=p[i][1]; }
7.2.3 梁友栋-Barsky裁剪算法
XWmin X 1 Xu ' XWmax X 1 Xu ' YWmin Y1 Yu ' YWmax Y1 Yu '
XWmin X 1 Xu '
这四个不等式可以表示为:
XWmax X 1 Xu ' YWmin Y1 Yu ' YWmax Y1 Yu '
7.2.3 梁友栋-Barsky裁剪算法

裁剪III(计算机图形学)

裁剪III(计算机图形学)
( y 1 YT ) y 2 y1
2009-2010-2:CG:SCUEC
14
多边形裁剪-凸多边形的二维裁剪
多边形是由一组线段围成的封闭区域,线段裁剪是多边形 裁剪的基础。下图(b)是多边形的线段被裁剪后的结果,但 已不再是封闭的区域。正确的剪裁结果应是一个有边界的区 域,即裁剪后的结果仍是一个(或多个)多边形 ,这就要求
x t x R x 0 y t y0 yB y t y T y 0

QR x QB y QT y
则有 t Q i D i i L , R , B , T
2009-2010-2:CG:SCUEC
3
梁友栋-Barsky算法
凸多边形裁剪区域
3) N (P(t)-A) < 0,则P(t)在L外侧。
性质1表明,P(t)在凸多边形内的充要条件是,对于凸多边形边界上 任意一点A和该处内法向量N,都有N (P(t)-A) 0 。
2009-2010-2:CG:SCUEC
9
Cyrus-Beck算法
现假设多边形有k条边,在每条边界Li上取1个点 Ai ,该点处的内法 向量Ni(i=1,2,…,k),则可见线段的参数区间为下列不等式组的解

t Q i D i i L , R , B , T
i , j { L , R }i j
Dj Di (Q i 0 ) t (Q j 0 ) Q Qj i D Dj i (Q i 0 ) t (Q j 0 ) Qj Qi 0 t 1
i , j { B , T }i j
2009-2010-2:CG:SCUEC
4
梁友栋-Barsky算法

计算机图形学 第三章 二维图形的裁剪概述

计算机图形学 第三章 二维图形的裁剪概述

3.2.3 梁友栋-Barsky裁剪算法
式中,Δ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)所 确定的窗口内,那么下式成立: xwmin≤x1+ u· Δx≤xwmax ywmin≤y1+ u· Δy≤ywmax(3-10)
3.2.1 Cohen-Sutherland算法
► Code(int ►{
x,int y,int *c)
*c=0; if(y>ymax) /*(xmin,ymin)和(xmax,ymax) 为窗口左下角、右上角坐标。*/ *c=*c|0x08; else if(y<ymin) *c=*c|0x04; if(x>xmax) *c=*c|0x02; else if(x<xmin) *c=*c|0x01; }
► 根据直线两点式方程:

2)
(3-
3.2 线段的裁剪
► 整理后得通用交点公式: ►
(3-3)
► ►
1、与上边界的求交公式: (3-4)
3.2 线段的裁剪
► ►
2、与下边界的求交公式:
(3-5)

► ►
3、与右边界的求交公式:
(3-6) 4、与左边界的求交公式:

(3-7)
3.2.1 Cohen-Sutherla2、判别 根据C1和C2的具体值,可以有三种情况: (1)C1=C2=0,表明两端点全在窗口内,因而 整个线段也在窗内,应予保留。 (2)C1&C2≠0(两端点代码按位作逻辑乘不为 0),即C1和C2至少有某一位同时为1,表明两端点 必定处于某一边界的同一外侧,因而整个线段全在 窗外,应予舍弃。 (3)不属于上面两种情况,均需要求交点。

计算机图形学课程设计

计算机图形学课程设计

计算机图形学课程设计
要求:程序中有必要的注释,程序中变量命名规范合理。

否则,成绩按降一档处理。

1、交互式绘图程序设计
内容:使用VC++6.0编程环境,实现一个简单的交互式绘图界面。

要求:用户通过鼠标能交互式输入一些数据,实现采用橡皮筋技术绘制相应的图形,要求能演示1-2个基本算法(Bresenham画线算法)。

选做:在状态栏上当鼠标运动时,能实时显示鼠标的当前坐标。

2、Cohen-Sutherland裁剪算法的实现
内容:使用VC++6.0环境,编程实现Cohen_Sutherland二维裁剪算法的实现。

要求:用户可以交互输入要裁剪线段的两个顶点,将裁剪后的线段和被裁剪掉的线段以不同的颜色显示在视图中。

3、Liang-Barsky裁剪算法的实现
内容:使用VC++6.0环境,编程实现Liang_Barsky二维裁剪算法的实现。

要求:用户可以交互输入要裁剪线段的两个顶点,将裁剪后的线段和被裁剪掉的线段以不同的颜色显示在视图中。

4、满足四象限的Bresenham绘制直线算法的实现
内容:使用VC++6.0环境,编程实现满足四象限的Bresenham直线段算法,并能够设置线宽和颜色属性。

要求:要求直线段端点可以由用户随机输入。

5、用OpenGL生成裁剪NURBS曲面
内容:使用VC++6.0编程环境,用OpenGL实现一个裁剪NURBS曲面的绘制。

要求:用户能交互式输入控制多面体的顶点,和剪切曲线的顶点数目和顶点坐标。

直线裁剪算法研究(Cohen_Sutherland算法和Liang_Barsky算法)

直线裁剪算法研究(Cohen_Sutherland算法和Liang_Barsky算法)

直线裁剪算法研究摘要:直线裁剪是计算机图形学中的一个重要技术,在对常见的直经线裁剪的算法分析的基础上,针对Cohen-Sutherland算法和Liang-Barsky算法进行了分析研究。

并对两种算法了计算直线与窗口边界的交点时,进行了有效有比较。

关键词:裁剪;算法;Cohen-Sutherland;Liang-Barsky;1 引言直线是图形系统中使用最多的一个基本元素。

所以对于直线段的裁剪算法是被研究最深入的一类算法,目前在矩形窗口的直线裁剪算法中,出现了许多有效的算法。

其中比较著名的有:Cohen-Sutherland算法、中点分割算法、Liang-Ba rsky算法、Sobkow-Pospisil-Yang 算法,及Nicholl-Lee-Ncholl算法等。

2 直线裁剪的基本原理图1所示的为直线与窗口边界之间可能出现的几种关系。

可以通过检查直线的两个端点是否在窗口之确定如何对此直线裁剪。

如果一直线的两个端点均在窗口边界之(如图1中P5到P6的直线),则此直线应保留。

如果一条直线的一个端点在窗口外(如P9)另一个点在窗口(如P10),则应从直线与边界的交点(P9)处裁剪掉边界之外的线段。

如果直线的两个端点均在边界外,则可分为两种情况:一种情况是该直线全部在窗口之外;另一种情况是直线穿过两个窗口边界。

图中从P3到P4的直线属于前一种情况,应全部裁剪掉;从P7到P8的直线属于后一种情况,应保留P7到P8的线段,其余部分均裁剪掉。

图1直线相对干窗口边界的栽剪直线裁剪算法应首先确定哪些直线全部保留或全部裁剪,剩下的即为部分裁剪的直线。

对于部分裁剪的直线则首先要求出这些直线与窗口边界的交点,把从交点开始在边界外的部分裁剪掉。

一个复杂的画面中可能包含有几千条直线,为了提高算法效率,加快裁剪速度,应当采用计算量较小的算法求直线与窗口边界的交点。

3 cohen-sutherland直线裁剪算法Cohen-Sutherland算法的大意是:对于每条线段P1P2,分为3种情况处理。

图形学课程设计要求 《计算机图形学》

图形学课程设计要求 《计算机图形学》

《计算机图形学》课程设计一、 设计要求1. 根据设计任务,编制程序,在机器上调试运行,并通过上机考核。

2. 按照下面的“三、课程设计报告格式”的要求,写出课程设计报告。

3. 课程设计报告在第19周之前交来。

二、 设计任务1.1)给定直线的起点坐标为P0(x0,y0)、终点坐标为P1(x1,y1),容易计算出直线斜率k 。

假设0≤k ≤1,则x 方向为主位移方向,绘制直线的递推公式为:,这称为数值微分法(Digital Differential Analyzer ,DDA ),请编程实现之。

提示:DDA 算法实质上是对直线斜率进行了四舍五入计算。

2)椭圆的扫描转换。

2.用鼠标在屏幕上绘制任意顶点数的封闭多边形并填充,填充效果如下图所示。

编程要求:⑴多边形的顶点数不受限制;⑵按下鼠标左键,拖动鼠标绘制多边形,同时按下Shift 键可以绘制水平边或垂直边; ⑶单击鼠标右键闭合多边形; ⑷使用边缘填充算法填充多边形。

⎩⎨⎧+=+=++k y y x x i i i i 1113请按照图所示,使用对话框输入直线的起点和终点坐标。

在窗口左侧区域绘制输入直线和“窗口”,在窗口右边右侧区域绘制“视区”并输出裁剪结果。

这里需要用到窗视变换的公式。

请分别用Cohen-Sutherland算法、中点分割裁剪算法和梁友栋-Barsky算法实现。

4在屏幕上使用鼠标绘制控制多边形,根据控制多边形的阶次绘制Bezier曲线和B样条曲线。

5.1)使用VC编程实现,以直角三角形为基础绘制下图所示Sierpinski三角形。

2)以屏幕范围为基础绘制下图所示Sierpinski地毯。

6.1)给定直线的起点颜色(如红色)和终点颜色(如黑色)不同,请使用中点Bresenham算法绘制任意斜率的颜色渐变直线,效果如图所示。

2)用梁友栋-Barsky算法裁剪线段P1(3,3),P2(-2,-1),裁剪窗口为wxl=0,wxr=2,wyb=0,wyt=2。

计算机图形学裁剪算法

计算机图形学裁剪算法

一、实验目标1.了解Cohen-SutherLand线段裁剪算法、Liang-Barsky线段裁剪算法、SutherLand-Hodgeman多边形裁剪算法的基本思想;2.掌握Cohen-SutherLand线段裁剪算法、Liang-Barsky线段裁剪算法、SutherLand-Hodgeman多边形裁剪算法的算法实现;二、实验内容本次实验主要是实现Cohen-SutherLand线段裁剪算法、Liang-Barsky线段裁剪算法、SutherLand-Hodgeman多边形裁剪算法。

Cohen-sutherland线段裁剪算法思想:该算法也称为编码算法,首先对线段的两个端点按所在的区域进行分区编码,根据编码可以迅速地判明全部在窗口内的线段和全部在某边界外侧的线段。

只有不属于这两种情况的线段,才需要求出线段与窗口边界的交点,求出交点后,舍去窗外部分。

对剩余部分,把它作为新的线段看待,又从头开始考虑。

两遍循环之后,就能确定该线段是部分截留下来,还是全部舍弃。

Cohen-sutherland线段裁剪算法步骤:1、分区编码延长裁剪边框将二维平面分成九个区域,每个区域各用一个四位二进制代码标识。

各区代码值如图中所示。

四位二进制代码的编码规则是:(1)第一位置1:区域在左边界外侧(2)第二位置1:区域在右边界外侧(3)第三位置1:区域在下边界外侧(4)第四位置1:区域在上边界外侧裁剪窗口内(包括边界上)的区域,四位二进制代码均为0。

设线段的两个端点为P1(x1,y1)和P2(x2,y2),根据上述规则,可以求出P1和P2所在区域的分区代码C1和C2。

2、判别根据C1和C2的具体值,可以有三种情况:(1)C1=C2=0,表明两端点全在窗口内,因而整个线段也在窗内,应予保留。

(2)C1&C2≠0(两端点代码按位作逻辑乘不为0),即C1和C2至少有某一位同时为1,表明两端点必定处于某一边界的同一外侧,因而整个线段全在窗外,应予舍弃。

计算机图形学实验报告实验2裁剪算法实验

计算机图形学实验报告实验2裁剪算法实验

一、实验目的:直线段的裁剪:编码裁剪算法,中点分割裁剪算法。

二、实验内容://BasicGraph.cpp//请将下列裁剪程序补充完整,并用注释说明是何种裁剪算法void Encode (int x,int y,int *code,int XL,int XR,int YB,int YT) {//请将此程序补充完整int c=0;if(x<XL) c=c|LEFT;else if(x>XR) c=c|RIGHT;if(y<YB) c=c|BOTTOM;else if(y>YT) c=c|TOP;(*code)=c;}//编码裁剪算法:void C_S_Line(POINT &p1,POINT &p2,int XL,int XR,int YB,int YT) {//请将此程序补充完整int x1,x2,y1,y2,x,y,code1,code2,code;x1=p1.x; x2=p2.x; y1=p1.y; y2=p2.y;Encode(x1,y1,&code1,XL,XR,YB,YT);Encode(x2,y2,&code2,XL,XR,YB,YT);while(code1!=0||code2!=0){if((code1&code2)!=0) return;code=code1;if(code1==0) code=code2;if((LEFT&code)!=0){x=XL;y=y1+(y2-y1)*(XL-x1)/(x2-x1);}else if((RIGHT&code)!=0){x=XR;y=y1+(y2-y1)*(XR-x1)/(x2-x1);}if((BOTTOM&code)!=0){y=YB;x=x1+(x2-x1)*(YB-y1)/(y2-y1);}else if((TOP&code)!=0){y=YT;x=x1+(x2-x1)*(YT-y1)/(y2-y1);}if(code==code1){x1=x;y1=y;Encode(x,y,&code1,XL,XR,YB,YT);}else{x2=x;y2=y;Encode(x,y,&code2,XL,XR,YB,YT);}}p1.x=x1;p1.y=y1;p2.x=x2;p2.y=y2;}int IsInArea(POINT point,int XL,int XR,int YB,int YT){//请将此程序补充完整if(point.x>=XL && point.x<=XR && point.y>YB && point.y<YT) return 1;else return 0;}int NotIntersect(POINT begin,POINT end,int XL,int XR,int YB,int YT) {//请将此程序补充完整int maxx,maxy,minx,miny;maxx=(begin.x>end.x)?begin.x:end.x;minx=(begin.x<end.x)?begin.x:end.x;maxy=(begin.y>end.y)?begin.y:end.y;miny=(begin.y<end.y)?begin.y:end.y;if(maxx<XL|| minx>XR||maxy<YB||miny>YT) return 1;else return 0;}//中点裁剪算法:POINT ClipMid(POINT begin,POINT end,int XL,int XR,int YB,int YT){//请将此程序补充完整POINT mid,temp;if(IsInArea(begin,XL,XR,YB,YT)) temp=begin;else if(NotIntersect(begin,end,XL,XR,YB,YT)) temp=begin;else{mid.x=(begin.x+end.x)/2;mid.y=(begin.y+end.y)/2;if(abs(mid.x-end.x)<=1&& abs(mid.y-end.y)<=1) temp=mid;else{if(NotIntersect(begin,mid,XL,XR,YB,YT))temp=ClipMid(mid,end,XL,XR,YB,YT);elsetemp=ClipMid(begin,mid,XL,XR,YB,YT);}}return temp;}//Liang-Barsky直线裁剪算法:void ClipParameter(POINT &p1,POINT &p2,int XL,int XR,int YB,int YT) {float u1=0.0,u2=1.0;float dx=p2.x-p1.x,dy=p2.y-p1.y;if(clipTest(-dx,p1.x-XL,&u1,&u2))if(clipTest(dx,XR-p1.x,&u1,&u2))if(clipTest(-dy,p1.y-YB,&u1,&u2))if(clipTest(dy,YT-p1.y,&u1,&u2)){if(u2<1.0){p2.x=p1.x+u2*dx;p2.y=p1.y+u2*dy;}if(u1>0.0){p1.x=p1.x+u1*dx;p1.y=p1.y+u1*dy;}}}int clipTest(float p,float q,float *u1,float *u2){float r;int remainFlag=1;if(p<0.0){r=q/p;if(r>*u2) remainFlag=0;else if(r>*u1) *u1=r;}else if(p>0.0){r=q/p;if(r<*u1) remainFlag=0;else if(r<*u2) *u2=r;}else //*p=0if(q<0.0) remainFlag=0;return remainFlag;}//逐边裁剪算法://typedef struct tRes { int yes,isIn; POINT pout;} Res;Res TestIntersect(int edge,int type,POINT p1,POINT p2){//判断p2是否在所裁剪的窗边edge的内侧,是否与p1点分别在窗边edge的异侧float dx,dy,m;Res res;int isIn=0,yes=0;POINT pout;dy=p2.y-p1.y;dx=p2.x-p1.x;m=dy/dx;switch(type){case 1: /*right*/if(p2.x<=edge){isIn=1;if(p1.x>edge)yes=1;}else if(p1.x<=edge)yes=1;break;case 2: /*bottom*/if(p2.y>=edge){isIn=1;if(p1.y<edge)yes=1;}else if(p1.y>=edge)yes=1;break;case 3: /*left*/if(p2.x>=edge){isIn=1;if(p1.x<edge)yes=1;}else if(p1.x>=edge)yes=1;break;case 4: /*top*/if(p2.y<=edge){isIn=1;if(p1.y>edge)yes=1;}else if(p1.y<=edge)yes=1;default: break;}if(yes){if((type==1) || (type==3)){ pout.x=edge;pout.y=p1.y+m*(pout.x-p1.x);}if((type==2) || (type==4)){ pout.y=edge;pout.x=p1.x+(pout.y-p1.y)/m;}}res.isIn=isIn;res.yes=yes;res.pout=pout;return res;}int clipSingleEdge(int edge,int type,int nin,POINT pin[50],POINT pout[50])/*对多边形pin与窗边edge进行裁剪,返回裁剪后的多边形pout及点数*/ {int i,k=0;POINT p;Res res;p.x=pin[nin-1].x;p.y=pin[nin-1].y;for(i=0;i<nin;i++){res=TestIntersect(edge,type,p,pin[i]);if(res.yes){ pout[k].x=res.pout.x;pout[k].y=res.pout.y;k++;} if(res.isIn){ pout[k].x=pin[i].x;pout[k].y=pin[i].y;k++;}p.x=pin[i].x;p.y=pin[i].y;}return k;}void ClipEdgePolygon(POINT ps[50],int &n,int XL,int XR,int YB,int YT) { /*对多边形ps进行逐边裁剪*/int n1=0,n2=0;POINT pt[50];n1=clipSingleEdge(XR,1,n,ps,pt);n2=clipSingleEdge(YB,2,n1,pt,ps);n1=clipSingleEdge(XL,3,n2,ps,pt);n2=clipSingleEdge(YT,4,n1,pt,ps);n=n2;}//多边形编码裁剪算法:void ClipEncodePolygon(POINT ps[50],int &n,int XL,int XR,int YB,int YT) {POINT tp[50];int k=0,m;int code1,code2,code;int x,y;for(int i=0;i<n-1;i++){Encode(ps[i].x,ps[i].y,&code1,XL,XR,YB,YT);Encode(ps[i+1].x,ps[i+1].y,&code2,XL,XR,YB,YT);code=code1;m=i;for(int j=0;j<2;j++){if((code1 & code2)!=0) //线段两端都在窗口外的同一侧{switch(code){case 1:x=XL;y=ps[m].y;break;case 2:x=XR;y=ps[m].y;break;case 4:x=ps[m].x;y=YB;break;case 5:x=XL;y=YB;break;case 6:x=XR;y=YB;break;case 8:x=ps[m].x;y=YT;break;case 9:x=XL;y=YT;break;case 10:x=XR;y=YT;break;}tp[k].x=x;tp[k].y=y;k++;}else if((code1 & code2)==0) //线段两端不在窗口的同一侧{if(code==0){tp[k]=ps[m];k++;}else if ((LEFT & code) !=0) //线段与左边界相交 {x=XL;y=ps[i].y+(ps[i+1].y-ps[i].y)*(XL-ps[i].x)/(ps[i+1].x-ps[i].x);if(y>YB && y<YT){tp[k].x=x;tp[k].y=y;k++;}}else if((TOP & code)!=0) //线段与上边界相交{y=YT;x=ps[i].x+(ps[i+1].x-ps[i].x)*(YT-ps[i].y)/(ps[i+1].y-ps[i].y);if(x>XL && x<XR){tp[k].x=x;tp[k].y=y;k++;}}else if((RIGHT & code)!=0) //线段与右边界相交 {x=XR;y=ps[i].y+(ps[i+1].y-ps[i].y)*(XR-ps[i].x)/(ps[i+1].x-ps[i].x);if(y>YB && y<YT){tp[k].x=x;tp[k].y=y;k++;}}else if((BOTTOM & code) != 0) //线段与下边界相交 {y=YB;x=ps[i].x+(ps[i+1].x-ps[i].x)*(YB-ps[i].y)/(ps[i+1].y-ps[i].y);if(x>XL && x<XR){tp[k].x=x;tp[k].y=y;k++;}}}code=code2;m++;}//for(j)}//for(i)for(i=0;i<k;i++)ps[i]=tp[i];n=k;}//函数的调用,裁剪窗口的调整//DrawView.cpp文件//裁剪窗口的调整CDrawView::CDrawView(){/************请在此函数中将裁剪窗口大小调整为长度100单位像素,宽度50单位像素的矩形********/// TODO: add construction code here//m_pWidth=1;m_pStyle=PEN_STYLE_SOLID;m_pColor=RGB(0,0,0);m_FFlag=0;m_FColor=RGB(0,0,0);m_HFlag=0;CurrentDraw=DRAW_VCLINE;m_Num=0;m_Drag=0;m_HCursor=AfxGetApp()->LoadStandardCursor(IDC_CROSS);//DrawType=0;ClipFlag=0;ClipType=-1;XL=200;XR=300;YB=150;YT=200;//XL=200;XR=500;YB=150;YT=400;ClipWindowColor=RGB(192,192,50);}void CDrawView::OnDraw(CDC* pDC){CDrawDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);// TODO: add draw code for native data hereif(ClipFlag){CPen NewPen,*pOldPen;NewPen.CreatePen(PS_DASH,1,ClipWindowColor);pOldPen=pDC->SelectObject(&NewPen);pDC->MoveTo(XL,YB);pDC->LineTo(XR,YB);pDC->LineTo(XR,YT);pDC->LineTo(XL,YT);pDC->LineTo(XL,YB);}int index;index=pDoc->GetShapeNumber();for(int i=0;i<index;i++)pDoc->GetShape(i)->Drawing(pDC);}void CDrawView::OnInitialUpdate(){CSize sizeTotal;sizeTotal.cx = 640; sizeTotal.cy = 480;SetScrollSizes(MM_TEXT, sizeTotal);// TODO: Add your specialized code here and/or call the base class }void CDrawView::OnLButtonDown(UINT nFlags, CPoint point){// TODO: Add your message handler code here and/or call defaultCClientDC dc(this);OnPrepareDC(&dc);dc.DPtoLP(&point);m_pPrev=point;m_pOrigin=point; //点击鼠标左键作为拖动绘图的第一点m_Drag=1;SetCapture();RECT rect;GetClientRect(&rect);ClientToScreen(&rect);ClipCursor(&rect);CScrollView::OnLButtonDown(nFlags, point);}//函数调用处void CDrawView::OnLButtonUp(UINT nFlags, CPoint point){// TODO: Add your message handler code here and/or call defaultif(m_Drag){m_Drag=0;ReleaseCapture();ClipCursor(NULL);CDrawDoc *pDoc=GetDocument();CShape *pShape;POINT p1,p2;if(CurrentDraw==DRAW_VCLINE || CurrentDraw==DRAW_DDALINE ||CurrentDraw==DRAW_MIDLINE || CurrentDraw==DRAW_BSHLINE){if(ClipFlag){switch(ClipType){/****************编码裁剪函数调用处*************/case CLIP_ENCODE:C_S_Line(m_pOrigin,m_pPrev,XL,XR,YB,YT); break; /****************中点分割裁剪函数调用处************/case CLIP_MIDPOINT: ClipMid(m_pPrev,m_pOrigin,XL,XR,YB,YT);p1=ClipMid(m_pPrev,m_pOrigin,XL,XR,YB,YT);p2=ClipMid(m_pOrigin,m_pPrev,XL,XR,YB,YT);m_pOrigin=p1;m_pPrev=p2;break;case CLIP_PARAMETER:ClipParameter(m_pOrigin,m_pPrev,XL,XR,YB,YT);break;}}pShape=newCLine(m_pOrigin,m_pPrev,m_pWidth,m_pStyle,m_pColor,DrawType);pDoc->AddShape(pShape);}if(CurrentDraw==DRAW_RECTANGLE){if(ClipType==CLIP_WINDOW){XL=m_pOrigin.x;XR=m_pPrev.x;YB=m_pOrigin.y;YT=m_pPrev.y;}else{pShape=newCRectangle(m_pOrigin,m_pPrev,m_pWidth,m_pStyle,m_pColor,m_FFlag,m_FColor,m_HFlag,m_Hatch);pDoc->AddShape(pShape);}}if( CurrentDraw==DRAW_VCCIRCLE || CurrentDraw==DRAW_MIDCIRCLE || CurrentDraw==DRAW_BSHCIRCLE){pShape=newCCircle(m_pOrigin,m_pPrev,m_pWidth,m_pStyle,m_pColor,m_FFlag,m_FColor,m_HFlag,m_Hatch,DrawType);pDoc->AddShape(pShape);}if(CurrentDraw==DRAW_VCELLIPSE || CurrentDraw==DRAW_MIDELLIPSE) {pShape=newCEllipse(m_pOrigin,m_pPrev,m_pWidth,m_pStyle,m_pColor,m_FFlag,m_FColor,m_HFlag,m_Hatch,DrawType);pDoc->AddShape(pShape);}pDoc->UpdateAllViews(NULL);}CScrollView::OnLButtonUp(nFlags, point);}三实验结果:四、实验总结通过这次试验使我了解到如何运用计算机程序对窗口进行剪裁,了解到编码剪裁算法直观方便,速度较快,中点分割剪裁算法不用进行乘除运算,剪裁效率高,Liang-Barsky直线裁剪算法更快。

裁剪算法设计实验报告(3篇)

裁剪算法设计实验报告(3篇)

第1篇一、实验目的本次实验旨在深入理解并掌握裁剪算法的基本原理,通过编程实现Cohen-Sutherland算法和Liang-Barsky算法,对图形进行窗口裁剪,从而提高图形处理效率,优化显示效果。

二、实验环境1. 开发环境:Visual Studio 20192. 编程语言:C++3. 图形库:OpenGL三、实验内容1. 理解裁剪算法的基本原理;2. 实现Cohen-Sutherland算法;3. 实现Liang-Barsky算法;4. 对图形进行窗口裁剪,并展示裁剪效果。

四、实验过程1. 理解裁剪算法的基本原理裁剪算法是计算机图形学中的一个重要技术,用于将一个图形或图像中不需要的部分去除,只保留需要的部分。

常见的裁剪算法有Cohen-Sutherland算法、Liang-Barsky算法等。

Cohen-Sutherland算法是一种编码线段裁剪算法,通过将线段端点相对于窗口的位置进行编码,判断线段是否与窗口相交,从而实现裁剪。

Liang-Barsky算法是一种参数化线段裁剪算法,通过计算线段参数,判断线段是否与窗口相交,从而实现裁剪。

2. 实现Cohen-Sutherland算法(1)定义窗口边界首先,定义窗口边界,包括左边界、右边界、上边界和下边界。

(2)编码线段端点将线段端点相对于窗口的位置进行编码,编码规则如下:- 如果端点在窗口内,则编码为0;- 如果端点在窗口左侧,则编码为1;- 如果端点在窗口右侧,则编码为2;- 如果端点在窗口上方,则编码为4;- 如果端点在窗口下方,则编码为8。

(3)判断线段是否与窗口相交将线段两端点的编码进行异或运算,如果结果为0,则线段与窗口相交;否则,线段与窗口不相交。

(4)裁剪线段如果线段与窗口相交,则根据端点编码,将线段分为两部分,分别进行裁剪。

3. 实现Liang-Barsky算法(1)定义窗口边界首先,定义窗口边界,包括左边界、右边界、上边界和下边界。

梁友栋-barsky算法

梁友栋-barsky算法

/** clip.cpp* This program clips the line with the given window.*/#include <windows.h>#include <GL/glut.h>#include <math.h>void myinit(void){glShadeModel (GL_FLA T);glClearColor (0.0, 0.0, 0.0, 0.0);}void myReshape(int w, int h){glViewport(0, 0, w, h);glMatrixMode(GL_PROJECTION);glLoadIdentity();if (w <= h)gluOrtho2D (0.0, 1.0, 0.0, 1.0*(GLfloat)h/(GLfloat)w);elsegluOrtho2D (0.0, 1.0*(GLfloat)w/(GLfloat)h, 0.0, 1.0);glMatrixMode(GL_MODELVIEW);}//-------------------------------// your task//-------------------------------int Clip(float p,float q,float *m,float *n){int flag=1;/*flag为标志变量,0表示舍弃,1表示可见*/ float r;if (p<0.0){r=q/p;if (r>*n)flag=0;else if (r>*m){*m=r;/*m取进入点最大参数值*/flag=1;}}else if (p>0.0){r=q/p;if (r<*m)flag=0;else if (r<*n){*n=r;/*n取离开点的最小值*/flag=1;}}else if (q<0 && p==0) //平行于边界,而且在界外的线flag=0;return flag;}void myclip()// line clipping algorithm{float dx,dy,m,n,x1,x2,y2,y3,xmin,xmax,ymin,ymax;m=0.0,n=1.0;glBegin(GL_LINES);glColor4f (0.5, 0.0, 1.0, 0.0);glV ertex2f(0.1f, 0.5f); // line startpointglV ertex2f(0.9f, 0.2f); // line endpointglEnd();x1=0.1,x2=0.9,y2=0.5,y3=0.2;dx=x2-x1;xmin=0.2,xmax=0.8,ymin=0.3,ymax=0.7;if (Clip(-dx,x1-xmin,&m,&n))if(Clip(dx,xmax-x1,&m,&n)){dy=y3-y2;if (Clip(-dy,y2-ymin,&m,&n))if (Clip(dy,ymax-y2,&m,&n)){if (n<1.0){x2=x1+n*dx;//通过n求得裁剪后的p2端点y3=y2+n*dy;}if (m>0.0){x1=x1+m*dx;//通过m求得裁剪后的p1端点y2=y2+m*dy;}glBegin(GL_LINES);glColor4f (0.0, 0.5, 0.0, 1.0);glV ertex2f( x1, y2); // clipped line startpointglV ertex2f( x2, y3); // clipped line endpointglEnd();}}}void display(void){glClear(GL_COLOR_BUFFER_BIT);// The window// ------------------------------------// you can change the window definition on yourself.// ------------------------------------//x1=0.1f,y2=0.5f,x2=0.9f,y3=0.2f;glColor4f (0.0, 1.0, 1.0, 0.75);glBegin(GL_POLYGON);glV ertex2f( 0.2f, 0.3f); // Bottom LeftglV ertex2f( 0.8f, 0.3f); // Bottom LeftglV ertex2f( 0.8f, 0.7f); // Bottom RightglV ertex2f( 0.2f, 0.7f); // Bottom RightglEnd();// ------------------------------------// please define your own line segment and draw// it here with different color and line width// ------------------------------------//-------------------------------//do the clipping in myclip() funtion//-------------------------------myclip();//min=0.2f;//max=0.8f;//min=0.3f;//max=0.7f;// ------------------------------------// please draw clipped line here with another// color and line width// ------------------------------------glFlush();}/* Main Loop* Open window with initial window size, title bar,* RGBA display mode, and handle input events.*/int main(int argc, char** argv){glutInit(&argc, argv);glutInitDisplayMode (GLUT_SINGLE | GLUT_RGBA);//define size and the relative positon of the applicaiton window on the display glutInitWindowSize (500, 500);glutInitWindowPosition (100, 100);//init the defined window with "argv[1]" as topic showed on the top the window glutCreateWindow (argv[0]);// opengl setupmyinit ();//define callbacksglutDisplayFunc(display);glutReshapeFunc(myReshape);//enter the loop for displayglutMainLoop();return 1; }。

实验四4梁友栋

实验四4梁友栋

计算机图形学实验报告实验[四]:梁友栋-Barsky直线裁剪算法学生:杨双涛学号: 201206090130班级:网络121班实验时间: 2014.11.27学院:电气与信息工程学院梁友栋-Barsky直线裁剪算法1.实验目的1、深入理解Liang-Barsky裁剪算法的原理;2、学会使用Liang-Barsky裁剪算法实现对直线段以及多边形的裁剪函数;3、比较Liang-Barsky裁剪算法与Cohen-Sutherland裁剪算法的区别,并动手实现两种算法,体会Liang-Barsky裁剪算法的优势;4、掌握Liang-Barsky裁剪算法的裁剪原理,在理解的基础上动手完成实验任务。

2、实验环境Visual C++6.03、实验原理梁友栋与Barsky提出了比Cohen-Sutherland裁剪算法速度更快的直线段裁剪算法。

该算法是以直线的参数方程为基础设计的,把判断直线段与窗口边界求交的二维裁剪问题转化为求解一组不等式,确定直线段参数的一维裁剪问题。

Liang-Barsky裁剪算法把直线段与窗口的相互位置关系划分为两种情况进行讨论:平行于窗口边界的直线段与不平行与窗口边界的直线段。

设起点为P0(x0,y0),终点坐标为P1(x1,y1)的直线段参数方程为:P=P0+t(P1-P0)展开形式为:X=x0+t(x1-x0)Y=y0+t(y1-y0)式中,0 ≤ t ≤ 1。

对于对角点(Wxl,Wyt)、(Wxr,Wyb)的矩形裁剪窗口,直线段裁剪条件如下:Wxl≤x0+t(x1-x0)≤WxrWyt≤y0+t(y1-y0)≤Wyb分解后有:t(x0-x1)≤x0-Wxlt(x1-x0)≤Wxr-x0t(y0-y1)≤y0-Wybt(y1-y0)≤Wyt-y0将△x=x1-x0,△y=y1-y0代入上式得到:t*(-△x)≤x0-Wxlt*△x≤Wxr-x0t*(-△y)≤y0-Wybt*△y≤Wyt-y0令:u1=-△x,v1=x0-Wxlu2=△x,v2=Wxr-x0u3=-△y,v3=y0-Wybu4=△y,v4=Wyt-y0则统一表示为:t*Un≤Vn,n=1,2,3,4N代表直线段裁剪时,窗口的边界顺序,n=1表示左边界;n=2表示右边界;n=3表示下边界;n=4表示上边界。

梁友栋-Barsky算法步骤

梁友栋-Barsky算法步骤


Liang-Barsky算法步骤: 算法步骤: 算法步骤 1) 令u1=0.0,u2=1.0,k=1; , , ; 2) 按参数化形式写出裁剪条件:upk≤qk 按参数化形式写出裁剪条件: k=1,2,3,4 其中, 其中, p1 = -x, q1 = x1 - xL; p2 = x, q2 = xR – x1; p3 = -y, q3 = y1 - yB; p4 = y, q4 = yT – y1. . 3) 如果pk≠0: 如果 : a) 如果pk<0,u1 = max{ u1,rk=qk/pk }; 如果p <0, b) 如果pk>0,u2 = min{ u2,rk=qk/pk }; 如果p >0, c) 如果u1>u2,则线段位于裁剪区域之外,舍弃之,转8);否则,转5); 如果 则线段位于裁剪区域之外,舍弃之, ;否则, ); 4) 如果pk=0,则表示直线平行于第k条裁剪边界(k=1,2,3,4分别对应于左, 如果 ,则表示直线平行于第 条裁剪边界( 分别对应于左, 条裁剪边界 分别对应于左 右,下,上边界). 上边界). a) 如果同时还满足qk<0,则该线段完全在裁剪边界外,舍弃之,转8);否 如果同时还满足 ,则该线段完全在裁剪边界外,舍弃之, ; 则,转5); ); 5) k++; 6) 如果k≤4,转3);否则,转7); 如果 , );否则, ); );否则 7) t∈[u1,u2]的线段就是原线段 0P1的可见部分,应当保存或显示; ∈ 的线段就是原线段P 的可见部分,应当保存பைடு நூலகம்显示; 的线段就是原线段 8) 结束. 结束.
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

河南理工大学万方科技学院课程设计报告2011 — 2012学年第二学期课程名称计算机图形学设计题目计算机图形学基本算法演示系统设计学生姓名学号专业班级网络11升—1班指导教师徐文鹏2012 年5 月28 日目录第1章设计内容与要求 (1)1.1 总体目标和要求 (1)1.2内容与要求 (1)1.2.1 直线的生成 (1)1.2.2 圆弧的生成 (1)1.2.3 线段裁剪 (2)1.2.4 多边形裁剪 (2)1.2.5 综合 (2)第2章总体设计 (3)2.1 Bresenham算法画直线 (3)2.1.1 Bresenham算法画直线理论基础 (3)2.1.2 Bresenham算法画直线原理 (3)2.2 Bresenham算法画圆 (4)2.2.1 Bresenham算法画圆理论基础 (4)2.2.2 Bresenham算法画圆原理 (5)2.3 梁友栋-Barsky算法进行线段裁剪 (6)2.3.1梁友栋-Barsky算法进行线段裁剪基本原理 (6)2.4 Sutherland-Hodgman算法进行多边形裁剪 (8)2.4.1 Sutherland—Hodgman多边形裁剪算法思想 (8)2.4.2 点在边界内侧的判断方法 (8)2.4.4 Sutherland-Hodgeman多边形裁剪算法特点 (8)第3章详细设计 (9)3.1 Bresenham算法画直线 (9)3.1.1 Bresenham 算法画线算法具体实现过程 (9)3.2 Bresenham算法画圆 (9)3.2.1 Bresenham 算法画圆核心代码 (9)3.3 梁友栋-Barsky算法进行线段裁剪 (10)3.3.1梁友栋-Barsky算法推导过程 (10)3.3.2梁友栋-Barsky算法进行线段裁剪的步骤 (11)3.4 Sutherland-Hodgman算法进行多边形裁剪 (11)3.4.1 Sutherland—Hodgman多边形裁剪算法步骤 (11)3.5将画线、画圆、线段裁剪和多边形裁剪综合 (12)第4章功能实现 (14)4.1用Bresenham算法画线测试结果 (14)4.2用Bresenham算法画圆测试结果 (14)4.3梁友栋-Barsky算法进行线段裁剪测试结果 (15)4.4 Sutherland-Hodgman算法进行多边形裁剪测试结果 (16)4.5将四种算法综合测试结果 (16)第5章总结 (17)参考文献 (18)第1章设计内容与要求1.1 总体目标和要求目标:以图形学算法为目标,深入研究。

继而策划、设计并实现一个能够表现计算机图形学算法原理的或完整过程的演示系统,并能从某些方面作出评价和改进意见。

通过完成一个完整程序,经历策划、设计、开发、测试、总结和验收各阶段,达到:1)巩固和实践计算机图形学课程中的理论和算法;2)学习表现计算机图形学算法的技巧;3)培养认真学习、积极探索的精神。

总体要求:策划、设计并实现一个能够充分表现图形学算法的演示系统,界面要求美观大方,能清楚地演示算法执行的每一个步骤。

开发环境:Viusal C++ 6.0,VC2005或其他你认为比较熟悉的环境。

1.2 内容与要求实验分为五项内容。

1.2.1 直线的生成内容:用Bresenham算法画直线要求:1)鼠标移动时,显示鼠标当前位置2)显示判别式的计算过程和下一点的选择策略3)记录生成点的坐标4)图形生成过程可以重复进行1.2.2 圆弧的生成内容:用Bresenham算法画圆要求:1)鼠标移动时,显示鼠标当前位置2)显示判别式的计算过程和下一点的选择策略3)记录生成点的坐标4)图形生成过程可以重复进行5)橡皮筋技术实现1.2.3 线段裁剪内容:用梁友栋-Barsky算法进行线段裁剪要求:1)对于线段裁剪,线段被窗口的四条边裁剪的过程要显示出来2)用橡皮筋的形式输入剪裁线段1.2.4 多边形裁剪内容:用Sutherland-Hodgman算法进行多边形裁剪要求:1)裁剪过程需先输入一多边形,然后用窗口四边裁剪的过程中要显示顶点增删过程。

2)用橡皮筋的形式输入剪裁线段1.2.5 综合内容:把前四次的实验内容整合到一起要求:第2章总体设计2.1 Bresenham算法画直线2.1.1 Bresenham算法画直线理论基础计算机是如何画直线的?简单来说,就是过各行各列像素中心构造一组虚拟的网格线,按直线从起点到终点的顺序计算各直线与歌垂直网格线的交点,然后确定各列像素中与此交点最近的像素。

真实的直线是连续的,但我们的计算机显示的精度有限,不可能真正显示连续的直线,于是我们用一系列离散化后的点(像素)来近似表现这条直线。

2.1.2 Bresenham算法画直线原理接下来的问题就是如何尽可能高效地找到这些离散的点,Bresenham直线算法就是一个非常不错的算法。

Bresenham直线算法是用来描绘由两点所决定的直线的算法,它会算出一条线段在 n 维光栅上最接近的点。

这个算法只会用到较为快速的整数加法、减法和位元移位,常用于绘制电脑画面中的直线。

是计算机图形学中最先发展出来的算法。

这个算法的流程图如下:可以看到,算法其实只考虑了斜率在0 ~ 1 之间的直线,也就是与x 轴夹角在0 度到45 度的直线。

只要解决了这类直线的画法,其它角度的直线的绘制全部可以通过简单的坐标变换来实现。

2.2 Bresenham算法画圆2.2.1 Bresenham算法画圆理论基础Bresenham画圆算法与Bresenham 直线算法一样,其基本的方法是利用判别变量来判断选择最近的像素点,判别变量的数值仅仅用一些加、减和移位运算就可以计算出来。

为了简便起见,考虑一个圆心在坐标原点的圆,而且只计算八分圆周上的点,其余圆周上的点利用对称性就可得到。

为什么只计算八分圆周上的点就可以了呢?和上面的直线算法类似,圆也有一个“八对称性”,如下图所示。

显然,我们只需要知道了圆上的一个点的坐标(x, y) ,利用八对称性,我们马上就能得到另外七个对称点的坐标。

2.2.2 Bresenham算法画圆原理和直线算法类似,Bresenham画圆算法也是用一系列离散的点来近似描述一个圆,如下图。

Bresenham画圆算法的流程图如下。

可以看到,与画线算法相比,画圆的循环中用到了整数的乘法,相对复杂了一些。

2.3 梁友栋-Barsky算法进行线段裁剪2.3.1梁友栋-Barsky算法进行线段裁剪基本原理我们知道,一条两端点为P1(x1,y1)、P2(x2,y2)的线段可以用参数方程形式表示:x= x1+ u·(x2-x1)= x1+ u·Δx,y= y1+ u·(y2-y1)= y1+ u·Δy式中,Δ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)所确定的窗口内,那么下式成立:xwmin≤x1+ u·Δx≤xwmax,ywmin≤y1+ u·Δy≤ywmax这四个不等式可以表示为:u·pk ≤qk ,k=1,2,3,4其中,p、q定义为p1=-Δx,q1=x1-xwminp2= Δx,q2=xwmax-x1p3=-Δy,q3=y1-ywminp4= Δy,q4=ywmax-y1可以知道:任何平行于窗口某边界的直线,其pk=0,k值对应于相应的边界(k=1,2,3,4对应于左、右、下、上边界)。

如果还满足qk<0,则线段完全在边界外,应舍弃该线段。

如果pk=0并且qk≥0,则线段平行于窗口某边界并在窗口内,见图中所示。

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计算出来。

2.4 Sutherland-Hodgman算法进行多边形裁剪2.4.1 Sutherland—Hodgman多边形裁剪算法思想该算法的基本思想是每次用窗口的一条边界及其延长线来裁剪多边形的各边。

多边形通常由它的顶点序列来表示,经过裁剪规则针对某条边界裁剪后,结果形成新的顶点序列,又留待下条边界进行裁剪,直到窗口的所有边界都裁剪完毕,算法形成最后的顶点序列,才是结果多边形(它可能构成一个或多个多边形)。

当多边形一个顶点Pi相对于窗口某条边界及其延长线进行剪裁时,不外乎下列四种情况(即裁剪规则):1、顶点Pi在内侧,前一顶点Pi-1也在内侧,则将Pi纳入新的顶点序列;2、顶点Pi在内侧,前一顶点Pi-1在外侧,则先求交点Q,再将Q、Pi依次纳入新的顶点序列;3、顶点Pi在外侧,前一顶点Pi-1在内侧,则先求交点Q,再将Q纳入新的顶点序列;4、顶点Pi与前一顶点Pi-1均在外侧,则顶点序列中不增加新的顶点。

2.4.2 点在边界内侧的判断方法为了判断点是否在边界内侧可用坐标比较法和更通用的向量叉积符号判别法。

1、坐标比较法将点的某个方向分量与边界进行比较。

例如,判断某点是否在下边界内侧,用条件判别式: if(p[i][1]>=ymin) 即可。

2、向量叉积法为简单计,测试点表示为P点。

假设窗口边界方向为顺时针,如图中所示,对于其中任一边界向量,从向量起点A向终点B看过去:如果被测试点P在该边界线右边(即内侧),AB×AP的方向与X-Y平面垂直并指向屏幕里面,即右手坐标系中Z轴的负方向。

反过来,如果P在该边界线的左边(即外侧),这时AB×AP的方向与X-Y平面垂直并指向屏幕外面,即右手坐标系中Z轴的正方向。

相关文档
最新文档