计算机图形学-实验五直线和多边形的裁剪
图形学实验报告直线段的裁剪算法

实验报告Experimentation Report of Taiyuan teachers College系部计算机系年级三年级课程图形学姓名同组者日期项目直线段的裁剪算法一、实验目的:1.熟悉图形裁剪的基本知识2.掌握Cohen-Sutherland 直线裁剪算法二、实验内容:在矩形窗口的裁剪算法中,考虑到构成图形的基本元素就是线段,曲线可看成是有很多小线段逼近而成的,因此,讨论线段的裁剪算法更为实用,即Cohen-Sutherland裁剪算法。
Cohen-Sutherland裁剪算法具体思路如下。
任意平面线段和矩形窗口的位置关系只会有如下3种:(1)完全落在窗口内。
(2)完全落在窗口外。
(3)部分落在窗口内,部分落在窗口外。
要想判断线段和窗口的位置关系,只要找到线段的两端点相对于矩形窗口的位置即可,线段的两端点相对于矩形窗口的位置可能会有如下几种情况:(1)线段的两个端点均在窗口内,这时线段全部落在窗口内,完全可见,应予以保留。
(2)线段的两个端点均在窗口边界线外同侧,这时线段全部落在窗口外,完全不可见,应予以舍弃。
(3)线段的一个端点在窗口内,另一个端点在窗口外,这时线段部分可见,应求出线段与窗口边界线的交点,从而得到线段在窗口内的可见部分。
(4)线段的两个端点均不在窗口内,但不处于窗口边界线外同侧,这时有可能线段是部分可见的,也可能是完全不可见的。
Cohen-Sutherland裁剪算法就是按照上述思路来对线段进行裁剪的,只是在线段的两端点相对于矩形窗口的位置上,巧妙地运用了编码的思想。
首先,延长窗口的四条边界线,将平面划分成9个区域,然后,用四位二进制数C3C2C1C0对这9个区域进行编码,编码规则如下:第0位C0:当线段的端点在窗口的左边界之左时,该位编码为1,否则,该位编码为0。
第1位C1:当线段的端点在窗口的右边界之右时,该位编码为1,否则,该位编码为0。
第2位C2:当线段的端点在窗口的下边界之下时,该位编码为1,否则,该位编码为0。
中间区段法裁剪

中间区段法裁剪
中间区段法裁剪(Middle Segment Clipping)是计算机图形学
中一种常用的二维裁剪算法,主要用于裁剪直线和多边形等图形。
中间区段法裁剪的基本思想是:首先确定裁剪窗口的边界,并将其等分为上、下、左、右四个方向的区段。
接着,根据裁剪窗口与图形在平面上的相对位置关系,决定各个区段是否需要进行裁剪。
最终,根据裁剪结果进行图形的显示或丢弃。
具体裁剪过程如下:
1. 确定裁剪窗口的边界:左边界(Xmin)、右边界(Xmax)、上边界(Ymin)和下边界(Ymax)。
2. 以直线为例,对于每一条线段,根据起点(P1)和终点
(P2)的位置关系,判断其是否需要进行裁剪。
3. 首先根据P1和P2的水平位置关系判断是否在裁剪窗口的
左右区段内。
若在同一区段内,则根据垂直位置关系进一步判断是否在裁剪窗口的上下区段内。
若在裁剪窗口内,则直接保留该线段。
若跨越区段边界,则根据裁剪窗口与线段的交点计算新的起点和终点,并进行裁剪。
4. 根据裁剪结果进行线段的显示或丢弃。
中间区段法裁剪的优点是相对简单、高效,适用于直线和多边形等较简单的图形。
缺点是无法处理曲线和复杂图形的裁剪。
在实际应用中,可以与其他裁剪算法结合使用,以实现更复杂的图形裁剪效果。
计算机图形学裁剪技术

