计算机图形学实验报告-二维裁剪

合集下载

计算机图形学-图形变换与裁剪-二维线段裁剪

计算机图形学-图形变换与裁剪-二维线段裁剪
裁剪边内侧的原顶点; 多边形的边与裁剪边的交点。
❖ 顺序连接。 几点说明: 裁剪算法采用流水线方式,适合硬件实现。 可推广到任意凸多边形裁剪窗口
32
Sutherland-Hodgman算法-4/4
存在的问题
❖ 逐边裁剪要求裁剪窗口为凸多边形,那么凹多边形窗口怎么办?
❖ 逐边裁剪法对凹多边形裁剪时,裁剪后分裂为几个多边形, 这几个多边形沿边框产生多余的线段?
裁剪算法的线段可见性测试方法,直至找到每段线段与窗口边界线的 交点或分割子段的长度充分小可视为一点为止
❖ 取中点Pm=(P1+P2)/2。
P2
P2
P1
从P1点出发找距P1最近的可见点
Pm
P1
用P1Pm代替P1P2
P2 Pm
P1
用PmP2代替P1P2
18
1.直线段裁剪(13/18) 中点分割法
❖ 优点:
裁剪结果区域的边界由两部分构成:
1. SP的部分边界
2. CP的部分边界
且在交点处,边界发生交替
即由SP边界转至CP边界
或由CP边界转至SP边界
36
Weiler-Atherton算法-4/7
如果SP与CP有交点,则交点成对出现,
它们被分为如下两类:
❖进点:SP边界由此进入CP
如,I1,I3, I5, I7, I9, I11
当前裁剪边
当前裁剪边
当前裁剪边
当前裁剪边
可见一侧 Pi+1
可见一侧
可见一侧
可见一侧
Pi
Pi+1
Pi I
Pi
Pi+1
Pi+1
Pi
I
窗口
(a) 输出Pi+1

计算机图形学二维图形的裁剪

计算机图形学二维图形的裁剪
所示,对于其中任一边界向量,从向量起点A向终点B看过去: 如果被测试点P在该边界线右边(即内侧),AB×AP的方向与X-Y平面
垂直并指向屏幕里面,即右手坐标系中Z轴的负方向。 反过来,如果P在该边界线的左边(即外侧),这时AB×AP的方向与X-
Y平面垂直并指向屏幕外面,即右手坐标系中Z轴的正方向。 设:点P(x,y)、点A(xA,yA)、点B(xB,yB), 向量AB={(xB-xA),(yB-yA)}, 向量AP={(x-xA),(y-yA)}, 那么AB×AP的方向可由下式的符号来确定:
依次下去,相对于第三条、第四条边界线进行裁剪,最后输出的多边 形顶点序列即为所求的裁剪好了的多边形。如下图所示。
7.3.1 Sutherland-Hodgeman多边形裁剪
新的多边形顶点序列产生规则: 在用窗口一条边界及其延长线裁剪一个多边形时,该边界线把平面分
成两个部分:一部分称为边界内侧;另一部分称为边界外侧。 如下图所示,依序考虑多边形的各条边。假设当前处理的多边形的边为
V=(xB-xA)·(y-yA)-(x-xA)·(yB-yA)
(3-14)
因此,当V≤0时,P在边界线内侧; 而V>0时,P在边界线外侧。
练习
Sutherland-Hodgeman多边形裁剪中,常用向量叉积法来测试当前点P是 否在边界内侧。已知窗口边界A(30,100)、B(40,180),某点P(50, 300),请 问点P在边界内侧吗?
7.3 多边形的裁剪
多边形裁剪的常用算法 1.Sutherland-Hodgeman多边形裁剪 2.Weiler-Atherton任意多边形裁剪
7.3.1 Sutherland-Hodgeman多边形裁剪
Sutherland-Hodgman算法也叫逐边裁剪法,该算法是萨瑟兰德 (I.E.Sutherland)和霍德曼(Hodgman)在1974年提出的。这种算法采用了 分割处理、逐边裁剪的方法。 一、Sutherland-Hodgeman多边形裁剪算法思想:

计算机图形学-图形变换与裁剪-二维线段裁剪

计算机图形学-图形变换与裁剪-二维线段裁剪
v 若是进点:则沿SP边所示方向收集顶点序列。 v 若是出点:则从此点开始,检测CP的边所
示方向收集顶点序列。 v 如此交替沿两个多边形的边行进。直至回到
跟踪的起始点为止。
38
Weiler-Atherton算法-6/7
S2
C2
I2
I3
主多边形表
裁剪多边形CP
S1
C3
开始 I1
I2
I1
S3
I4
S4
S2 I3
U
S
ymin P1
A
T
L
R
xmin
P2 xmax
ymax P4
P3
B
U
S
ymin P1
A
P2
T
L xmiRn
xmax
22
1.直线段裁剪(16/18)
v 当Q为空集时,线段AB不可能在窗口中有可见线段。 v 当Q不为空集时,Q可看成是一个一维窗口。
v 存在可见线段的充要条件


