线段裁剪算法

合集下载

描述cohen sutherland裁剪算法

描述cohen sutherland裁剪算法

描述cohen sutherland裁剪算法
Cohen-Sutherland裁剪算法是一种用于裁剪线段的算法,由S.G.Cohen和D.P.Sutherland在1969年提出。

它的基本思想是使用一个2D窗口矩形对要裁剪的线段进行测试,根据结果将线段分成四个不同的类别(左端点的左边,右端点的右边,上端点的上边,下端点的下边),这样就可以把线段按照它们在窗口中的相对位置编码。

下面具体讲解Cohen-Sutherland裁剪算法的步骤:
1.首先,确定要裁剪的线段端点的坐标,以及窗口的左上角和右下角的坐标。

2.然后,根据左上角的坐标和右下角的坐标,利用一个4位的二进制整数对线段端点进行编码,每一位的0或1表示端点是否在窗口的4个边界外面。

3.对比端点的编码,如果两个编码都为0,表示线段完全位于窗口内,不需进行裁剪。

如果两个编码不同,则表示至少有一个端点位于窗口边界外,此时需要进行裁剪。

4.根据不同的编码情况,对线段进行裁剪:
(1)如果两个编码都不为0,则表明线段两个端点都在窗口边界外,此时线段不可见,可以将线段丢弃。

(2)如果两个编码中只有一个不为0,则表明线段上有一个端点在窗口边界外,此时只需要将外部端点移动到窗口边界上,即可得到一个可见的线段。

5.此外,还需要对线段两个端点进行重新编码,根据编码重复步
骤3和步骤4,直至线段完全位于窗口内,或者线段完全被丢弃。

至此,Cohen-Sutherland裁剪算法就完成了。

它既可以用于直线的裁剪,也可以用于曲线的裁剪。

liang-barsky算法的基本原理

liang-barsky算法的基本原理

liang-barsky算法的基本原理
liangbarsky算法是一种用于裁剪线段的算法,其基本原理是利用参数化表示,将线段与剪裁窗口边界进行比较,确定线段是否需要进行裁剪,并计算出裁剪后的线段端点坐标。

具体来说,liangbarsky算法将线段表示为参数化形式:
x = x1 + t * (x2 - x1)
y = y1 + t * (y2 - y1)
其中,t是参数,表示线段上的点。

根据线段的起点和终点坐标(x1,y1)、(x2,y2),可以计算出线段在参数范围[0,1]内的参数化表示。

然后,将参数化表示代入剪裁窗口边界的方程中,求解参数t的范围,即线段与边界的交点,以确定裁剪后的线段端点坐标。

具体的求解过程如下:
首先,根据线段的方向向量(dx,dy)和窗口边界的方向向量(dx',dy'),计算出4个参数p1、p2、p3、p4:
p1 = -dx
p2 = dx
p3 = -dy
p4 = dy
然后,利用线段的起点坐标(x1,y1)与窗口边界的4个顶点坐标(xi,yi),计算出参数q1、q2、q3、q4:
q1 = x1 - xi
q2 = xi + w - x1
q3 = y1 - yi
q4 = yi + h - y1
其中,w和h分别是窗口的宽度和高度。

最后,通过以下公式计算出参数u1、u2:
u1 = max(0, max(p1 * q1, p3 * q3))
u2 = min(1, min(p2 * q2, p4 * q4))
如果u1>u2,则线段完全在剪裁窗口外部,可以忽略直接将线段裁剪掉;否则,根据参数化表示计算出裁剪后的线段端点坐标。

中间区段法裁剪

中间区段法裁剪

中间区段法裁剪
中间区段法裁剪(Middle Segment Clipping)是计算机图形学
中一种常用的二维裁剪算法,主要用于裁剪直线和多边形等图形。

中间区段法裁剪的基本思想是:首先确定裁剪窗口的边界,并将其等分为上、下、左、右四个方向的区段。

接着,根据裁剪窗口与图形在平面上的相对位置关系,决定各个区段是否需要进行裁剪。

最终,根据裁剪结果进行图形的显示或丢弃。

具体裁剪过程如下:
1. 确定裁剪窗口的边界:左边界(Xmin)、右边界(Xmax)、上边界(Ymin)和下边界(Ymax)。

2. 以直线为例,对于每一条线段,根据起点(P1)和终点
(P2)的位置关系,判断其是否需要进行裁剪。

3. 首先根据P1和P2的水平位置关系判断是否在裁剪窗口的
左右区段内。

若在同一区段内,则根据垂直位置关系进一步判断是否在裁剪窗口的上下区段内。

若在裁剪窗口内,则直接保留该线段。

若跨越区段边界,则根据裁剪窗口与线段的交点计算新的起点和终点,并进行裁剪。

4. 根据裁剪结果进行线段的显示或丢弃。