求交测试顺序固定(左右下上) 最坏情形,线段求交四次。
裁剪
直线段裁剪
Cohen-Sutherland算法 中点分割算法 参数化裁剪算法 Liang-Barskey算法
多边形裁剪
Sutlerland_Hodgman算法
Weiler-Athenton算法
字符裁剪
裁剪
裁剪:确定图形中哪些部分落在显示区之内, 哪些落在显示区之外 , 以便只显示落在显示区 内的那部分图形。这个选择过程称为裁剪。在 进行裁剪时,画面中对应于屏幕显示的那部分 区域称为窗口。
Cohen-Sutherland算法
将区域码的各位从右到左编号,则坐标区 域与各位的关系为:
任何位赋值为1,代表端点落在相应的位置上,否则该 位为0。若端点在剪取矩形内,区域码为0000。如果端 点落在矩形的左下角,则区域码为0101。
直线段裁剪
裁剪线段与窗口的关系:(1)线段完全可见;(2) 显然不可见;(3)其它 提高裁剪效率: 快速判断情形(1)(2), 对于情形(3),设法减 少求交次数和每次求 交时所需的计算量。
常用的线段裁剪方法三种:
Cohen-Sutherland算法 中点分割算法 参数化裁剪算法
Cohen-Sutherland裁剪
基本思想:
对于每条线段P1P2分为三种情况处理: (1)若P1P2完全在窗口内,则显示该线段P1P2。 (2)若P1P2明显在窗口外,则丢弃该线段。
(3)若线段不满足(1)或(2)的条件,则在交点处把线段
分为两段。其中一段完全在窗口外,可弃之。然后对另一段 重复上述处理。
如何实现上述的处理呢?
实现方法:采用下面的编码方法
计算机图形学-多边形区域裁剪

P1被裁减多边形 P2为裁剪边框
多边形的边界均用其定点序列来表示,多边形的外部边界取顺时针方向(其内部 边界或内孔取逆时针方向),保证当遍历环形顶点表时,多边形内部总是位于前进 方向的右侧,依次定义了多边形边界的正方向。 交点判定规则: ①当主多边形的一条边位于窗口多边形 的一条边上时,两条边看作没有交点。 ②当主多边形的一个顶点位于窗口多边 形上时,作为主多边形的一条边的起点, 这个顶点应看作不是交点。 ③当主多边形的一个顶点位于窗口多边 形上时,,作为主多边形的一条交点,这 个顶点应看做一个交点。 ④ 当主多边形的一条边与窗口多边形的 交点不是主多边形的一个顶点时,是一个 正常的交点。 其类型为:如果该边的起点在裁剪 多边形外,则该交点是进入交点;反之如 果该边的起点在裁剪多边形内,则该交点 是离开交点。
记录顶点的判断 逐边裁剪法的实质使用四条边依次对多边形各边进行裁剪。每次裁剪的结果 都是输出一个多边形的顶点表。 ( 多边形的每一个顶点都是一条边的终点,又是下一条边的起点,我们统一 当多边形的一条边被窗口的一条边的延长线裁剪后需输出裁剪结果,即记录 将顶点作为边的终点进行判断和处理。) 需要保留的顶点(或交点)但应保留哪些点取决于该边与裁剪线的位置关系。 被裁多边形的边与裁剪线之间的位置关系存在四种可能的情况: ① 边的起点在不可见区域,终点在可见区域,此时,需保留边与裁剪线 的交点和边的终点。 ②边的起点和终点都在可见区域,此时,只需保留边与裁剪线的交点和 边的终点。 ③变得起点在可见区域,终点在不可见区域,此时只需保留边与裁剪线 的交点。 ④边到起点和终点都在不可见区域,此时,没有需要保留的点。
p1被裁减多边形p2为裁剪边框多边形的边界均用其定点序列来表示多边形的外部边界取顺时针方向其内部边界或内孔取逆时针方向保证当遍历环形顶点表时多边形内部总是位于前进方向的右侧依次定义了多边形边界的正方向
计算机图形学(简单多边形裁剪算法)