不为空集 。
ymax P4
为提高效率,该算法强调: l 快速判断情形(1)(2); l 减少情形(3)的求交次数和求交所需的计算量。
11
1.直线段裁剪(8/18)
Cohen-Sutherland 算法
算法步骤:
1. 判别线段两端点是否都落在窗口内,如果是,则线 段完全可见,转至第4步;
2. 判别线段是否为显然不可见,如果是,则裁剪结束, 转至第4步 ;
C1 C2 C3 II45 C4 I8 I1 结束 C1 C5 I2
I7 C6 I6 I3 结束
C7
C8 C5
40
v 分割处理策略:
将多边形关于矩形窗口的裁剪分解为多边形关于窗口四边所 在直线的裁剪。

二维图形的裁剪1

二维图形的裁剪1

7.2.1 Cohen-Sutherland算法
2、判别 根据C1和C2的具体值,可以有三种情况: (1)C1=C2=0,表明两端点全在窗口
内,因而整个线段也在窗内,应予保留。
(2)C1&C2≠0(两端点代码按位作逻辑 乘不为0),即C1和C2至少有某一位同时为1,
表明两端点必定处于某一边界的同一外侧,因
Cohen-Sutherland 算法 (编码算法)
算法思想:
第一步 判别线段两端点是否都落在窗口内,如果是, 则线段完全可见;否则进入第二步; 第二步 判别线段是否为显然不可见,如果是,则裁 剪结束;否则进行第三步 ; 第三步 求线段与窗口边延长线的交点,这个交点将 线段分为两段,其中一段显然不可见,丢弃。 对余下的另一段重新进行第一步,第二步判断, 直至结束
裁剪过程是递归的。
7.2.1 Cohen-Sutherland算法
二、Cohen-Sutherland算法步骤:
1、分区编码 延长裁剪边框将二维平面分成九个区域,每个区域各用一个四位二进 制代码标识。各区代码值如图中所示。 四位二进制代码的编码规则是:
(1)第一位置1:区域在左边界外侧 (2)第二位置1:区域在右边界外侧 (3)第三位置1:区域在下边界外侧 (4)第四位置1:区域在上边界外侧 裁剪窗口内(包括边界上)的区域,四位二进制代码均为0。 设线段的两个端点为P1(x1,y1)和P2(x2,y2),根据上述规则, 可以求出P1和P2所在区域的分区代码C1和C2。
7.2.1 Cohen-Sutherland算法
一、Cohen-Sutherland算法思想: 该算法也称为编码算法,首先对线段的两个端点按所在的 区域进行分区编码,根据编码可以迅速地判明全部在窗口内的 线段和全部在某边界外侧的线段。只有不属于这两种情况的线 段,才需要求出线段与窗口边界的交点,求出交点后,舍去窗 外部分。 对剩余部分,把它作为新的线段看待,又从头开始考虑。 两遍循环之后,就能确定该线段是部分截留下来,还是全部舍 弃。

计算机图形学_第八章_开窗口及二维裁剪

计算机图形学_第八章_开窗口及二维裁剪

8.1.2 窗口与视区
考察一个图形时,采用两种模型:
•物理模型,它是用户在世界坐标系中描述物体的图形; •逻辑模型,也就是在显示器上呈现的物体的图形.它是
在设备坐标系中描述的。
世界坐标系中描述物体的图形可能相当复杂:
•只能在显示器上显示局部的内容,以使用户能清晰地观
察其细节部分
•用户可能只对图形的某一区域感兴趣,因此也只需要显
若x<xl,则D0=1,否则D0=0; 若x>xr,则D1=1,否则D1=0; 若y<yb,则D2=1,否则D2=0; 若y>yt,则D3=1,否则D3=0。
1001 0001 0101
1000 0000 0100
1010 0010 0110
任何位赋值为1,代表端点落在相应的位置上,否则该位为0。若端点在 裁剪矩形内,区域码为0000。如果端点落在矩形的左下角,则区域码为 0101,其它类推。
Cohen-Sutherland算法

裁剪 裁剪一条线段时,先求出端点p1和p2的编码code1和code2,然后:
1001
0001
1000
0000
1010
0010
0101

0100
0110
(1)若code1|code2=0,对直线段应简取之。 (2)若code1&code2≠0,对直线段可简弃之。
Lecture 8
开窗口及二维裁剪
概述
我们把用一观察窗口有选择地显示物体的某一部分称为 开窗口技术,如果要求删除显示区域之外的画面部分则 称为裁剪,用开窗口技术不但可灵活地显示物体的各个 部分,还可通过动态地改变画面的大小及位置,产生某 些特殊的显示效果。

图形学二维裁剪实验报告

图形学二维裁剪实验报告

专业班级:学号:姓名:一、试验名称:二维裁剪二、试验目的:在二维观察中,需要在观察坐标系下对窗口进行裁剪,即只保留窗口内的那部分图形,去掉窗口外的图形。

二维裁剪是用计算机生成图形最基本的技能,通过本实验使学生掌握如何用计算机进行二维裁剪并熟悉开发环境。