中间区段法裁剪的优点是相对简单、高效,适用于直线和多边形等较简单的图形。

缺点是无法处理曲线和复杂图形的裁剪。

在实际应用中,可以与其他裁剪算法结合使用,以实现更复杂的图形裁剪效果。

计算机图形学第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裁剪算法

裁剪算法——cohen-sutherland算法

裁剪算法——cohen-sutherland算法

裁剪算法——cohen-sutherland算法实验环境:VC6.0算法思想: 延长窗⼝的边,将⼆维平⾯分成9个区域,每个区域赋予4位编码C t C b C r C l,裁剪⼀条线段P1P2时,先求出所在的区号code1,code2。

若code1=0,且code2=0,则线段P1P2在窗⼝内,应取之。

若按位与运算code1&code2,则说明两个端点同时在窗⼝的上⽅、下⽅、左⽅或右⽅,则可判断线段完全在窗⼝外,可弃之;否则,按第三种情况处理,求出线段与窗⼝某边的交点,在交点处把线段⼀分为⼆,其中必有⼀段在窗⼝外,可弃之,再对另⼀段重复上述处理。

100110001010000100000010010********* 多边形裁剪编码程序实现:#include "stdafx.h"#include<stdio.h>#include<conio.h>#include<graphics.h>#define LEFT 1#define RIGHT 2#define BOTTOM 4#define TOP 8void midpointLine(int x0,int y0,int x1,int y1,int color)//中点画线算法{int a,b,d1,d2,d,x,y;a=y0-y1;b=x1-x0;d=2*a+b;d1=2*a;d2=2*(a+b);x=x0;y=y0;putpixel(x,y,color);while(x<x1){if(d<0){x++;y++;d+=d2;}else{x++;d+=d1;}putpixel(x,y,color);}}int encode(int x,int y,int XL,int XR,int YB,int YT)//编码{int c=0;if(x<XL) c|=LEFT;if(x>XR) c|=RIGHT;if(y<YB) c|=BOTTOM;if(y>YT) c|=TOP;return c;}void C_SLineClip(int x1,int y1,int x2,int y2,int XL,int XR,int YB,int YT){int code1,code2,code,x,y;code1=encode(x1,y1,XL,XR,YB,YT);code2=encode(x2,y2,XL,XR,YB,YT);while((code1 != 0) || (code2 != 0)){if((code1 & code2) != 0){midpointLine(x1,y1,x2,y2,RGB(0, 255, 0));//如果直线在裁剪窗⼝外就⽤绿⾊画出printf("线段在窗⼝外!");return;}if(code1 != 0) code=code1;else 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);}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);}if(code == code1){x1=x; y1=y; code1=encode(x,y,XL,XR,YB,YT);}else{x2=x; y2=y; code2=encode(x,y,XL,XR,YB,YT);}}midpointLine(x1,y1,x2,y2,RGB(255,0,0));//将裁减的直线⽤红⾊标注return;}int main(int argc, char* argv[]){int gdriver=DETECT,gmode;int x1=20,y1=30,x2=250,y2=300,XL=10,XR=200,YT=400,YB=30;initgraph(&gdriver,&gmode,"c:\\tc");//setbkcolor(WHITE);cleardevice();midpointLine(x1,y1,x2,y2,RGB(0,255,0));//将被裁剪直线⽤绿⾊画出rectangle(10,400,200,30);//rectangle(int left,int top,int right,int bottom);//裁剪窗⼝ C_SLineClip(x1,y1,x2,y2,XL,XR,YB,YT);// cohen sutherland算法getch();closegraph();return0;}显⽰效果:将在窗⼝内的线段设为红⾊,窗⼝外的线段设为绿⾊。

Cohen-Sutherland裁剪算法例题

Cohen-Sutherland裁剪算法例题

Cohen-Sutherland裁剪算法例题Cohen-Sutherland裁剪算法是一种用于线段裁剪的算法,用于确定线段是否完全位于视窗内部,或者是否与视窗有部分或完全重合。

以下是一个例题来说明Cohen-Sutherland算法的使用:假设有一个视窗,左上角坐标为(20, 20),右下角坐标为(60, 60)。

现有一条线段,起点坐标为(10, 40),终点坐标为(70, 30)。

使用Cohen-Sutherland算法对该线段进行裁剪。

步骤1: 定义裁剪区域的编码使用二进制编码来定义裁剪区域,对于视窗的四个边界线段,可以使用以下编码:●左侧编码: 0001●右侧编码: 0010●下方编码: 0100●上方编码: 1000步骤2: 计算线段的编码对于线段的起点和终点坐标,根据其相对于视窗的位置,计算其编码。

假设线段起点的编码为C1,终点的编码为C2。