简单多边形裁剪算法摘要:多边形裁剪算法与线性裁剪算法具有更广泛的实用意义,因此它是目前裁剪研究的主要课题。
本文主要介绍了一种基于多边形顶点遍历的简单多边形裁剪算法,它有效降低了任意多边形裁剪复杂度。
通过记录交点及其前驱、后继信息,生成结果多边形,该算法简化了交点的数据结构,节省了存储空间,降低了算法的时间复杂度,具有简单、易于编程实现、运行效率高的特点。
关键词:多边形裁剪;交点;前驱;后继;矢量数组一、技术主题的基本原理简单多边形裁剪算法综合考虑现有多边形裁剪算法的优缺点,它是一种基于多边形顶点遍历来实现简单多边形裁剪工作的。
其主要的原理是遍历多边形并把多边形分解为边界的线段逐段进行裁剪,输出结果多边形。
二、发展研究现状近年来,随着遥感绘图、CAD辅助设计、图象识别处理技术的发展,图形裁剪算法从最初在二维平面上线和图形的裁剪扩展到三维空间里体和场的裁剪,国内外相继提出不少行之有效的算法,但越来越复杂的图形和计算也对算法的速度和适用性提出了越来越高的要求。
因此,不断简化算法的实现过程,完善细节处理,满足大量任意多边形的裁剪也就成了当今算法研究的焦点之一。
以往多边形裁剪算法不是要求剪裁多边形是矩形,就是必须判断多边形顶点的顺时针和逆时针性,即存在不实用或者是增加了多边形裁剪算法的难度。
为了解决现在的问题,我们研究现在的新多边形算法,其中,裁剪多边形和被裁剪多边形都可以是一般多边形,且不需要规定多边形输入方向。
它采用矢量数组结构,只需遍历剪裁多边形和被裁剪多边形顶点即完成多边形的裁剪,具有算法简单、运行效率高的特点。
三、新算法设计1、算法的思想本算法是为了尽量降低任意多边形裁剪算法复杂度而提出的,其主要思想是采用矢量数组结构来遍历裁剪多边形和被裁多边形顶点,记录裁剪多边形和被裁减多边形交点及其前驱、后继信息,并通过记录相邻交点的线段,然后通过射线法选择满足条件的线段,之后进行线段连接,输出对应的裁剪结果。
计算机图形学之裁剪算法

窗口特别小的场合。
2、中点裁剪法
中点分割裁剪法是将Cohen-Sutherland 算法中求线段与窗口边界的交点的过程用折 半查找(即求中点)的方法来代替。仍然采 用对线段端点进行编码的方式判断完全可见 和显然完全不可见的线段,对于与窗口有交 点的线段,该算法分别求离两个端点最近 (或最远)的可见点。这两个可见点之间的 线段即是原线段的可见部分。
计算P1P2的最近可见点Pma和 Pmb : (一)直线段P1P2的一个端点可见, P1 另一个端点不可见。 只需解算不可见端点的最近的 可见点。 1)设P1不可见,计算P1P2的中点Pm1。
P1
pm
P2
P2
判断中点Pm1如果落在(接近)窗口边上,则 确定该中点为最近可见点。裁剪结束。否则,
2)判断Pm1是否可见: 如果Pm1可见,以Pm1取代P2 ,返回到 1)计算 P1Pm1的中点Pm2,判断Pm2 如果Pm1不可见,以Pm1取代P1 ,返回到 1)计 算Pm1P2的中点Pm2,判断Pm2
关键: 根据多边形的边表,逐 次对每一段边与裁剪线 (窗口边直线)比较,判 别输入顶点的个数和坐 标,并联结成封闭多边 形。
不可见侧
2
多边形边与裁剪线相对位置的四种
情况与处理方法: (1) 位于可见一侧:输出终点作 为新多边形顶点 (2) 位于不可见一侧:不输出 (3) 由可见到不可见:输出与裁剪
P2
两种线段裁剪算法的比较
Cohen-Sutherland算法是最早的、使用最广泛的线
段裁剪算法之一。在裁剪窗口很大,大部分线段完全
可见,或裁剪窗口很小,大部分线段完全不可见的情 况下,该算法特别有效;在一般情况下,该算法有时 要做不必要的求交运算,因而效率不是太高.
第五章 裁剪