三、实验原理:算法源代码:void CMyView::OnDraw(CDC* pDC){CMyDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);// TODO: add draw code for native data herePoint FrameLT,FrameRB;Point P[5];FrameLT.x=150;FrameLT.y=150;FrameRB.x=320;FrameRB.y=320;pDC->Rectangle((int)FrameLT.x,(int)FrameLT.y,(int)FrameRB.x,(int)FrameRB. y);for(int i = 0; i < 5; i++){P[i].x = (float)(260 + 150*cos(72*i*PI/180) +0.5);P[i].y = (float)(260 + 150*sin(72*i*PI/180) +0.5);}专业班级:学号:姓名:pDC->MoveTo((int)P[0].x,(int)P[0].y);pDC->LineTo((int)P[2].x,(int)P[2].y);pDC->LineTo((int)P[4].x,(int)P[4].y);pDC->LineTo((int)P[1].x,(int)P[1].y);pDC->LineTo((int)P[3].x,(int)P[3].y);pDC->LineTo((int)P[0].x,(int)P[0].y);}void CMyView::Code(Point FrameLT,Point FrameRB,Point P,unsigned char *Flag){unsigned char flag=0;if(P.x<FrameLT.x) flag+=1;if(P.x>FrameRB.x) flag+=2;if(P.y>FrameRB.y) flag+=4;if(P.y<FrameLT.y) flag+=8;(*Flag)=flag;}void CMyView::Clipping(Point FrameLT,Point FrameRB,Point LineSP,Point LineEP){CClientDC dc(this);unsigned char flagSP,flagEP,flagAND,flagOR;double k=(LineEP.y-LineSP.y)/(LineEP.x-LineSP.x);Code(FrameLT,FrameRB,LineSP,&flagSP);Code(FrameLT,FrameRB,LineEP,&flagEP);专业班级:学号:姓名:flagAND=flagSP & flagEP;if(flagAND!=0)return;while(flagSP!=0||flagEP!=0){flagOR=flagSP|flagEP;if((flagOR&0x01)==1){if((flagSP&0x01)==1){LineSP.y=(float)(LineSP.y+k*(FrameLT.x-LineSP.x)); LineSP.x=FrameLT.x;Code(FrameLT,FrameRB,LineSP,&flagSP);}else{LineEP.y=(float)(LineEP.y+k*(FrameLT.x-LineEP.x)); LineEP.x=FrameLT.x;Code(FrameLT,FrameRB,LineEP,&flagEP);}}if((flagOR&0x02)==2){if((flagSP&0x02)==2){LineSP.y=(float)(LineSP.y+k*(FrameRB.x-LineSP.x)); LineSP.x=FrameRB.x;专业班级:学号:姓名:Code(FrameLT,FrameRB,LineSP,&flagSP);}else{LineEP.y=(float)(LineEP.y+k*(FrameRB.x-LineEP.x)); LineEP.x=FrameRB.x;Code(FrameLT,FrameRB,LineEP,&flagEP);}}if((flagOR&0x04)==4){if((flagSP&0x04)==4){LineSP.x=(float)(LineSP.x+(FrameRB.y-LineSP.y)/k); LineSP.y=FrameRB.y;Code(FrameLT,FrameRB,LineSP,&flagSP);}else{LineEP.x=(float)(LineEP.x+(FrameRB.y-LineEP.y)/k); LineEP.y=FrameRB.y;Code(FrameLT,FrameRB,LineEP,&flagEP);}}if((flagOR&0x08)==8){专业班级:学号:姓名:if((flagSP&0x08)==8){LineSP.x=(float)(LineSP.x+(FrameLT.y-LineSP.y)/k); LineSP.y=FrameLT.y;Code(FrameLT,FrameRB,LineSP,&flagSP);}else{LineEP.x=(float)(LineEP.x+(FrameLT.y-LineEP.y)/k); LineEP.y=FrameLT.y;Code(FrameLT,FrameRB,LineEP,&flagEP);}flagAND=flagSP&flagEP;if(flagAND!=0)return;}dc.MoveTo((int)LineSP.x,(int)LineSP.y);dc.LineTo((int)LineEP.x,(int)LineEP.y);}}void CMyView::OnCut() //裁剪{// TODO: Add your command handler code hereCClientDC dc(this);CPen pen(PS_SOLID,1,RGB(255,255,255));CPen *pOldpen = dc.SelectObject(&pen);专业班级:学号:姓名:CBrush*pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));dc.SelectObject(pBrush);Point FrameLT,FrameRB;Point P[5];FrameLT.x=150;FrameLT.y=150;FrameRB.x=320;FrameRB.y=320;dc.Rectangle((int)FrameLT.x,(int)FrameLT.y,(int)FrameRB.x,(int)FrameR B.y);for(int i = 0; i < 5; i++){P[i].x = (float)(260 + 150*cos(72*i*PI/180) +0.5);P[i].y = (float)(260 + 150*sin(72*i*PI/180) +0.5);}dc.MoveTo((int)P[0].x,(int)P[0].y);dc.LineTo((int)P[2].x,(int)P[2].y);dc.LineTo((int)P[4].x,(int)P[4].y);dc.LineTo((int)P[1].x,(int)P[1].y);dc.LineTo((int)P[3].x,(int)P[3].y);dc.LineTo((int)P[0].x,(int)P[0].y);dc.SelectObject(pOldpen);专业班级:学号:姓名:dc.Rectangle((int)FrameLT.x,(int)FrameLT.y,(int)FrameRB.x,(int)FrameR B.y);Clipping(FrameLT,FrameRB,P[0],P[2]);Clipping(FrameLT,FrameRB,P[2],P[4]);Clipping(FrameLT,FrameRB,P[4],P[1]);Clipping(FrameLT,FrameRB,P[1],P[3]);Clipping(FrameLT,FrameRB,P[3],P[0]);}四、实验总结:裁剪处理的主要步骤是:①图元关于窗口内外关系的判别;②图元与窗口的求交。