起点(10, 40)编码计算:●位于视窗左侧,所以C1 = 0001终点(70, 30)编码计算:●位于视窗右侧,所以C2 = 0010步骤3: 判断是否完全落在视窗内部如果起点和终点的编码C1和C2都为0,则表示线段完全位于视窗内部,无需裁剪。

在这个例子中,C1 = 0001,C2 = 0010,都不等于0,因此线段不完全位于视窗内部,需要进行裁剪。

步骤4: 判断是否完全在视窗之外如果起点和终点的编码C1和C2的逻辑与操作(AND)结果为非零,表示线段完全在视窗之外,可以完全丢弃不进行裁剪。

在这个例子中,C1 = 0001,C2 = 0010,它们的逻辑与操作结果为0,因此线段不完全在视窗之外,需要进行裁剪。

步骤5: 通过裁剪区域裁剪线段通过逐步调整线段的起点和终点坐标,根据它们的编码,使得线段落在视窗内部或与视窗边界相交。

在这个例子中,我们将线段向视窗内进行裁剪:●根据起点编码C1 = 0001,在视窗左边界裁剪:将起点的x坐标调整为视窗左边界的x坐标,即20,计算新的起点编码C1 =0000。

计算机图形学-NLN线段剪裁算法

计算机图形学-NLN线段剪裁算法

3、点p1的第三种状态
• 点p1在裁剪窗口的左上角区域,这种状态又将p1的位置 分为两种进行讨论,即靠近上边界的和靠近左边界的两 种位置。如图 p1
p1 L2 L2
L1
L3 L4 L4
L3
L1
P1位置判别
kp1a>kab,p1为下图a所示; Kp1a<kab,p1为下图b所示;
如果靠近上边界
• • • • 如果靠近上边界,那么 (1)当k>=k1 && k<=k2时, 当p2在裁剪窗口的内部,求交点 y=YT; x=(y-y1)/(y2-y1)*(x2-x1) ;交点 (x,y),那么点p2与交点的连线就是我们的 裁剪结果 • 当p2在裁剪窗口的外部,此时我们需要求 两个交点 • x0=XR; y0 =(y2-y1)/(x2-x1) *(x0-x1);交 点(x0,y0) • y=YT; x=(y-y1)/(y2-y1)*(x2-x1) ;交点 (x,y),那么两个交点的连线就是我们的裁 剪结果。
2、点p1在裁剪窗口的正左边
L1 L2
p1
p2
L3
L4
• 端点p2的位置有两种选择,在裁剪窗口内部或在裁剪窗口的外 面,利用点p2的编码来判断,即如果codep2==0,那么点p2在 裁剪窗口内部;否则点p2在裁剪窗口外部。???????? • (1)当k>=k2 && k<=k1时, • 当p2在裁剪窗口的内部,求交点 • x=XL;y =k*(x-x1);交点是(x,y),那么点p2与交点的连线就是 的裁剪结果; • 当p2在裁剪窗口的外部,此时我们需要求两个交点 • x0=XL; y0 =k*(x0-x1);交点(x0,y0) • y=YT; x=k*(x2-x1) ;交点(x,y),两个交点的连线就是裁剪结 果。

图形的裁剪

图形的裁剪

此时B在窗口外,为使1变为 ,得出交点I2(-8/5,6), 此时 在窗口外,为使 变为0,得出交点 ( , ), 在窗口外 变为 I2B被裁剪,剩下 被裁剪, 被显示。 被裁剪 剩下I1I2被显示。因为他们的区域编码都是 被显示 因为他们的区域编码都是0000
CD裁剪:先从D开始 裁剪:先从 开始 裁剪 编码为1010,为使第一 , 编码为 变为0 个1变为 变为 得出的交点: 得出的交点: I3(1/3,6)区域编码 ( , ) 为0000,得不显示 ,得不显示I3D 保留CI3(仍然为分类 ( 保留 3),因为(0000)and ),因为( ),因为 ) )=0000 (1000)= )=
图 形 裁 剪
视图区
简称视图(viewport),是在屏 简称视图(viewport),是在屏 视图 ), 幕上定义的一个小于或等于屏幕区 域的一个矩形块。 域的一个矩形块。视图区可用来显 示某一窗口内的图形。 示某一窗口内的图形。
窗口区
进行图形设计时,图形输出程序中的图形 都是在用户坐标系中定义的,此坐标系拥 有的区域在理论上是无限的,在使用时我 们可以把它当作一个有限的矩形区,这就 是用户域。用户可以在用户域中指定任意 区域输出到屏幕上,这个指定区域称为窗 口区,简称窗口(window)。 定义窗口的目的是选取用户所定义的图形 中需要观察的那一部分图形。
偶规则(Odd-even Rule) 奇-偶规则
从任意位置p作一条射线,若与该射线相交的多边形边的数目 为奇数,则p是多边形内部点,否则是外部点。
非零环绕数规则(Nonzero Winding Number Rule) 非零环绕数规则
1.首先使多边形的边变为矢量。 2.将环绕数初始化为零。 3.再从任意位置p作一条射线。当从p点沿射线方向移动时,对在每个方向上穿 过射线的边计数,每当多边形的边从右到左穿过射线时,环绕数加1,从左到 右时,环绕数减1。 4.处理完多边形的所有边之后,若环绕数为非零,则p为内部点,否则,p是外 部点。