A
A G 8
1
1 K
G J H I 9 8
H 3 4 5
D
7 6
F
3
D
4 5 7 6
输入:A134D56FGH 输出:A134D5678GH (c)用右边界裁剪
输入:A134D5678GH 输出:K34D56789IHJ (d)用上边界裁剪
3 多边形裁剪算法
只需把被裁剪多边形依次用裁剪窗口 的边来裁剪;
第五章 裁剪( Clipping)
裁剪:确定图形中哪些部分落在显示区之
内,哪些落在显示区之外,以便只显示落在 显示区内的那部分图形。这个选择过程称 为裁剪。 在使用计算机处理图形信息时,计算机内 部存储的图形往往比较大,而屏幕显示的 只是图的一部分。
5.1 线段裁剪
线段裁剪算法是复杂图元裁剪的基础。复杂的曲 线可以通过折线段来近似,从而裁剪问题也可以 化为线段的裁剪问题。 所谓线段裁剪就是把线段位于裁剪区域的部分找 出来,而把位于裁剪区域之外的部分去掉。 最常见的裁剪区域是长方形。
求交: 计算线段P1(x1,y1)P2(x2,y2)与窗口边界的交点
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);} else 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);}
多边形裁剪报告

多边形裁剪实验报告一、实验内容1.实验目的:●理解多边形裁剪算法的基本思想,掌握多边形裁剪算法及其特点。
●能够应用多边形裁剪算法,编程实现裁剪指定多边形的功能。
2.常见的解决方法以及各方法的优点:a)Sutherland-Hodgman(逐边)裁剪算法优点:原理简单实用。
缺点:对于凸多边形的裁剪将显示出一条多余的裁剪边界直线。
这种情况在裁剪后的多边形有两个或多个分离部分的时候出现,因为只有一个输出顶点表,所以表中的最后一个顶点总是连着第一个顶点。
二、试验方法1.Sutherland-Hodgman裁剪算法所用方法的原理采用分割处理策略,将多边形关于矩形窗口的裁剪分解为多边形关于窗口四边所在直线的裁剪。
顺序是左上右下,前边的结果永远是后边的输入。
一次用窗口的一条边裁剪多边形,考虑窗口的一条边以及其延长线构成的裁剪线,该线把平面分为两个部分:可见一侧和不可见一侧。
对于两个端点均在可见一侧,则输出一个端点;对于两个端点均在不可见一侧,则输出0个端点;如果起始端点在可见一侧,终止端点在不可见一侧,则输出线段与裁剪边的交点;如果起始端点在不可见一侧,终止端点在可见一侧,则输出线段与裁剪边的交点以及终止端点。
程序设计思路(1)输入第一个顶点S,输入第一个顶点F(2)判断定点是否输入完毕,如果输入完毕,F—>P,处理线段SP(3)如果顶点未输入完毕,则输入顶点P,处理线段SP,P->S,然后再判断顶点是否输入完毕,转到第二步(4)处理线段SP,判断SP是否与裁剪线相交,如果与裁剪线相交,则求出SP与裁剪线的交点(5)输出交点(6)如果SP与裁剪线不相交,则判断P是否位于可见一侧,如果P位于可见一侧,则输出顶点P(7)如果P位于不可见一侧,则直接舍弃P(8)线段SP处理完毕,算法结束。
三、实验结果分析1.实验环境:windows xp操作系统、主频、内存、VC2.实验结果:3.分析解释实验结果初始化的背景为白色glClearColor(1.0,1.0,1.0,0.0);两个多边形的线段颜色设置为黑色glColor3f(0.0,0.0,0.0);将裁剪出的多边形设置为红色glColor3f(1.0,0.0,0.0); 然后利用循环进行裁剪。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
大学实验报告学院:计算机科学与信息学院专业:软件工程班级:102班** 实验组实验时间指导教师成绩实验工程名称实验五直线和多边形的裁剪实验目的掌握直线段的裁剪算法以及多边形的裁剪算法实验要求熟练掌握直线段的裁剪算法以及多边形的裁剪算法的根本原理,并编写测试代码进展实验。
实验原理Cohen-Sutherland直线剪裁算法以区域编码为根底,将窗口及其周围的,8个方向以4 bit的二进制数进展编码。
右图所示的编码方法将窗口及其邻域分为5个区域:⑴域:区域(0000)。
⑵上域:区域(1001, 1000, 1010)。
⑶下域:区域(0101, 0100, 0110)。
⑷左域:区域(1001, 0001, 0101)。
⑸右域:区域(1010, 0010, 0110)。
当线段的两个端点的编码的逻辑"与〞非零时,线段为显然不可见的,对*线段的两个端点的区号进展位与运算,可知这两个端点是否同在视区的上、下、左、右;Cohen-Sutherland直线剪裁算法的算法思想是:对于每条线段P1P2分为三种情况处理。
〔1〕假设P1P2完全在窗口,则显示该线段P1P2简称"取〞之。
〔2〕假设P1P2明显在窗口外,则丢弃该线段,简称"弃〞之。
〔3〕假设线段既不满足"取〞的条件,也不满足"弃〞的条件,则在交点处把线段分为两段。
其while (code1 != 0 || code2 != 0) {if ((code1 & code2) != 0) {// 两端点的编码相与不为0,表示直线在窗口外return;}if (code1 != 0) {code = code1;} else {code = code2;}if ((LEFT & code) != 0) {// 直线的端点与矩形窗口的左边编码相与!=0* = *L;y = y1 + (y2 - y1) * (*L - *1) / (*2 - *1);// 求直线与矩形窗口的左边界的交点} elseif ((RIGHT & code) != 0) {// 直线的端点与矩形窗口的右边编码相与!=0* = *R;y = y1 + (y2 - y1) * (*R - *1) / (*2 - *1);// 求直线与矩形窗口的右边界的交点} elseif ((BOTTOM & code) != 0) {// 直线的端点与矩形窗口的下边编码相与!=0y = YB;* = *1 + (*2 - *1) * (YB - y1) / (y2 - y1);// 求直线与矩形窗口的下边界的交点} elseif ((TOP & code) != 0) {// 直线的端点与矩形窗口的上边编码相与!=0y = YT;* = *1 + (*2 - *1) * (YT - y1) / (y2 - y1);// 直线的端点与矩形窗口的上// 边编码相与!=0}if (code == code1) {*1 = *;y1 = y;code1 = encode(*, y);} else {*2 = *;y2 = y;code2 = encode(*, y);}}g.drawLine((int) (*1 + 0.5), (int) (y1 + 0.5), (int) (*2 + 0.5),(int) (y2 +0.5));}二、多边形裁剪的核心代码为:通过点集画直线或者多边形:privatevoid draw() {//通过点集画直线或者多边形for (int i = 1; i < points.size(); i++) {Point p1 = new Point();p1 = points.get(i);int *1 = (int) p1.get*();int y1 = (int) p1.getY();Point p2 = new Point();p2 = points.get(i - 1);int *2 = (int) p2.get*();int y2 = (int) p2.getY();g.drawLine(*1, y1, *2, y2);}}多边形的裁剪函数:private Point[] cutPicture(Point[] point, Point[] edge) {// 剪裁函数,参数为〔点集,边〕Point[] intersectPoint = new Point[20];//存放交点的集合for (int j = 0; j < 20; j++) {intersectPoint[j] = new Point();}Point s = new Point();Point p = new Point();Point t = new Point();int i = 0;int length = point.length;s = point[length - 1];for (int j = 0; j < length; j++) {p = point[j];if (inside(p, edge)) {// sp在窗口,情况1if (inside(s, edge)) {intersectPoint[i] = p;i += 1;} else {// s在窗口外,情况4t = intersect(s, p, edge);intersectPoint[i] = t;i += 1;intersectPoint[i] = p;i += 1;}} elseif (inside(s, edge)) {// s在窗口,p在窗口外,情况3t = intersect(s, p, edge);intersectPoint[i] = t;i += 1;}// 情况2没有输出s = p;}List<Point> tempList = new ArrayList<Point>();for (int k = 0; k < i; k++) {if (intersectPoint[k] != null) {Point pt = intersectPoint[k];tempList.add(pt);}}Point[] temp = new Point[tempList.size()];for (int j = 0; j < tempList.size(); j++) {temp[j] = new Point();temp[j] = tempList.get(j);}intersectPoint = temp;return intersectPoint;}判断点是否在裁剪边的可见侧:privateboolean inside(Point point, Point[] edge) {//判断点是否在裁剪边的可见侧// 裁剪边为窗口下边if ((edge[0].y == edge[1].y) && (edge[0].* < edge[1].*)) {if (point.y >= edge[0].y) {returntrue;}}// 裁剪边为窗口上边if ((edge[0].y == edge[1].y) && (edge[0].* > edge[1].*)) {if (point.y <= edge[0].y) {returntrue;}}// 裁剪边为窗口右边if ((edge[0].* == edge[1].*) && (edge[0].y < edge[1].y)) {if (point.* <= edge[0].*) {returntrue;}}// 裁剪边为窗口左边if ((edge[0].* == edge[1].*) && (edge[0].y > edge[1].y)) {if (point.* >= edge[0].*) {returntrue;}}returnfalse;}直线段与窗口边界求交:private Point intersect(Point s, Point p, Point[] edge) {//直线段与窗口边界求交,并返回交点Point t = new Point();if (edge[0].y == edge[1].y) {// 水平裁剪边t.y = edge[0].y;t.* = s.* + (edge[0].y - s.y) * (p.* - s.*) / (p.y - s.y);} elseif (edge[0].* == edge[1].*) {// 垂直裁剪边t.* = edge[0].*;t.y = s.y + (edge[0].* - s.*) * (p.y - s.y) / (p.* - s.*);}return t;}鼠标的监听类〔部类〕:class MouseMonitor e*tends MouseAdapter {//通过鼠标的单击获取点,并画出直线或者多边形publicvoid mouseClicked(MouseEvent e) {points.add(e.getPoint());if (points.size() > 1) {draw();}}}键盘的监听类〔部类〕:class KeyMonitor e*tends KeyAdapter {// 键盘控制publicvoid keyPressed(KeyEvent e) {switch (e.getKeyCode()) {case KeyEvent.VK_R:// 清空画布和点集panel.repaint();points.removeAll(points);break;case KeyEvent.VK_W://对裁剪窗口的处理g.setColor(Color.RED);g.drawRect(*L, YB, *R - *L, YT - YB);//存放裁剪窗口的边top = new Point[2];// 存放裁剪窗口的上边top[0] = new Point(*L, YB);top[1] = new Point(*R, YB);right = new Point[2];//存放裁剪窗口的右边right[0] = new Point(*R, YB);right[1] = new Point(*R, YT);bottom = new Point[2];//存放裁剪窗口的下边bottom[0] = new Point(*R, YT);bottom[1] = new Point(*L, YT);left = new Point[2];//存放裁剪窗口的左边left[0] = new Point(*L, YT);left[1] = new Point(*L, YB);break;case KeyEvent.VK_A://对直线段进展裁剪g.setColor(Color.GREEN);Point p1 = points.get(0);Point p2 = points.get(1);lineCut(p1.get*(), p1.getY(), p2.get*(), p2.getY()); break;case KeyEvent.VK_B://对多边形进展裁剪source = new Point[points.size()];//得到多边形的点for (int i = 0; i < points.size(); i++) {source[i] = points.get(i);}g.setColor(Color.GREEN);wT = cutPicture(source, top);//得到多边形与裁剪窗口上边的交点wR = cutPicture(wT, right);//得到多边形与裁剪窗口右边的交点wB = cutPicture(wR, bottom);//得到多边形与裁剪窗口下边的交点wL = cutPicture(wB, left);//得到多边形与裁剪窗口左边的交点第二种情况:线段在裁剪窗口的部,线段完全可见。