计算机图形学第6章二维图形的裁剪

计算机图形学第6章二维图形的裁剪
第七章 二维图形的裁剪
• 重点:掌握二维图形点、线段、多边形和字符的裁剪算法 。
• 难点:理解二维图形的裁剪算法思想并且用C语言进行算法 的实现。
一、裁剪的意义 为了描述图形对象,我们必须存储它的全部信息,但有时为了达到分 区描述或重点描述某一部分的目的,往往将要描述的部分置于一个窗口内, 而将窗口外的部分“剪掉”,这个处理过程叫做裁剪,裁剪在计算机图形 处理中具有十分重要的意义。 裁剪实质上是从数据集合中抽取信息的过程,这个过程是通过一定的 计算方法来实现。
7.2.2 中点分割算法
二、中点分割算法实现: 1、将直线的两端点P1、P2编码得:C1、C2; 2、判别 根据C1和C2的具体值,可以有三种情况: (1)C1=C2=0,表明两端点全在窗口内,因而整个线段也在窗内, 应予保留。 (2)C1&C2≠0(两端点代码按位作逻辑乘不为0),即C1和C2至少 有某一位同时为1,表明两端点必定处于某一边界的同一外侧,因而整个线 段全在窗外,应予舍弃。 (3)不属于上面两种情况,均需要求交点。
如果上面四个不等式中任何一个不满足,则点(x,y)位于窗口之 外。 对于任意多边形窗口,需要根据多边形内点的判别准则进行判断。
7.2 线段的裁剪
直线段的裁剪比点复杂,其裁剪方法又是多边形裁剪和三维图形裁剪的 基础。 一、直线裁剪的基本思想 判断直线与窗口的位置关系: 1.确定直线是完全可见; 2.部分可见; 3.还是完全不可见。 对部分可见线段,求出它与窗口边界的交点,并将窗口内的线段输出。
一、中点分割算法思想: 1、中点公式
7.2.2 中点分割算法
2、中点分割法求交点的规则 如图中所示,当线段P1P2求出中点P后,舍弃线段的哪部分,由下面 两条规则决定:
中点分割法求交点规则

计算机图形学中的二维裁剪算法研究

计算机图形学中的二维裁剪算法研究

计算机图形学中的二维裁剪算法研究计算机图形学研究的是如何在计算机上制图,根据研究对象的不同又分为二维图形学和三维图形学。

二维图形学研究的范畴是点,线,面。

本文就是介绍计算机图形学中的众多基本算法之一的二维剪裁算法。

在二维剪裁算法中,椭圆形窗口线剪裁算法又是应用最为广泛的算法之一,所以将是本文重点论述的对象。

标签:计算机图形学;二维剪裁算法;椭圆形窗口线剪裁算法计算机图形学中的基本算法对于计算机图形学应用于实践有着重要的作用,而且算法需要时时更新才能够发挥出计算机图形学在实践中的作用。

本文对计算机二维剪裁算法进行介绍,并对其中的椭圆窗口线剪裁算法进行着重的研究分析,探讨如何使该算法更加的稳定高效,方便易行。

算法可以指导人们的工作与生活,所以笔者在本文通过坐标分析设计出一个算法以供读者参考。

1 二维剪裁算法的基本介绍剪裁算法是计算机图形学中的基础算法之一。

剪裁在日常生活和工作中的应用十分广泛,最典型的一个应用就是对整体场景中的局部目的物进行剪裁。

剪裁的过程其实就是将场景中的目的物标记圈出来,一般为矩形窗口框圈出。

矩形窗口框为闪动的虚线框,可以根据剪裁的目的物大小随意变换矩形框的大小。

此外具体说来,剪裁算法还有其他的形式。

如:点剪裁,线段剪裁,多边形剪裁,曲线及文字剪裁等。

现在笔者再详细介绍二维剪裁算法。

二维剪裁算法分为两种,一种是对线段的剪裁,一种是对多边形的剪裁。

因为线段和多边形往往是二维平面中的图形,故而使用二维剪裁算法对其进行剪裁。

目前对该领域的研究已经取得了很丰硕的成果,已经有很多成熟也高效实用的二维剪裁算法。

详细地来说,这些经典的算法有Cyrus—berk二维剪裁算法,Cohen—Sutherland二维多边形剪裁算法等等。

2 椭圆形窗口线剪裁算法的简介在计算机图形学中,椭圆形窗口线剪裁算法是十分重要的一种基础算法。