图形学实验报告直线段的裁剪算法

图形学实验报告直线段的裁剪算法

实验报告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。

计算机图形学实验报告实验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直线裁剪算法更快。

cohen-sutherland 直线段裁剪算法

cohen-sutherland 直线段裁剪算法

Cohen-Sutherland 直线段裁剪算法是一种计算机图形学中的算法,用于裁剪二维图形中超出指定矩形区域的线段。

算法步骤如下:
定义四个常量,分别表示矩形区域的四个边界:TOP, BOTTOM, LEFT, RIGHT。

对于每条待裁剪的线段,计算其与矩形区域的交集情况,可以使用一个 4 位的二进制数表示,其中每一位分别表示线段与矩形上、下、左、右边界的交集情况。

例如,如果线段与矩形上边界有交集,则二进制数的第 0 位为 1,否则为 0。

根据线段的端点坐标和矩形区域的边界坐标,判断线段与矩形区域的相对位置关系,可以分为以下三种情况:
a. 线段完全在矩形区域内,不需要裁剪,直接保留。

b. 线段完全在矩形区域外,不需要裁剪,直接舍弃。

c. 线段部分在矩形区域内,部分在矩形区域外,需要进行裁剪。

4. 对于需要裁剪的线段,根据其与矩形边界的交点坐标,将线段裁剪成两部分,分别计算每部分与矩形区域的交集情况,并递归进行裁剪,直到所有线段都被处理完毕。

Cohen-Sutherland 直线段裁剪算法可以快速地裁剪二维图形中超出指定矩形区域的线段,是计算机图形学中的常用算法之一。

裁剪算法设计实验报告(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)定义窗口边界首先,定义窗口边界,包括左边界、右边界、上边界和下边界。

一种高效的圆形窗口线段裁剪算法

一种高效的圆形窗口线段裁剪算法
从距 离 圆心较远 的端 点 向 圆引 切线 , 通过 判 断 点 相 对于两 切线及 垂直 切线 两 圆半 径所在 直线 的位 置关 系确 定线段 与 圆形 窗 口的 相交 情 况 , 当被 裁
求 交运 算来判 断 是 否有 交 点 , 多 运算 是 不 必 要 很
的. 本文 首先判 断 被 裁剪 线 段 两 端点 与 圆形 窗 口
的位置关 系 , 端 点 都在 圆形 窗 口之 内和 一 端 点 两
如果 d =r,可得端 点 P 在 圆形 窗 口上 ; 如果 d <F,可得 端点 P 在 圆形 窗 口内 ; 2 如果 d >r,可得端 点 P 在 圆形 窗 口外 . 根据这 种相 对 应 的位 置关 系 , 区分 不 同情 况 判断如 下 :
首 先 , 算被 裁 剪 线段 两 端 点 到 圆形 窗 口圆 计
心 距离 的平 方 , 根 据 与半 径 平 方 比较确 定 两 端 再 点 相对 于 圆形 窗 口的位置 关 系. 被 裁剪 线 段 两 端 点 P 到 圆形 + i 1或 2 2 取 ( )

种 高效 的 圆形 窗 口线 段 裁 剪 算 法
任 洪 海
( 大连 交通 大 学 软件 学 院 ,辽 宁 大连 16 5 ) 10 2

要 : 圆 形 窗 口线段 裁 剪 过程 中 , 两 端 点 都 在 窗 口之 外 时 情 况 较 为 复 杂 . 较 远 端 点 向圆 形 窗 口 在 当 从
中应用较 为烦 琐 的辅 助 操 作 , 文 献 [ ] 如 8 中根 据
圆与其 外切 正方形 的线性 关 系制备 规范 化交 点表 和文献 [ ] 9 中多 重 编 码 都 很 费 时 , 由于 同样 没 有 完全 区分被裁 剪 线 段是 否 与 圆 形 窗 口相 交 , 因此 并没有 太简 化裁 剪 过程 . 圆形 窗 口线段 裁 剪 系 在 统中, 多数被 裁剪线 段与 圆形 窗 口并 不相交 , 果 如 不 区分 被裁剪 线段 与 圆形 窗 口的相 交情况 就进 行

论述cohen-suthorland直线段裁剪算法的编码原理

论述cohen-suthorland直线段裁剪算法的编码原理

论述cohen-suthorland直线段裁剪算法的编码原理1. 引言1.1 概述Cohen-Sutherland直线段裁剪算法是一种常用的计算机图形学算法,用于确定直线段是否与给定裁剪窗口相交,从而实现对直线段的裁减。

