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

实验报告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。
计算机图形学实验报告材料三图形裁剪算法

实验题目:实验三图形裁剪算法1.实验目的:理解区域编码(Region Code,RC)设计Cohen-Sutherland直线裁剪算法编程实现Cohen-Sutherland直线裁剪算法2.实验描述:设置裁剪窗口坐标为:wxl=250;wxr=850;wyb=250;wyt=450;裁剪前如下图所示:裁剪后结果为:3.算法设计:Cohen-Sutherland 直线裁剪算法:假设裁剪窗口是标准矩形,由上(y=wyt)、下(y=wyb)、左(x=wxl)、右(x=wxr)四条边组成,如下图所示。
延长窗口四条边形成 9个区域。
根据被裁剪直线的任一端点 P(x,y)所处的窗口区域位置,可以赋予一组4位二进制区域码C4C3C2C1。
编码定义规则:第一位C1:若端点位于窗口之左侧,即 X<Wxl,则 C1=1,否则 C1=0。
第二位C2:若端点位于窗口之右侧,即 X>Wxr,则 C2=1,否则 C2=0。
第三位C3:若端点位于窗口之下侧,即 Y<Wyb,则 C3=1,否则 C3=0。
第四位C4:若端点位于窗口之上侧,即 Y>Wyt,则 C4=1,否则 C4=0。
裁剪步骤:1. 若直线的两个端点的区域编码都为0,即 RC1|RC2=0(二者按位相或的结果为0,即 RC1=0 且RC2=0),说明直线两端点都在窗口内,应“简取”。
2. 若直线的两个端点的区域编码都不为0,即 RC1&RC2≠0(二者按位相与的结果不为0,即 RC1≠0且 RC2≠0,即直线位于窗外的同一侧,说明直线的两个端点都在窗口外,应“简弃”。
3. 若直线既不满足“简取”也不满足“简弃”的条件,直线段必然与窗口相交,需要计算直线与窗口边界的交点。
交点将直线分为两段,其中一段完全位于窗口外,可“简弃”。
对另一段赋予交点处的区域编码,再次测试,再次求交,直至确定完全位于窗口内的直线段为止。
4. 实现时,一般按固定顺序左(x=wxl)、右(x=wxr)、下(y=wyb)、上(y=wyt)求解窗口与直线的交点。
4上机实验报告3:图形裁剪算法的具体实现

计算机图形学课程实验报告信息与计算科学(三)上机实验3:裁剪算法班级:姓名:学号:上机实验(3)的题目和要求一、实验目的掌握图形裁剪算法的基本思想,并能上机编程实现相应的算法。
二、实验要求(Direction)1.每个学生单独完成。
2.开发语言规定为C语言。
3.请在自己的实验报告上写明姓名、学号、班级。
4.每次交的实验报告内容包括:试验目的和意义、题目、程序制作步骤、主程序(包括源代码注释)。
三、实验题目实验题1:上机编一程序实现直线的中点裁剪算法。
具体要求如下说明:1 该程序能实现窗口屏幕上任意一条直线的裁剪;2 直线段要求可以随机输入;运行结果图:裁剪之前裁剪之后#define LE 2#define RI 4#define BO 6#define TO 10#define XLEFT 150#define XRIGHT 350#define YBOTTOM 150#define YTOP 300#include "math.h"#include "stdio.h"#include "graphics.h"void main(){int x1,y1,x2,y2,xx,yy,xxx,yyy;int graphdriver=DETECT,graphmode;initgraph(&graphdriver,&graphmode," ");setcolor(6);line(XLEFT,YTOP,XRIGHT,YTOP);line(XLEFT,YBOTTOM,XRIGHT,YBOTTOM);line(XLEFT,YTOP,XLEFT,YBOTTOM);line(XRIGHT,YTOP,XRIGHT,YBOTTOM);x1=50;y1=200;x2=400;y2=300;setcolor(1);line(x1,y1,x2,y2);xx=0;yy=0;xxx=0;yyy=0;draw_ett(x1,y1,x2,y2,&xx,&yy);draw_ett(x2,y2,xx,yy,&xxx,&yyy);setcolor(4);line(xx,yy,xxx,yyy);getch();closegraph();}int encode (int x, int y, int *code){ int c=0;if (x<XLEFT) c=c|LE;else if (x>XRIGHT) c=c|RI;if (y<YBOTTOM) c=c|BO;else if (y>YTOP) c=c|TO;*code=c;return code;}draw_ett(int x1, int y1, int x2, int y2, int *x, int *y) { int code1,code2,code;int xx,yy;float d,d1,d2;encode(x1,y1,&code1);encode(x2,y2,&code2);if (code2==0) { xx=x2;yy=y2; *x=xx; * y=yy;return;}if ((code1&code2)!=0) return;L1: xx=(x1+x2)/2;yy=(y1+y2)/2;encode(xx, yy, &code);d1=(yy-y1)*(yy-y1);d2=(xx-x1)*(xx-x1);d=sqrt(d1+d2);if (d<=1) { *x=xx;*y=yy; return;}if ((code&code1)!=0){ x1=xx; y1=yy; }else { x2=xx; y2=yy;}goto L1;}实验题2:实现Sutherland-Hodgeman多边形裁剪算法。
计算机图形学实验Cohen-Sutherland算法

实验5-6一、实验题目请按照图5-32所示,使用对话框输入直线段的起点和终点坐标。
在屏幕客户区左侧区域绘制输入直线段和“窗口”,在屏幕客户区右侧区域绘制“视区”并输出裁剪结果。
这里需要用到窗视变换公式。
请使用Cohen-Sutherland 算法编程实现。
二、实验思想Cohen-Sutherland 直线裁剪算法是最早流行的编码算法。
每条直线的端点都被赋予一组四位二进制代码,称为区域编码(Region Code ,RC),用来标识直线端点相对于窗口边界及其延长线的位置。
假设窗口是标准矩形,由上(y=w yt )、下(y=w yb )、左(x=w xl )、右(x=w xr )四条边组成,如图5-23所示。
延长窗口四条边形成9个区域,如图5-24所示。
这样根据直线的任一端点P(x,y)所处的窗口区域位置,可以赋予一组4位二进制区域码RC =C 4C 3C 2C 1。
w yb w yt wxr w xl为了保证窗口内直线端点的编码为零,编码规则定义如下:第一位:若端点位于窗口之左侧,即x<w xl,则C1=1,否则C1=0。
第二位:若端点位于窗口之右侧,即x>w xr,则C2=1,否则C2=0。
第三位:若端点位于窗口之下侧,即y<w yb,则C3=1,否则C3=0。
第四位:若端点位于窗口之上侧,即y>w yt,则C4=1,否则C4=0。
裁剪步骤如下:(1)若直线的两个端点的区域编码都为零,即RC1|RC2=0,说明直线两端点都在窗口内,应“简取”之。
(2)若直线的两个端点的区域编码都不为零,即RC1&RC2≠0,即直线位于窗外的同一侧,说明直线的两个端点都在窗口外,应“简弃”之。
(3)若直线既不满足“简取”也不满足“简弃”的条件,直线必然与窗口或窗口边界的延长线相交,需要计算直线与窗口边界的交点。
交点将直线分为两段,其中一段完全位于窗口外,可“简弃”之。
对另一段重复进行上述处理,直至该直线段完全被舍弃或找到完全位于窗口内的直线段为止。
计算机图形学实验指导书--实验2使用线段剪裁

实验2使用线段剪裁Cohen——sutherland算法一.实验目的及要求根据Cohen——sutherland算法,掌握直线剪裁的程序设计方法。
注意,不能使用语言库中的画圆函数。
二.理论基础将不需要裁剪的直线挑出,并删去其中在窗外的直线,然后对其余直线,逐条与窗框求交点,并将窗框外的部分删去。
采用Cohen-Sutherland直线剪裁的算法一区域编码为基础,将窗口及周围的八个方向以4位的二进制数进行编码。
4个位分代表窗外上,下,左右的编码值。
三、算法分析1. Cohen—SutherLand直线裁剪算法裁剪的实质,就是决定图形中那些点、线段、文字、以及多边形在窗口之内。
Cohen—SutherLand直线裁剪算法的基本大意是:对于每条线段P1P2,分为三种情况处理。
1) 若P1P2完全在窗口内,则显示该线段P1P2,简称“取”之。
2) 若P1P2明显在窗口外,则丢弃该线段P1P2,简称“弃”之。
3) 若线段既不满足“取”的条件,也不满足“弃”的条件,则把线段分为两段。
其中一段完全在窗口外,可弃之。
然后对另一段重复上述处理。
为了使计算机能够快速地判断一条线段与窗口属何种关系,采用如下的编码方法。
延长窗口的边,把未经裁剪的图形区域分为9个区,每个区具有一个四位代码,即四位二进制数,从左到右各位依次表示上、下、左、右。
裁剪一条线段时,先求出端点P1P2所在的区号code1和code2。
若code1=0且code2=0,则说明P1和P2均在窗口内,那么整条线段也比在窗口内,应取之。
若code1和code2经按位与运算后的结果code1&code2不为0,则说明两个端点同在窗口的上方、下方、左方或右方。
若上述两种条件均不成立,则按第三种情况处理,求出线段与窗口某边的交点,在交点处把线段一分为二,其中必有一段完全在窗口外,可以弃之。
再对另一段重复进行上述处理。
计算线段与窗口边界(或其延长线)的交点,属于线段与直线求交问题。
图形学实验报告2

return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CTransformView drawing
三、实验要求:
实验前须规划程序界面和按钮的相关事件的编写代码。实验时进行代码的调试。
四、实验代码
1,图形的变换
// TransformView.cpp : implementation of the CTransformView class
//
#include "stdafx.h"
#include "Transform.h"
#include "TransformDoc.h"
#include "TransformView.h"
#include <math.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
for(i=1; i<3; i++)
{
Pt[i].x *= 0.5;
Pt[i].y *= 0.5;
}
Pt[0] = TmpPt;
Pt[1] = Pt[1] + Pt[0];
Pt[2] = Pt[2] + Pt[0];
break;
case 0X58://X的ASCII码
计算机图形学-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),两个交点的连线就是裁剪结 果。
计算机图形学裁剪算法

一、实验目标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,表明两端点必定处于某一边界的同一外侧,因而整个线段全在窗外,应予舍弃。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一、实验目的:直线段的裁剪:编码裁剪算法,中点分割裁剪算法。
二、实验内容://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直线裁剪算法更快。