该算法之所以十分重要,笔者总结为两点原因:首先椭圆形是几何图形中最基础的图形之一,其次在我们的日常生活和工作当中有很多地方的剪裁工作是更适合椭圆形的(我们生活与工作之中,很少有标准的圆形目的物去剪裁,更多情况下是不规则的图像剪裁,而椭圆形可以更好的,更多的剪裁出合适的目的物)。

计算机图形学第二次实验报告

计算机图形学第二次实验报告

计算机图形学实验报告2015-2016学年第一学期班级计自1302 学号姓名一.实验内容与实验步骤1.实验内容实现一个二维或三维裁剪算法,或实现一个Bezier曲线或Bezier曲面算法,并能够实现曲线曲面的形状修改。

2.主要思路每一裁剪窗口边界将二维空间划分成内部和外部的两个半空间。

一旦给所有的的线段端点建立了区域码,就可以快速判断哪条线段完全在裁剪窗口之内,哪条线段完全在窗口之外。

3.部分源代#include"stdafx.h"#include<GL/glut.h>#include<math.h>#include<GL/gl.h>#include<stdio.h>#include<stdlib.h>int flag;void setPixel(GLintx,GLint y){glBegin(GL_POINTS);glVertex2i(x, y);glEnd();}/* Bresenham line-drawing procedure for |m| < 1.0. */void lineBres (float x0, float y0, float xEnd, float 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;/* Determine which endpoint to use as start position. */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);}}class wcPt2D {public:GLfloat x, y;};inline GLint round (const GLfloat a) { return GLint (a + 0.5); }/* Define a four-bit code for each of the outside regions of a * rectangular clipping window.*/const GLintwinLeftBitCode = 0x1;const GLintwinRightBitCode = 0x2;const GLintwinBottomBitCode = 0x4;const GLintwinTopBitCode = 0x8;inline GLint inside (GLint code) { return GLint (!code); } inline GLint reject (GLint code1, GLint code2){ return GLint (code1 & code2); }inline GLint accept (GLint code1, GLint code2){ return GLint (!(code1 | code2)); }GLubyte encode (wcPt2D pt, wcPt2D winMin, wcPt2D winMax){GLubyte code = 0x00;if (pt.x<winMin.x)code = code | winLeftBitCode;if (pt.x>winMax.x)code = code | winRightBitCode;if (pt.y<winMin.y)code = code | winBottomBitCode;if (pt.y>winMax.y)code = code | winTopBitCode;return (code);}void swapPts (wcPt2D * p1, wcPt2D * p2){wcPt2Dtmp;tmp = *p1; *p1 = *p2; *p2 = tmp;}void swapCodes (GLubyte * c1, GLubyte * c2){GLubytetmp;tmp = *c1; *c1 = *c2; *c2 = tmp;}void lineClipCohSuth (wcPt2D winMin, wcPt2D winMax, wcPt2D p1, wcPt2D p2) {GLubyte code1, code2;GLint done = false, plotLine = false;GLfloat m;while (!done) {code1 = encode (p1, winMin, winMax);code2 = encode (p2, winMin, winMax);if (accept (code1, code2)) {done = true;plotLine = true;}elseif (reject (code1, code2))done = true;else {/* Label the endpoint outside the display window as p1. */if (inside (code1)) {swapPts (&p1, &p2);swapCodes (&code1, &code2);}/* Use slope m to find line-clipEdge intersection. */if (p2.x != p1.x)m = (p2.y - p1.y) / (p2.x - p1.x);if (code1 &winLeftBitCode) {p1.y += (winMin.x - p1.x) * m;p1.x = winMin.x;}elseif (code1 &winRightBitCode) {p1.y += (winMax.x - p1.x) * m;p1.x = winMax.x;}elseif (code1 &winBottomBitCode) {/* Need to update p1.x for nonvertical lines only. */if (p2.x != p1.x)p1.x += (winMin.y - p1.y) / m;p1.y = winMin.y;}elseif (code1 &winTopBitCode) {if (p2.x != p1.x)p1.x += (winMax.y - p1.y) / m;p1.y = winMax.y;}}}if (plotLine)lineBres (round (p1.x), round (p1.y), round (p2.x), round (p2.y)); void myDisplay(){wcPt2DwinMin , winMax , p1 , p2;winMin.x=100; winMin.y=200;winMax.x=400; winMax.y=400;p1.x=50; p1.y=50;p2.x=450; p2.y=450;glClear(GL_COLOR_BUFFER_BIT);glColor3f (1.0f, 0.0f, 0.0f);glRectf(winMin.x ,winMin.y ,winMax.x,winMax.y);glColor3f (1.0f, 1.0f, 1.0f);if (flag){lineClipCohSuth (winMin, winMax,p1,p2);}else{glBegin(GL_LINES);glVertex2i(p1.x,p1.y);glVertex2i(p2.x,p2.y);glEnd();}glFlush();}void Init(){glClearColor(0.0, 0.0, 0.0, 0.0);glMatrixMode (GL_PROJECTION);gluOrtho2D (0.0, 640.0, 0.0, 480.0);}void Reshape(int w, int h){glViewport(0, 0, (GLsizei) w, (GLsizei) h);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D(0.0, (GLdouble) w, 0.0, (GLdouble) h);}void keyboard(unsignedchar key, int x, int y) {if (key=='c' || key=='C') flag=true;if (key=='r' || key=='R') flag=false;glutPostRedisplay();}int main(int argc, char *argv[]){glutInit(&argc, argv);glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);glutInitWindowPosition(100, 100);glutInitWindowSize(640, 480);glutCreateWindow("Cohen-Sutherland直线裁减算法,C 键裁减,R键复原"); Init();glutDisplayFunc(myDisplay);glutReshapeFunc(Reshape);glutKeyboardFunc(keyboard);glutMainLoop();return 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裁剪算法