该算法以编码方式表示直线段位置关系,并根据编码结果进行裁剪判断,具有简单高效的特点,在计算机图形学领域得到广泛应用。

1.2 文章结构本文将详细论述Cohen-Sutherland直线段裁剪算法的编码原理及实现过程。

首先介绍算法的背景和相关概念,解释其在计算机图形学中的重要性。

接下来,详细说明Cohen-Sutherland算法的步骤以及编码方法,并阐述其实现过程中所需进行的初始化设置、裁剪区域判定和直线段裁剪计算等操作。

然后,通过效果评估对该算法进行评价,并分析其优点和缺点。

最后,总结论述并提出在进一步研究方向上可能存在的建议。

1.3 目的本文旨在深入探讨Cohen-Sutherland直线段裁剪算法的编码原理及其应用。

通过对该算法进行详细的解释和分析,读者将能够全面了解算法的工作原理,并具备实现及优化该算法的能力。

此外,我们也希望通过对其效果的评估和优缺点的分析,为使用该算法的工程师和学术研究人员提供参考,以便更好地选择合适的裁剪算法并应用于具体问题中。

2. Cohen-Sutherland直线段裁剪算法的编码原理2.1 算法简介Cohen-Sutherland直线段裁剪算法是一种常用的二维直线段裁剪方法,它通过将裁剪区域划分为9个小区域来判断并去除不需要显示的部分,从而实现快速而准确的线段裁剪。

2.2 算法步骤Cohen-Sutherland直线段裁剪算法主要包括以下步骤:步骤1:对于给定的两个端点P1和P2,首先利用编码方法将两个端点进行编码。

编码中使用4位二进制数表示每个点所处位置。

步骤2:根据编码结果判断两个端点是否在裁剪区域内。

如果两个端点的编码值为0000(即都在可视范围内),则可以直接输出该线段;否则,执行下一步。

C语言图形编程(五、二维图形变换-02)