计算机图形学实验报告实验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)定义窗口边界首先,定义窗口边界,包括左边界、右边界、上边界和下边界。

计算机图形学中二维裁剪算法的研究

计算机图形学中二维裁剪算法的研究

计算机图形学中二维裁剪算法的研究随着计算机技术的发展,计算机图形学也日益成熟。

在我们的日常生活中,也成了随处可见的必需部分。

在医学、娱乐、图形艺术、商业、教育培训、科学工程等众多领域,计算机图形学的应用非常普遍。

计算机图形学主要研究的是在计算机中构造图形,将用数学模型描述的图形数据采用合适的算法转换为屏幕上图形的显示。

计算机图形学学科研究的对象为二维图形学和三维图形学及其显示和变化情况。

点、线、面为二维图形学范畴,几何体和场等数学构造方法则为三维图形学范畴。

现在,计算机图形学的一些基本算法已经形成了固化在硬件中的规范软件包,这个学科也日趋成熟和完善。

但是依然有很多算法还需要不断的改进才能应用到实际中,而裁剪算法就是其中之一。

本文主要对二维图形裁剪中的椭圆形窗口裁剪算法进行了研究,使其具有较高的效率和稳定性。

标签:计算机图形学裁剪算法椭圆形窗口线裁剪算法1 裁剪概述裁剪算法,简称裁剪,是计算机图形学中很多重要问题的基础,它就是从数据集合中识别指定区域内或指定区域外图形部分的过程。

裁剪用途很广泛,最典型的就是确定场景中位于指定区域内的景物部分。

其中,指定区域成为裁剪窗口,一般为矩形,由四条边组成,上、下、左、右,即:(Xl,Yb),(Xr,Yt)。

实质上来说,裁剪就是确定哪些多边形等几何体位于裁剪窗口内。

对于点(X,Y),只要判断两对不等式:Xl≤X≤Xr,Yb≤Y≤Yt即可。

如果四个点坐标的不等式都不成立,则这个点在矩形窗口外,否则,在窗口内。

有一种最简单的裁剪方法,就是将所有图形扫描转换成点,然后在进行判断。

但是这种方法时间消耗太大,非常不可取。

倘若将全部在窗口外的图形完全排除而不进行扫描转换,则时间上面可以高效很多,故一般采用先裁剪再扫描的方法。

按裁减对象来分,裁剪算法大概分为如下几种:点裁剪、直线段裁剪、区域多边形裁剪、曲线裁剪和文字裁剪。

裁剪有多方面应用,主要包括:使用实体造型创建对象、在三维视图中标示出可见面、对图形的一部分进行删除、复制或移动操作、防止图形边界混淆、从特定场景中抽取指定部分等。

计算机图形学实验四 :裁剪

计算机图形学实验四 :裁剪

贵州大学实验报告学院:计算机科学与技术专业:计算机科学与技术班级:计科131glColor3f(0.0f, 1.0f, 0.0f);glVertex2f(x1, y1);glEnd();}//矩形的结构体typedef struct Rectangle{float xmin;float xmax;float ymin;float ymax;} Rectan;Rectan rect;int x0, y0, x1, y1;//求出坐标点的Cohen-Sutherland编码int CompCode(int x, int y, Rectan rect) {int code = 0x00;if (y < rect.ymin){code = code | 4;}if (y>rect.ymax){code = code | 8;}if (x>rect.xmax){code = code | 2;}if (x<rect.xmin){code = code | 1;}return code;}//裁剪直线int cohensutherlandlineclip(Rectan rect, int& x0, int& y0, int& x1, int& y1) {int accept = 0, done = 0;float x, y;int code0, code1, codeout;int x00 = x0, y00 = y0, x11 = x1, y11 = y1;code0 = CompCode(x0, y0, rect);code1 = CompCode(x1, y1, rect);//直线全部在矩形框内部,应保留if (!(code0 | code1)){accept = 1;done = 1;}//直线和矩形不相交,并且划直线的两点在矩形同侧(上、下、右。

计算机图形学 二维裁剪算法Cohen_Sutherland的实现

计算机图形学 二维裁剪算法Cohen_Sutherland的实现

实验六二维裁剪算法Cohen_Sutherland的实现一、实验目的:理解并掌握直线裁剪算法。

使用Visual C++实现二维直线的裁剪的Cohen_Sutherland算法。

对窗口进行编码,并实现相应的裁剪函数。