C语言图形编程(五、二维图形变换-02)
留中间数据,其实不然,它可以采用递归方式调用同一算法,整个裁剪过程由四级同样的算法组成。每一级相对于窗口的四条边界线之一来剪裁,第一级输出的顶点传送给第二级(即把多边形每个顶点相对于第一条边界线裁剪,所形成
为了方便下次访问,建议你把网址加入以下收藏夹:
当线的一端点位于某一区域时,便将该区域的代码赋予端点。然后根据线从而段两端点代码就能很方便地判断出线段相对于窗口的位置关系,并决定对该线段如何进行裁剪。四位代码中每位(位的顺序由右向左排序)代码的意义如下:
第一位,点在窗口左边界线之左为1,否则为0;
第二位,点在窗口右边界线之右为1,否则为0;
下面介绍线段裁剪算法(编码裁剪法)。
由上面线段相对于窗口的位置的几种情况讨论可以得知,有些线段被窗口边界切割后会产生一条以上的窗口外的线段,而窗口内的线段却只有一条。这一点很重要,它意味着要确定窗口内的线段,只要计算出它位于窗口内的两个端点。丹科恩和伊凡.瑟萨兰德就根据这一思路设计出了线段裁剪的算法。这种算法分为两步:第一步先确定该线段是否整个位于窗口内或全部位于窗口外,若属于这两种情况,则全部保留或全部舍弃;第二步对不属于第一步那两种情况的线段,则被窗口某一边界线分成两部分,再对每一部分进行第一步。具本这两步留舍测试如下进行:延长窗口各边界,将窗口及其周围共划分为九个区域,中央就是所要裁剪的区域。每个区域各用一个四位二进制数组成的代码(即代码中每一位分别为0或1)来表示,如图2-7所示。
第三节 二维裁剪
一、线段裁剪
二、多边形裁剪
第三节 二维裁剪
在二维图形的绘制或显示处理中,有时需要给出或显示某一部分原始图形。这可在适当位置按一定边界范围定义一个矩形区域(即窗口),使窗口内图形为所需部分,将其保留下来作为绘制或显示之用,而窗口边界以外的图形则予以舍弃。这种对二维原始图形的处理称为二维裁剪。

Cohen-SutherLand裁剪算法(vc++)

Cohen-SutherLand裁剪算法(vc++)

Cohen-SutherLand裁剪算法(vc++)Cohen-SutherLand实现裁剪直线的两个关键函数//计算点 x,y的编码void CCohenSutherLandView::CompOutCode(float x,float y,CRect* rect,OutCode* outCode){outCode->all = 0;outCode->top = outCode->bottom =0;if (y < rect->top){outCode->top = 1;outCode->all += 1;}else if (y > rect->bottom){outCode->bottom = 1;outCode->all += 1;}outCode->right = outCode->left = 0;if (x > rect->right){outCode->right = 1;outCode->all += 1;}else if(x < rect->left){outCode->left = 1;outCode->all += 1;}}//CohenSutherLand线段裁剪算法void CCohenSutherLandView::CohenSutherLineClip(CDC* pDC,float x0,float y0,float x1,float y1, CRect* rect) {BOOL accept,done;OutCode outCode0,outCode1;OutCode *outCodeOut;float x,y;accept = FALSE;done = FALSE;CompOutCode(x0,y0,rect,&outCode0);CompOutCode(x1,y1,rect,&outCode1);do{if (outCode0.all == 0 && outCode1.all == 0) //完全可见{accept = TRUE;done = TRUE;}else if ((outCode0.all & outCode1.all) != 0) //显然可见{done = TRUE;}else //进⾏求交测试{if (outCode0.all != 0){outCodeOut = &outCode0;}else{outCodeOut = &outCode1;}if (outCodeOut->left){y = y0 + (y1 - y0) * (rect->left - x0) / (x1 - x0); //线段与窗⼝左边求交x = (float)rect->left;}else if (outCodeOut->top){x = x0 + (x1 - x0) * (rect->right - y0) / (y1 - y0); //线段与窗⼝上边求交y = (float) rect->top;}else if (outCodeOut->right){y = y0 + (y1 - x0) * (rect->right - x0) / (x1 - x0); //线段与窗⼝右边求交x = (float)rect->right;}else if (outCodeOut->bottom){x = x0 + (x1 - x0) * (rect->bottom - x0) / (y1 - y0); //线段与窗⼝下边求交y = (float)rect->bottom;}if (outCodeOut ->all == outCode0.all){x0 = x; //以交点为界,将线段位于窗⼝所在的直线的外侧的部分丢弃 y0 = y; //剩下的继续CompOutCode(x0,y0,rect,&outCode0);}else{x1 = x;y1 = y;CompOutCode(x1,y1,rect,&outCode1);}}} while(!done);if (accept){pDC->MoveTo(int(x0),int(y0));pDC->LineTo(int(x1),int(y1));}}具体原理等,参见《计算机图形学》北京⼤学出版社 倪明⽥等 第111页。

计算机图形学裁剪算法详解

计算机图形学裁剪算法详解

计算机图形学裁剪算法详解裁剪算法详解在使⽤计算机处理图形信息时,计算机内部存储的图形往往⽐较⼤,⽽屏幕显⽰的只是图的⼀部分。

因此需要确定图形中哪些部分落在显⽰区之内,哪些落在显⽰区之外,以便只显⽰落在显⽰区内的那部分图形。

这个选择过程称为裁剪。

最简单的裁剪⽅法是把各种图形扫描转换为点之后,再判断各点是否在窗内。

但那样太费时,⼀般不可取。

这是因为有些图形组成部分全部在窗⼝外,可以完全排除,不必进⾏扫描转换。

所以⼀般采⽤先裁剪再扫描转换的⽅法。

(a)裁剪前 (b) 裁剪后图1.1 多边形裁剪1直线段裁剪直线段裁剪算法⽐较简单,但⾮常重要,是复杂图元裁剪的基础。

因为复杂的曲线可以通过折线段来近似,从⽽裁剪问题也可以化为直线段的裁剪问题。

常⽤的线段裁剪⽅法有三种:Cohen-Sutherland,中点分割算法和梁友栋-barskey 算法。

1.1 Cohen-Sutherland裁剪该算法的思想是:对于每条线段P1P2分为三种情况处理。

(1)若P1P2完全在窗⼝内,则显⽰该线段P1P2简称“取”之。

(2)若P1P2明显在窗⼝外,则丢弃该线段,简称“弃”之。

(3)若线段既不满⾜“取”的条件,也不满⾜“弃”的条件,则在交点处把线段分为两段。

其中⼀段完全在窗⼝外,可弃之。

然后对另⼀段重复上述处理。

为使计算机能够快速判断⼀条直线段与窗⼝属何种关系,采⽤如下编码⽅法。

延长窗⼝的边,将⼆维平⾯分成九个区域。

每个区域赋予4位编码CtCbCrCl.其中各位编码的定义如下:图1.2 多边形裁剪区域编码图5.3线段裁剪裁剪⼀条线段时,先求出P1P2所在的区号code1,code2。

若code1=0,且code2=0,则线段P1P2在窗⼝内,应取之。

若按位与运算code1&code2≠0,则说明两个端点同在窗⼝的上⽅、下⽅、左⽅或右⽅。

可判断线段完全在窗⼝外,可弃之。

否则,按第三种情况处理。

求出线段与窗⼝某边的交点,在交点处把线段⼀分为⼆,其中必有⼀段在窗⼝外,可弃之。

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

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

大学实验报告学院:计算机科学与信息学院专业:软件工程班级: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);//得到多边形与裁剪窗口左边的交点第二种情况:线段在裁剪窗口的部,线段完全可见。

线段裁剪算法

线段裁剪算法

线段裁剪算法裁剪:确定图形中哪些部分落在显⽰区之内,哪些落在显⽰区之外,以便只显⽰落在显⽰区内的那部分图形。

这个选择过程称为裁剪。

图形裁剪算法,直接影响图形系统的效率。

Cohen-SutherLand直线裁剪算法1、基本思想对于每条线段P1P2分为三种情况处理:1. 若P1P2完全在窗⼝内,则显⽰该线段P1P2。

2. 若P1P2明显在窗⼝外,则丢弃该线段。

3. 若线段不满⾜(1)或(2)的条件,则在交点处把线段分为两段。

其中⼀段完全在窗⼝外,可弃之。

然后对另⼀段重复上述处理。

2、编码⽅法为了使计算机能够快速的判断⼀条线段与窗⼝属于何种关系,采⽤如下编码⽅法:把窗⼝的边界延长成直线,窗⼝平台就分成9个分区,每个区设定⼀个4位的编码与之对应。

平⾯上每⼀条直线的端点根据其所在的区域都可定义出两个编码。

编码(以⼆进制形式⾃右向左给出)的意义如下:1. 第0位:如果端点在窗⼝左边界左侧,则为1,否则为0;2. 第1位:如果端点在窗⼝右边界右侧,则为1,否则为0;3. 第2位:如果端点在窗⼝下边界下侧,则为1,否则为0;4. 第3位:如果端点在窗⼝上边界上侧,则为1,否则为0。

3、线段裁剪裁剪⼀条线段时,先求出端点p1和p2的编码code1和code2:1. 如果code1和code2均为0,则说明P1和P2均在窗⼝内,那么线段全部位于窗⼝内部,应取之。

(c)2. 如果code1和code2经过按位与运算后的结果code1&code2不等于0,说明P1和P2同时在窗⼝的上⽅、下⽅、左⽅或右⽅,那么线段全部位于窗⼝的外部,应弃之。

(e,d)3. 如果上述两种条件均不成⽴,则可按如下⽅法处理:求出线段与窗⼝边界的交点,在交点处把线段⼀分为⼆,其中必有⼀段完全在窗⼝外,可以弃之。

再对另⼀段重复进⾏上述处理,直到该线段完全被舍弃或者找到位于窗⼝内的⼀段线段为⽌。

(a,b,d’)4、检查顺序编码中对应位为1的边。

基于R树预处理的线段裁剪算法

基于R树预处理的线段裁剪算法
不 能突破 这个 复杂 度 . 是 , 但 一般 情况 下 窗 口都 要 比 图形 范 围小得 多 , 口内 的图形 只 占很 少一 部分 , 窗 这 在 矢量 电子地 图 的漫游 时显 得更 加 明显.
1 R树及其构造算 法
R树最 早是 由 G t a 在 1 8 ut n3 m 9 4年 提 出 的 , 它 是对 B+树 的一 种 延 伸 . R树 是 一 种 采 用 对 象 界 定 技术 的高 度 平 衡 树 , 中 用 对 象 的 最 小 外 包 矩 形 树 ( R) MB 来表 示对 象 . M 为每 个结 点所 能 容纳 的最 设
收 稿 日期 :0 8— 5—2 20 0 8 .
b 每个 非根结 点 包 含 的 实 体 个 数 介 于 i . n和 M
之间;
c所 有 叶子 结点 在 同一层 次 上. .
作者简介: 斌 (9 9 , 黑龙 江佳木斯人 , 陶 17 一) 男, 硕士研究生 , 主要从事计算机算法与辅助设计研究

种基 于 R树预 处理 的线段 裁剪算 法. 该算 法通过把 线段 集合预 先存储在 R树 中, 然后 再进行裁 剪 , 方 该
法极 大地提 高了裁 剪算法的整体效率. 对于比较 固定 的数 据 , 可以把预 处理 生成 的 R树 保存 下 来, 方便 以
后的裁剪. 改进 思路 也 同样 适 用 于其 他 的裁 剪 算 法 . 关键词 : 处理 ; 预 R树 ; 剪 ; 形 裁 矩 中 图 分 类 号 :P 0 . T 3 16 文 献 标 识码 : A 文章 编 号 :6 4— 3 X(0 8 0 06 — 4 17 3 0 2 0 )3— 0 1 0
法 , 基本 思想 是在 裁剪 之前 , 其 首先 对 图形 做一 个预
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

计算机图形学
实验报告
实验(四)
实验题目:线段裁剪算法
指导老师:吴颖斌
专业:数字媒体技术
班级: 1306班
姓名: xx(20131006xx)
2014年 11月19日
一、实验类型
验证性。