二、实验内容及要求:1、要求用消息映射的方式,绘制出一个裁剪窗口,大小为200×150象素;2、按照例程的步骤画出3条典型线段,分别对应于完全在裁剪窗口内、完全在裁剪窗口外、穿过裁剪窗口三种情况,并按照本实验例程的方法用颜色分别表示出裁剪后的情况;3、按要求撰写实验报告,写出实验心得,并在实验报告中附上程序的核心算法代码。

三、实验设备:微机,Visual C++6.0四、实验内容及步骤:1、打开VC,新建一个MFC Appwizard项目,选择创建单文档工程(SDI工程)。

假设工程名为Clip。

如图1和图2所示。

图1图22、在图2的界面上点击Finish,完成工程的创建。

3、在视图类ClipView中定义变量CRect rect; 用于记录裁剪窗口的位置;4、在ClipView.cpp文件中定义四个宏,记录裁剪窗口的上下左右四个位置:#define LEFT 100#define RIGHT 300#define TOP 150#define BOTTOM 3105、在视图类的构造函数中为rect赋值;CClipView::CClipView(){// TODO: add construction code hererect = CRect(LEFT, TOP, RIGHT, BOTTOM);}6、在视图类(类CFillView中)的OnDraw()函数中绘制裁剪矩形,OnDraw函数的代码如下:void CClipView::OnDraw(CDC* pDC){CClipDoc* pDoc = GetDocument();ASSERT_V ALID(pDoc);// TODO: add draw code for native data herepDC->Rectangle(&rect);}7、在视图类(类CFillView中)添加成员函数int Encode(int x, int y),该函数用于对线段的两个顶点进行Cohen_Sutherland编码。

计算机图形学 实验四 二维图形的裁剪

计算机图形学 实验四 二维图形的裁剪

西北农林科技大学实习报告学院名称:理学院专业班级:姓名:学号:课程:计算机图形学实验报告日期:第十五周实验四二维图形的裁剪一、实验目的1)加深直线段的剪裁算法的理解。

2)熟练掌握一种裁剪算法的编程方法。

二、实验步骤1)分析直线段和矩形窗口的位置关系,选定比较合理算法流程。

2)画出程序流程图。

3)编写程序的源程序。

4)编辑源程序并进行调试。

5)进行特殊模式的运行测试,并结合情况进行调整。

三、实验内容1)在编码算法、中点分割算法、Liang-Barsky算法三种中任选一种作为编程模型。

2)编写直线段裁剪的源程序。

3)建议有能力的学生编写多边形裁剪程序。

4)在计算机上编辑编译运行,实现直线段的裁剪。

原理1.直线和窗口的关系:直线和窗口的关系可以分为如下3类:(1)整条直线在窗口内。

此时,不需剪裁,显示整条直线。

(2)整条直线在窗口外,此时,不需剪裁,不显示整条直线。

(3)部分直线在窗口内,部分直线在窗口外。

此时,需要求出直线与窗框的交点,并将窗口外的直线部分剪裁掉,显示窗口内的直线部分。

直线剪裁算法有两个主要步骤。

首先将不需剪裁的直线挑出,即删去在窗外的直线。

然后,对其余直线,逐条与窗框求交点,并将窗口外的部分删去。

2.Cohen-Sutherland直线剪裁算法:(1)输入直线段的两端点坐标p1(x1,y1),p2(x2,y2),以及窗口的4条边界坐标,y wt ,y wb,y wl,y wr.(2)对p1,p2进行编码,点p1的编码为code1,点p2的编码为code2.(3)若code1| code2=0,对直线p1p2“简取”之,转(6);否则,若code1& code2≠0,对直线段“简弃”之,转(7);当上述两条均不满足时,进行步骤(4)。

(4)确保p1在窗口外部。

若p1在窗口内,则交换p1和p2的坐标值和编码。

(5)根据p1编码从低位开始寻找值为1的地方,从而确定p1在窗口外的哪一侧,然后求出直线段与相应窗口边界的交点S,并用交点S的坐标值替换p1的坐标值,即在交点S处把线段一分为二,因此可以去掉p1S。

计算机图形学第6章开窗口和二维裁剪

计算机图形学第6章开窗口和二维裁剪
点分割算法
从P0出发找距离P0最近可见点采用中点分割方法 先求出P0P1的中点Pm, 若P0Pm不是显然不可见的,并且P0P1在窗口中有可见部分,则距P0最近的可见点一定落在P0Pm上,所以用P0Pm代替P0P1; 否则取PmP1代替P0P1。 再对新的P0P1求中点Pm。重复上述过程,直到PmP1长度小于给定的控制常数为止,此时Pm收敛于交点。 从P1出发找距离P1最近可见点采用上面类似方法。
待裁剪线段:
假定条件
图元关于窗口内外关系的判别
判断图形元素是否落在裁剪窗口之内并找出其位于内部的部分
矩形裁剪窗口:[xmin,xmax]X[ymin,ymax]
图元与窗口的求交
裁剪的处理的基础
裁剪的目的
直线裁剪的基本原理
01
直线裁剪的基本原理
点裁剪 点(x, y)在窗口内的充分必要条件是:
02
Sutherland-Hodgman算法
裁剪窗口为任意多边形(凸、凹、带内环)的情况:
Weiler-Atherton算法
主多边形:被裁剪多边形,记为A 裁剪多边形:裁剪窗口,记为B
Weiler-Atherton算法
多边形顶点的排列顺序(使多边形区域位于有向边的左侧 )外环:逆时针 ;内环:顺时针 主多边形和裁剪多边形把二维平面分成两部分。 内裁剪:A∩B 外裁剪:A-B
第6章 开窗口及二维裁剪
应用程序中所定义的画面均以世界坐标系表示,这些画面要映射到设备坐标系才可以显示出来。在显示器上可以只选择一个显示区域观察一幅画面,也可以同时选择若干显示区域观察若干幅画面。把用一观察窗口有选择地显示物体地某一部分称为开窗口技术,如果要求删除显示区域之外的画面部分则称为裁剪。
第6章 开窗口及二维裁剪
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

计算机科学与技术学院
2013-2014学年第一学期《计算机图形学》实验报告
班级:
学号:
姓名:
教师:
成绩:
实验项目(3、二维裁剪)
一、 实验目的与要求
(1) 掌握线段裁剪算法原理,并实现其算法。

(2) 理解多边形裁剪、字符裁剪算法思想,能编程实现其算法。

二、 实验内容
设计菜单程序,利用消息处理函数,完成以下要求:
(1) 实现直线段的标号法(Cohen-Sutherland )、矩形窗口裁剪算法。

(2) 参考教材中的算法,用矩形窗口实现多边形的Sutherland-Hodgman 裁剪算法。

三、 重要算法分析
以下分析Cohen-Sutherland 和Sutherland-Hodgma n 两个算法,其中Cohen-Sutherland 算法的基本思想通过编码的方法快速实现对直线段的裁剪;Sutherland-Hodgman 算法基本思想是用窗口的四条边所在的直线依次来裁剪多边形。

(一) Cohen-Sutherland 算法
该算法的基本思想是:对于每条待裁剪的线段P 1,P 2分三种情况处理:
(1) 若P 1P 2完全在窗口内,则显示该线段。

(2) 若P 1P 2完全在窗口外,则丢弃该线段。

(3) 若线段既不满足“取”的条件,也不满足“舍”的条件,则求线段与窗口边界的交点,在交点处把线段分为两段。

1. 编码原则
具体编码过程为将延长线窗口的四条边线(y T 、y B 、x R 、x L ),将二维平面分成九个区域,全为0的区域是裁剪窗口,其中各位编码的定义如下:
{T y y other T C >=
10 {B y y other B C <=10 {R x x other R C >=
10 {L x x other L C <=10 按照如上定义,相应区域编码如图1所示。

图1 区域编码
2.裁剪算法:
依据上面的编码原则,可以总结出对一条线段的可见性进行测试:
1)若线段两个端点的四位二进制编码全为0000,即两端点编码逻辑或运算为0,那么该线段完全位于窗口内,可直接保留。

2)对端点的四位二进制编码进行逻辑与运算,若结果不为零,那么整条线段必位于窗口外,可直接舍弃。

3)否则,这条线段既不能保留也不能舍弃,它可能与窗口相交。

此时,需要对窗口进行再分割,并对分割后的线段按照一定顺序进行检查,决定保留、舍弃或
再分割。

重复这过程,直到全部线段均被舍弃或保留为止。

(二) Sutherland-Hodgman算法
算法的基本思想是利用窗口的四条边所在的直线依次来裁剪多边形。

多边形的每条边与裁剪线的位置关系有4种情况,如图2所示。

图2 多边形边界与裁剪窗口的关系
其中a)为从外到内的输出P和I,b)为从内到内输出P,c)为从内到外输出I,d)为从外到外不输出。

假设当前处理的多边形为SP。

1)在图2a的情况中,端点S在外侧,P在内侧,则按顺序将交点I和P都输出到结果多边形的顶点表中。

2)在图2b的情况中,端点S和都在内侧,则输出P到结果多边形的顶点表中。

3)在图2c的情况中,端点S在内侧,P在外侧,则输出交点I到结果多边形的顶点表中。

4)在图2d的情况中,端点S和P在外侧,没有输出。

四、程序运行截图
1.用Cohen-Sutherland算法实现线段的裁剪,如图3所示,其中a)图中的线段为裁
剪前的,b)图将超出裁剪多边形的线段部分裁剪后的结果。

图3 Cohen-Sutherland算法裁剪前和后
a)裁剪前 b)裁剪后
2.Sutherland-Hodgman算法实现多边形裁剪,如图4所示。

图4 Sutherland-Hodgman算法裁剪多边形前和后
a)裁剪多边形前 b)裁剪多边形后
五、总结与调试经验
(1)通过这次实验,加深了对图形学的理解,尤其对线段裁剪和多边形裁剪有了更加深入的理解。

(2)我学会了多边形裁剪算法,从刚开始的不知道到现在的理解,这是一个很大的进步,当然我也遇到了些困难,比如用某一条多边形的窗口边界裁剪多边形,
它要分为四种情况来分别考虑,也看出了我的思维不够周密,需要多多锻炼。

相关文档
最新文档