二、实验目的和要求
目的:编写线段裁剪算法程序,验证算法的正确性。

要求:编写Cohen-Sutherland直线剪裁算法程序,编译、调试,查看运行结果。

三、实验中用到的硬件设备及软件环境
Microsoft Visual C++ 6.0和PC机
四、实验主要程序代码
Cohen-Sutherland直线剪裁算法
(1)主要步骤和代码:
步骤1:创建Code_Clip工程文件;
步骤2:在主程序的程序头部定义符号常量(鼠标双击“CCode_ClipView”,添
加至
“class CCode_ClipView : public …………”之前)
#define LEFT 1
#define RIGHT 2
#define BOTTOM 4
#define TOP 8
步骤3:定义成员变量和成员函数(鼠标双击“CCode_ClipView”,添加至“class CCode_ClipView : public …………”之内))
int WT;
int WB;
int WR;
int WL;
步骤4:在构造函数中为窗口边界变量赋初值
CCode_ClipView::CCode_ClipView()
{
// TODO: add construction code here
WL=100;WR=400;WB=100;WT=300;
}
步骤5:编写成员函数程序(在“CCode_ClipView”单击鼠标右键-->Add member function……)
void CCode_ClipView::encode(int x, int y, int *code)
{
int c=0;
if (x<WL) c=c|LEFT;
else if (x>WR) c=c|RIGHT;
if (y<WB) c=c|BOTTOM;
else if (y>WT) c=c|TOP;
*code=c;
}
int CCode_ClipView::C_S_Line(CDC* pDC,int x1, int y1, int x2, int y2) {
// CDC *pDC=GetDC();
int code1,code2,code,x,y;
encode(x1,y1,&code1); //(x1,y1)处的编码
encode(x2,y2,&code2); //(x2,y2)处的编码
while (code1!=0||code2!=0) //当code1不等于0或code2不等于0
{
if ((code1&code2)!=0) return 0; //当code1与 code2不等于0,在同侧;
code=code1;
if (code1==0) code=code2;
if ((LEFT&code)!=0) //求交点
{
x=WL;
y=y1+(y2-y1)*(WL-x1)/(x2-x1);
}
else if ((RIGHT&code)!=0)
{
x=WR;
y=y1+(y2-y1)*(WR-x1)/(x2-x1);
}
else if ((BOTTOM&code)!=0)
{
y=WB;
x=x1+(x2-x1)*(WB-y1)/(y2-y1);
}
else if ((TOP&code)!=0)
{
y=WT;
x=x1+(x2-x1)*(WT-y1)/(y2-y1);
}
if (code==code1)
{
x1=x;y1=y;
encode(x,y,&code1);
}
else
{
x2=x;y2=y;
encode(x,y,&code2);
}
}
//end while,表示code1,code2都为0,其中的线段为可视部分 pDC->MoveTo(x1,y1);
pDC->LineTo(x2,y2);
}
步骤6:编写OnDraw()程序
void CCode_ClipView::OnDraw(CDC* pDC)
{
CCode_ClipDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
//定义三条直线的坐标
int x11,y11,x21,y21,x12,y12,x22,y22,x13,y13,x23,y23; x11=50;y11=150;x21=450;y21=250;
x12=150;y12=150;x22=350;y22=240;
x13=50;y13=400;x23=500;y23=350;
//定义画笔
CPen PenRed(PS_SOLID,1,RGB(255,0,0));//定义红色笔
CPen PenBlue(PS_SOLID,1,RGB(0,0,255));//定义蓝色笔
//先画出窗口,用蓝色
pDC->SelectObject(&PenBlue);
pDC->Rectangle(WL,WB,WR,WT);
//先画出三条直线,用红线
pDC->TextOut(x11,y11,"line1:");
pDC->MoveTo(x11,y11);pDC->LineTo(x21,y21);
pDC->TextOut(x12,y12,"line2:");
pDC->MoveTo(x12,y12);pDC->LineTo(x22,y22);
pDC->TextOut(x13,y13,"line3:");
pDC->MoveTo(x13,y13);pDC->LineTo(x23,y23);
//用蓝线,画出裁剪三条线
pDC->SelectObject(&PenBlue);
C_S_Line(pDC,x11,y11,x21,y21);
C_S_Line(pDC,x12,y12,x22,y22);
C_S_Line(pDC,x13,y13,x23,y23);
}
步骤7:编译、调试,查看运行结果。

(2)运行结果如图1所示。

五、程序运行结果或数据记录
图1 Cohen-Sutherland直线剪裁算法
六、实验总结与体会
通过本次实验,让我了解到了Cohen-Sutherland直线剪裁算法剪裁直线实现的具体过程,并且对剪裁直线的过程和特点也有个更进一步的学习和掌握。

由于用的是MFC实现的,所以通过此次实验,对MFC的使用也得到了强化。

相关文档
最新文档