计算机图形学实验指导书--实验2使用线段剪裁
计算机图形学裁剪技术
求交测试顺序固定(左右下上) 最坏情形,线段求交四次。
裁剪
直线段裁剪
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)的条件,则在交点处把线段
分为两段。其中一段完全在窗口外,可弃之。然后对另一段 重复上述处理。
如何实现上述的处理呢?
实现方法:采用下面的编码方法
《计算机图形学》实验指导书
计算机图形学实验指导书袁科计算机技术实验中心目录实验一实现DDA、中点画线算法和Bresenham画线算法 (24)实验二实现Bezier曲线 (25)实验三实现B样条曲线 (26)实验四实现多边形填充的边界标志算法 (27)实验五实现裁剪多边形的Cohen-Sutherland算法 (28)实验六二维图形的基本几何变换 (30)实验七画图软件的编制 (31)实验一实现DDA、中点画线算法和Bresenham画线算法【实验目的】1、掌握直线的多种生成算法;2、掌握二维图形显示原理。
【实验环境】VC++6.0/ BC【实验性质及学时】验证性实验,2学时,必做实验【实验内容】利用任意的一个实验环境,编制源程序,分别实现直线的三种生成算法,即数字微分法(DDA)、中点画线法以及Bresenham画线算法。
【实验原理】1、数字微分法(Digital Differential Analyzer,DDA)算法思想:基于直线的微分方程来生成直线。
ε=1/max(|△x|,|△y|)max(|△x|,|△y|)=|△x|,即|k|≤1 的情况:max(|△x|,|△y|)=|△y|,此时|k|≥1:2、中点画线法算法思想:每次在最大位移方向上走一步,另一方向是否走步取决于误差项的判断。
3、Bresenham画线算法算法思想:其基本思想同中点算法一样,即每次在最大位移方向上走一步,而另一个方向是否走步取决于误差项的判断。
【实验要求】1.上交源程序;2.上交实验报告,实验报告内容如下:(1) 实验名称(2) 实验目的(3) 算法实现的设计方法及程序流程图(4) 程序结果分析【分析与思考】(1) 上述所阐述的三个算法,其基本算法只能适用于直线的斜率(|K|<=1) 的情形,如何将上述算法进行推广,使其能够处理任意斜率的直线?(2) 计算机显示屏幕的坐标圆心在哪里,与我们平时的习惯有什么差异,如何协调二者?实验二 实现Bezier 曲线【实验目的】1、掌握Bezier 曲线的定义;2、能编程实现N 次Bezier 曲线的绘制与显示。
计算机图形学实验指导书
《计算机图形学》实验指导书华南农业大学信息学院信息学院章晓华主编目录第一部分《计算机图形学》实验要求 (1)一、《计算机图形学》实验教学概述 (1)1、实验教学的基本情况 (1)2、实验教学的指导思想和教学目的 (1)3、实验项目表 (1)二、《计算机图形学》实验教学规范 (2)1、实验课的意义 (2)2、实验步骤 (2)3、实验报告(文档)规范 (2)4、实验考核 (3)第二部分实验内容 (4)实验一图元的生成算法 (4)实验二多边形填充 (7)实验三二维图形变换 (14)实验四直线Sutherland算法的实现 (22)实验五二维图形系统 (26)第一部分《计算机图形学》实验要求一、《计算机图形学》实验教学概述1、实验教学的基本情况课程总学时数:48学时;课程总学分:3学分实验总学时:16适用专业:信息学院计算机科学与技术、软件工程、网络工程专业,软件学院软件工程专业考核方式及方法:实际操作+程序运行+实验报告。
实验成绩、考勤及书面作业成绩组成平时成绩。
平时成绩占课程总成绩30%,考试成绩占课程总成绩70%。
成绩评定:在参考“难度系数”的基础上>=90——选做内容/必做内容功能完善,编程风格好,人机接口界面好;80~90——必做内容功能完善,完成部分选做内容,编程风格好,人机接口界面良好;70~80——完成必做内容,编程风格良好;60~70——能完成必做内容;<60——未按时完成必做内容,或者抄袭(含雷同者)。
2、实验教学的指导思想和教学目的1)指导思想:掌握计算机图形的生成技术和生成各种平面图形和简单立体图形的基本算法,掌握图形填充、裁剪、图形变换及图形消隐等计算机图形处理的基本方法,初步掌握用C++语言编写基本图形生成和处理程序的方法,为后续的课程奠定良好的基础。
2)教学目的:为了使学生在课程学习的同时,通过在具体的编程环境中的实际操作,对计算机图形学的基本概念和方法能有一个初步的了解,使学生加深了解和更好地掌握《计算机图形学》课程教学大纲要求的内容,并培养学生动手编程解决实际问题的能力,训练学生分析问题和调试程序的能力,锻炼学生撰写科技实验论文的能力。
计算机图形学基础实验指导书
计算机图形学基础实验指导书目录实验一直线的生成 ............................................................... -..2.-实验二圆弧及椭圆弧的生成........................................................ -..3 -实验三多边形的区域填充 ......................................................... - (4)-实验四二维几何变换 ............................................................. -..5.-实验五裁剪算法 ................................................................. -..6.-实验六三维图形变换 ............................................................. -..7.-实验七BEZIER 曲线生成......................................................... -..8.-实验八交互式绘图技术实现........................................................ -..10-实验一直线的生成一、实验目的掌握几种直线生成算法的比较,特别是Bresenham 直线生成算法二、实验环境实验设备:计算机实验使用的语言: C 或Visual C++ 、OpenGL三、实验内容用不同的生成算法在屏幕上绘制出直线的图形,对不同的算法可设置不同的线形或颜色表示区别。
四、实验步骤直线Bresenham 生成算法思想如下1)画点(x i, y i), dx=x2-x i, dy=y2-y i,计算误差初值P i=2dy-dx , i=1;2)求直线下一点位置x i+i=x i+i 如果P i>0,贝U y i+i=y i+i,否则y i+i=y i;3)画点(x i+i ,y i+i );4)求下一个误差P i+i 点,如果P i>0,贝U P i+i=P i+2dy-2dx,否则P i+i=P i+2dy;i=i+i ,如果i<dx+i 则转步骤2,否则结束操作。
计算机图形学基础实验指导书
《计算机图形学基础》实验指导书课程名称:计算机图形学基础英文名称:Computer Graphics课程性质:必修课程编号:适应专业:计算机科学与技术;软件工程学时学分:总学时48,实验学时102,总学分2编写人:王创存一、实验课程任务与要求1. 目的与任务:计算机图形学实验教学是为了将学生的计算机操作能力、分析能力、工程设计能力与应用实践结合起来,引导学生由浅入深地掌握计算机图形学理论与算法,掌握交互构图能力,具备工程应用的图形学基础。
本实验教学主要内容是要求学生用Visual Basic编程实现各种图形的绘制,强化学生的程序设计能力和程序调试能力,使学生巩固所学各种图形的生成算法的理论知识。
实践教学共包括十项内容。
2. 实验基本要求:(以软件设计为主要表现形式)上机前应准备好实验的程序设计算法描述与关键分析内容;准备好程序测试数据和设备操作步骤,上机调试、运行;完成每个实验后进行数据与程序对比分析,给出运行结果。
二、实验内容与学时安排实验一、图形输入/输出设备的操作使用及简单图形的输出(2学时)要求:(1)掌握图形设备的操作过程;测试图形设备的分辨率、性能;(2)图形软件包与外部设备的连接参数配置;(3)利用图形软件包绘制简单图形并在设备上输出;(4)设计菜单,实现人机交互方式控制图形设备进行简单操作实验二、编程环境及图形绘制基础练习(2学时)题目:绘制分形树基本要求:)数据输入项为:树干的起点坐标,树干长度,树枝倾斜角度,树枝层数,最短树枝;)结果直接输出在窗体中。
附加要求:(1)通过用户输入可改变线型(实线、虚线与点划线)。
(2)通过用户输入可改变线宽。
实验三、直线的绘制(2学时)题目:用逐点比较法或中点Bresenham法实现直线的绘制基本要求:)数据输入项为:直线的起点与终点坐标;)直线与圆输出在PictureBox控件中;)保存图形绘制结果,将该实验加入到菜单中去。
实验四、圆的绘制(2学时)题目:用逐点比较法或中点Bresenham法实现圆的绘制基本要求:)数据输入项为:圆心坐标与半径;)直线与圆输出在PictureBox控件中;)保存图形绘制结果,将该实验加入到菜单中去。
计算机图形学裁剪算法
一、实验目标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,表明两端点必定处于某一边界的同一外侧,因而整个线段全在窗外,应予舍弃。
计算机图形学实验 两种裁剪算法
Cohen-Sutherland裁剪算法#include<GL/glut.h>#include<math.h>class wcPt2D{public:GLfloat x,y;};inline GLint round(const GLfloat a){return GLint(a+0.5);}const GLint winLeftBitCode = 0x1;const GLint winRightBitCode = 0x2;const GLint winBottomBitCode = 0x4;const GLint winTopBitCode = 0x8;void init(void){glClearColor(1.0,1.0,1.0,0.0);glMatrixMode(GL_PROJECTION);gluOrtho2D(0.0,640.0,0.0,480.0);glMatrixMode(GL_MODELVIEW);}void setPixel(GLint xCoord,GLint yCoord){glBegin(GL_POINTS);glVertex2i(xCoord,yCoord);glEnd();}void lineBres (int x0,int y0,int xend,int 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);}}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){wcPt2D tmp;tmp = *p1;*p1 = *p2;*p2 = tmp;}void swapCodes(GLubyte *c1,GLubyte *c2){GLubyte tmp;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{if(inside(code1)){swapPts(&p1,&p2);swapCodes(&code1,&code2);}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){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 display(void){int flag = 1;wcPt2D winMin,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(0.0,0.0,1.0);glRectf(winMin.x,winMin.y,winMax.x,winMax.y);//绘制蓝色裁剪矩形glColor3f(1.0,1.0,1.0);if (flag){lineClipCohSuth (winMin, winMax,p1,p2);// 绘制裁剪线段}else{glBegin(GL_LINES);glVertex2i(p1.x,p1.y);glVertex2i(p2.x,p2.y);glEnd();}glFlush();}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(unsigned char key, int x, int y){int flag;if (key=='c' || key=='C') flag=1;if (key=='r' || key=='R') flag=0;glutPostRedisplay();}void main(int argc,char **argv){glutInit(&argc,argv);glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);glutInitWindowPosition(100,100);glutInitWindowSize(640,480);glutCreateWindow("chaungkou");init();glutDisplayFunc(display);glutReshapeFunc(Reshape);glutKeyboardFunc(keyboard);glutMainLoop();}梁友栋-Barsky线段裁剪算法#include<GL/glut.h>#include<math.h>#include<stdlib.h>class wcPt2D{public:GLfloat x,y;setCoords(GLfloat xCoord,GLfloat yCoord){x = xCoord;y = yCoord;}GLfloat getx() const{return x;}GLfloat gety() const{return y;}};void init(void){glClearColor(1.0,1.0,1.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);}inline GLint round(const GLfloat a){return GLint(a+0.5);}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 setPixel(GLint xCoord,GLint yCoord){glBegin(GL_POINTS);glVertex2i(xCoord,yCoord);glEnd();}void lineBres(int x0,int y0,int xEnd,int 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);}}void lineClipLiangBarsk(wcPt2D winMin,wcPt2D winMax,wcPt2D p1,wcPt2D p2) {GLfloat u1 = 0.0,u2 = 1.0,dx = p2.getx() - p1.getx(),dy;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(round(p1.getx()),round(p1.gety()),round(p2.getx()),round(p2.gety()));}}}void display(){GLint flag = 1;wcPt2D winMin , 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 (0.3, 0.8, 0.7);glRectf(winMin.x ,winMin.y ,winMax.x,winMax.y); //绘制裁剪矩形glColor3f (1.0, 1.0, 1.0);if (flag){lineClipLiangBarsk (winMin, winMax,p1,p2);// 绘制裁剪线段}else{glBegin(GL_LINES);glVertex2i(p1.x,p1.y);glVertex2i(p2.x,p2.y);glEnd();}glFlush();}void main(int argc,char **argv){glutInit(&argc,argv);glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);glutInitWindowPosition(50,50);glutInitWindowSize(600,600);glutCreateWindow("Demo");init();glutDisplayFunc(display);glutReshapeFunc(Reshape);glutMainLoop();}这两个都是完整的程序,可以直接用~。
计算机图形学实验报告实验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直线裁剪算法更快。
计算机图形学实验五直线段裁剪
计算机图形学实验报告黔南民族师范学院信息与计算科学撰写人姓名: __ 撰写时间:2010年5月5日审查人姓名:实验过程记录一、实验目的:1、通过实验,进一步理解和掌握直线段的裁剪算法;2、通直线段的裁剪。
二、实验内容:要求:•1 、进一步理解并掌握线段的裁剪算法,并可以实践至少一种线段的裁剪算法;•2、注意:本次作业要求学生不能直接使用系统提供的线段裁剪函数,但是可以调用相关的画点、画线函数。
三、实验设备及软件软件需求:windows98以上操作系统、Turbo C 2.0 、Turbo C++3.0、Visual C++软件、Microsoft Word 97或2000。
硬件需求:建议Pentium IV CPU处理器、64MB以上内存、1GB以上硬盘空间的计算机、激光打印机四、实验方法及步骤1 实验准备上该实验课前将针对解决实验内容问题的C语言程序编制好,在实验课上,对编制完的程序进行调试、修改和分析,熟悉TurboC2.0的菜单,以及编译,运行程序和调试程序的方法,并编写程序。
2. 调试程序;程序一:#define LEFT 1#define RIGHT 2#define BOTTOM 4#define TOP 8#define XL 150#define XR 350#define YB 150#define YT 300#include <math.h>#include"graphics.h"main(){ int gdriver=DETECT,gmode;initgraph(&gdriver,&gmode,"c:\\tc");setcolor(12);line(XL,YT,XR,YT);line(XL,YB,XR,YB);line(XL,YT,XL,YB);line(XR,YT,XR,YB);setcolor(9);draw_ett();getch();closegraph();}encode (x,y,code)int x,y;int *code;{ int c;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;return;}draw_ett(){ int x1,x2,y1,y2,x,y;int code1,code2,code;/* printf("XL=150,XR=350,YB=150,YT=300\n");scanf("%d,%d,%d,%d",&x1,&y1,&x2,&y2);*/x1=50;y1=210;x2=300;y2=100;setcolor(2);line(x1,y1,x2,y2);encode(x1,y1,&code1);encode(x2,y2,&code2);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);}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;encode(x,y,&code1);}else{ x2=x;y2=y;encode(x,y,&code2);}}setcolor(14);line(x1,y1,x2,y2);return;}运行结果:程序二:请按书上P109的Cohen-Sutherland算法写出完整的程序,并运行出效果图,可参考以上程序一#define XL 150#define XR 350#define YB 150#define YT 300#define FALSE 0#define TRUE 1#include <math.h>#include"graphics.h"typedef struct{int xmin,xmax,ymin,ymax;}Rectangle;typedef int boolean;typedef struct{unsigned all;unsigned left,right,top,bottom;}OutCode;void CompOutCode(float x,float y,Rectangle *rect,OutCode *outCode){outCode->all=0;outCode->top=outCode->bottom=0;if(y>(float)rect->ymax){outCode->top=1;outCode->all+=1;}else if(y<(float)rect->ymin){outCode->bottom=1;outCode->all+=1;}outCode->right=outCode->left=0 ; if(x>(float)rect->xmax){outCode->right=1;outCode->all+=1;}else if(x<(float)rect->xmin){outCode->left=1;outCode->all+=1;}}void CSLineClip(float x0,float y0,float x1,float y1,Rectangle *rect){boolean 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;elseoutCodeOut=&outCode1;if(outCodeOut->left){y=y0+(y1-y0)*(rect->xmin-x0)/(x1-x0);x=(float)rect->xmin;}else if(outCodeOut->top){x=x0+(x1-x0)*(rect->ymax-y0)/(y1-y0);y=(float)rect->ymax;}else if(outCodeOut->right){y=y0+(y1-y0)*(rect->xmax-x0)/(x1-x0);x=(float)rect->xmax;}else if(outCodeOut->bottom){x=x0+(x1-x0)*(rect->ymin-y0)/(y1-y0);y=(float)rect->ymin;}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){line((int)x0,(int)y0,(int)x1,(int)y1);}}main(){ int gdriver=DETECT,gmode;Rectangle rect;rect.xmin=XL;rect.xmax=XR;rect.ymin=YB;rect.ymax=YT;initgraph(&gdriver,&gmode,"c:\\tc"); setcolor(12);line(XL,YT,XR,YT);line(XL,YB,XR,YB);line(XL,YT,XL,YB);line(XR,YT,XR,YB);setcolor(2);line(100,100,300,400);setcolor(WHITE);CSLineClip(100,100,300,400,&rect);getch();closegraph();}成绩评定:指导教师:。
图形学实验报告--线段裁剪
计算机科学与技术学院2013-2014学年第一学期《计算机图形学》实验报告班级:110341B班学号:110341228姓名:王陈教师:惠康华成绩:实验项目: 二维裁剪一、实验目的与要求(1)掌握线段裁剪算法原理,并实现其算法。
(2)理解多边形裁剪、字符裁剪算法思想,能编程实现其算法。
二、实验内容(1)实现直线段的标号法、矩形窗口裁剪算法。
(2)参考教材中的算法,用矩形窗口实现多边形的裁剪算法。
三、重要算法分析(一)线段裁剪Cohen-Sutherland算法实验原理:1、线段裁剪生成算法:对于矩形的窗口,任何直线至多只有一段处于该窗口之内,即在此窗口范围内永远不会产生一条直线的两条或更多的可见部分线段。
该算法的基本思想为:对于每条待裁剪的线段分完全在窗口内(此时不需要裁剪,全部显示)、完全在窗口外(此时不需要裁剪,整条线段不显示)、部分在窗口内部分在窗口外三种情况讨论。
将窗口及其周围的八个方向以四位的二进制数进行编码,用来快速判断一条直线段与窗口属于何种关系。
其中全为0的区域为裁剪窗口。
(1) 判断线段两个端点的四位二进制编码,如果全为0,即两端点编码逻辑或运算为0,那么该线段完全位于窗口内,可直接保留;(2) 对两端点的四位二进制编码进行逻辑与运算,若结果不为0,那么整条线段必位于窗口外,可直接舍弃。
(3) 如果以上两种情况皆不是,则这条线段既不能直接保留,也不能直接舍弃,它可能与窗口相交。
此时,需要对线段进行再分割,即找到与窗口边线的一个交点,根据交点位置,赋予四位二进制编码,并对分割后的线段按照一定的顺序(左右下上)进行检查,决定保留、舍弃或再次进行分割。
(4) 重复第三步,直到出现正确的裁剪结果为止。
四、实验结果截图裁剪线段1、双击击鼠标左键,出现要裁剪的线段:如图3-1图3-1 生成裁剪窗口和待裁剪线段2、裁剪后的结果:如图3-2图3-2 裁剪后的结果五、总结与调试经验1、程序初期的结构搭建很重要:在VC中选择MFC APPWizard(exe),建立单文档应用程序,编辑菜单资源,重置ID,添加消息处理函数,建立类向导,最后添加程序代码。
图形学实验报告直线段的裁剪算法
实验报告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。
简述利用sutherland的直线段裁剪方法
简述利用sutherland的直线段裁剪方法Sutherland的直线段裁剪方法是一种常见的计算机图形学中的算法。
该算法的目的是在二维平面上裁剪出线段,使其仅显示线段与裁剪边界的
交集。
该算法的过程如下:
1.由裁剪边界确定一个裁剪窗口,其中包括一个左、右、上和下四个
裁剪边界。
2.通过比较线段的端点与裁剪边界,确定线段是否跨过裁剪边界,并
同时保存线段于裁剪边界的相交点。
3.计算出线段与裁剪边界相交点的参数值(也称交点)和线段的斜率,再根据这些值确定线段与裁剪窗口的交集。
4.把裁剪后的线段输出或者显示出来。
通过这种方法,可以有效地减少不必要的计算并缩短执行时间,同时
也可以减少对图形性能的影响。
它被广泛地应用于计算机图形学中,并在
裁剪方面被广泛地采用。
计算机图形学之裁剪算法
窗口特别小的场合。
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算法是最早的、使用最广泛的线
段裁剪算法之一。在裁剪窗口很大,大部分线段完全
可见,或裁剪窗口很小,大部分线段完全不可见的情 况下,该算法特别有效;在一般情况下,该算法有时 要做不必要的求交运算,因而效率不是太高.
线段裁剪算法
线段裁剪算法裁剪:确定图形中哪些部分落在显⽰区之内,哪些落在显⽰区之外,以便只显⽰落在显⽰区内的那部分图形。
这个选择过程称为裁剪。
图形裁剪算法,直接影响图形系统的效率。
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的边。
直线段剪裁实验报告
直线段剪裁实验报告摘要:本实验旨在通过剪裁算法对直线段进行处理,并观察其效果。
我们使用了一种常见的直线段剪裁算法——Cohen-Sutherland剪裁算法,并进行了详细的实验步骤和结果分析。
实验结果表明,Cohen-Sutherland算法能够有效地剪裁直线段,实现了准确的剪裁效果。
引言:计算机图形学中,直线段剪裁是一个重要的问题,尤其在计算机辅助设计和计算机游戏开发中具有广泛的应用。
通常情况下,直线段剪裁是指对一个直线段进行裁剪,使其仅保留在给定的裁剪窗口内。
方法:本实验使用了Cohen-Sutherland剪裁算法对直线段进行处理。
该算法是由Cohen和Sutherland于1967年提出的,是一种简单且高效的直线段剪裁算法。
它基于直线段的两端点(即P1和P2)分别与裁剪窗口的四个边界进行比较的原理,并根据他们的位置关系进行适当的处理。
算法的基本思想如下:1. 对于直线段的起点和终点,分别进行位置编码;2. 根据位置编码的结果,判断直线段是否完全在裁剪窗口内,如果是,则直接保留该直线段;3. 如果直线段完全在裁剪窗口外,那么可以直接舍弃该直线段;4. 如果直线段与裁剪窗口相交,那么可以根据交点计算出新的直线段。
实验步骤:1. 定义一个裁剪窗口(如矩形),并确定其边界;2. 输入一个需要进行剪裁的直线段,确定其起点P1和终点P2;3. 分别对P1和P2进行位置编码,得到4位二进制编码;4. 根据位置编码对两个顶点进行判断,确定直线段与裁剪窗口的位置关系;5. 根据位置关系来进行适当的处理:- 如果直线段完全在裁剪窗口内,则保留该直线段;- 如果直线段完全在裁剪窗口外,则舍弃该直线段;- 如果直线段与裁剪窗口相交,则根据交点计算出新的直线段;6. 输出剪裁后的直线段。
结果分析:经过多组实验数据的对比,我们发现Cohen-Sutherland算法能够很好地剪裁直线段,实现了准确的剪裁效果。
由于算法的采取了二进制编码的方式,可以高效地判断直线段与裁剪窗口的位置关系,并进行适当的处理。
直线段剪裁实验报告
《计算机图形学》实验报告《实验名称》直线段裁剪学号专业班级天津大学计算机科学与技术学院一、实验目的熟练掌握Cohen-Sutherland直线裁剪算法,并编程实现二、实验内容(1) 裁剪窗口为矩形窗口,且矩形边和坐标轴平行,长宽自己定。
(2) 待裁剪线段端点坐标自己定;裁剪线段涵盖完全可见、不完全可见、完全不可见类型。
(3) 要求显示待裁剪线段并用不同颜色标示出裁剪结果。
实现方法:一般情况下,需要判断一条直线是全部可见,全部不可见,部分裁剪(一段裁剪),全部裁剪(两端裁剪)。
通过把裁剪区域分成许多部分,然后给每一段被裁剪的线段的两端分配一位代码,通过少量if语句和一个case语句就可以判断出具体情况。
伪代码如下:#define CLIP_CODE_C 0x0000#define CLIP_CODE_N 0x0008#define CLIP_CODE_S 0x0004#define CLIP_CODE_E 0x0002#define CLIP_CODE_W 0x0001#define CLIP_CODE_NE 0x000a#define CLIP_CODE_SE 0x0006#define CLIP_CODE_NW 0x0009#define CLIP_CODE_SW 0x0005实验步骤:1)生成裁剪窗口,窗口由直线xl=250,xr=850,yb=250,yt=4502)绘制直线段3)编写Cohen-Sutherland直线裁剪算法,对直线段进行裁剪编码定义规则:第一位C1:若端点位于窗口之左侧,即X<xl,则C1=1,否则C1=0。
第二位C2:若端点位于窗口之右侧,即X>xr,则C2=1,否则C2=0。
第三位C3:若端点位于窗口之下侧,即Y<yb,则C3=1,否则C3=0。
第四位C4:若端点位于窗口之上侧,即Y>yt,则C4=1,否则C4=0。
裁剪步骤:对所有直线的端点都建立了区域码之后,就可按区域码判断直线在窗口之内或窗口之外。
计算机图形学裁剪算法详解
裁剪算法详解在使用计算机处理图形信息时,计算机内部存储的图形往往比较大,而屏幕显示的只是图的一部分。
因此需要确定图形中哪些部分落在显示区之内,哪些落在显示区之外,以便只显示落在显示区内的那部分图形。
这个选择过程称为裁剪。
最简单的裁剪方法是把各种图形扫描转换为点之后,再判断各点是否在窗内。
但那样太费时,一般不可取。
这是因为有些图形组成部分全部在窗口外,可以完全排除,不必进行扫描转换。
所以一般采用先裁剪再扫描转换的方法。
(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,则说明两个端点同在窗口的上方、下方、左方或右方。
可判断线段完全在窗口外,可弃之。
否则,按第三种情况处理。
求出线段与窗口某边的交点,在交点处把线段一分为二,其中必有一段在窗口外,可弃之。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验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,则说明两个端点同在窗口的上方、下方、左方或右方。
若上述两种条件均不成立,则按第三种情况处理,求出线段与窗口某边的交点,在交点处把线段一分为二,其中必有一段完全在窗口外,可以弃之。
再对另一段重复进行上述处理。
计算线段与窗口边界(或其延长线)的交点,属于线段与直线求交问题。
在实现本算法时,不必把线段与每条窗口边界依次求交,只要按顺序检测到端点区码的某位不为0时,才把线段与对应的窗口边界进行求交。
四、提示代码#include<stdio.h>#include<graphics.h>void initgr(void) /* BGI初始化*/{int gd = DETECT, gm = 0; /* 和gd = VGA,gm = VGAHI是同样效果*/registerbgidriver(EGAVGA_driver);/* 注册BGI驱动后可以不需要.BGI文件的支持运行*/initgraph(&gd, &gm, "");}clip_a_line(x1,y1,x2,y2,xw_min,xw_max,yw_min,yw_max) {int i,code1[4],code2[4],done,display;float m;int x11,x22,y11,y22,mark;done=0;display=0;while(done==0){x11=x1;x22=x2;y11=y1;y22=y2;encode(x1,y1,code1,xw_min,xw_max,yw_min,yw_max);encode(x2,y2,code2,xw_min,xw_max,yw_min,yw_max);if(accept(code1,code2)){done=1;display=1;break;}else if(reject(code1,code2)){done=1;break;}mark=swap_if_needed(code1,code2);if(mark==1){x1=x22;x2=x11;y1=y22;y2=y11;}if(x2==x1)m=-1;elsem=(float)(y2-y1)/(float)(x2-x1);if(code1[2]){x1+=(yw_min-y1)/m;y1=yw_min;}else if(code1[3]){x1-=(y1-yw_max)/m;y1=yw_max;}else if(code1[0]){y1-=(x1-xw_min)*m;x1=xw_min;}else if(code1[1]){y1+=(xw_max-x1)*m;x1=xw_max;}}if(display==1){line(x1,y1,x2,y2);printf("The result is:(x1,y1)=(%d,%d)\n",x1,y1);printf("The result is:(x2,y2)=(%d,%d)\n",x2,y2);}int encode(int x,int y,int code[],int xw_min,int xw_max,int yw_min,int yw_max) {int i;for(i=0;i<4;i++)code[i]=0;if(x<xw_min)code[0]=1;else if(x>xw_max)code[1]=1;if(y>yw_max)code[3]=1;else if(y<yw_min)code[2]=1;return(0);}int accept(int code1[],int code2[]){int i,flag;flag=1;for(i=0;i<4;i++){if((code1[i]==1) || (code2[i]==1)){flag=0;break;}}return(flag);int reject(int code1[],int code2[]){int i,flag;flag=0;for(i=0;i<4;i++){if((code1[i]==1) && (code2[i]==1)){ flag=1;break;}}return(flag);}int swap_if_needed(int code1[],int code2[]) {int i,flag1,flag2,tmp;flag1=1;for(i=0;i<4;i++)if(code1[i]==1){flag1=0;break;}flag2=1;for(i=0;i<4;i++)if(code2[i]==1){flag2=0;break;}if((flag1==0) && (flag2==0))return(0);if((flag1==1) && (flag2==0)){for(i=0;i<4;i++){tmp=code1[i];code1[i]=code2[i];code2[i]=tmp;}return(1);}return(0);}void main(){int x1,x2,y1,y2,xw_min,xw_max,yw_min,yw_max;initgr();printf("Please input the bottom boundary(xw_min,yw_min):\n"); scanf("%d,%d",&xw_min,&yw_min);printf("Please input the top boundary(xw_max,yw_max):\n"); scanf("%d,%d",&xw_max,&yw_max);setcolor(GREEN);line(xw_min,yw_min,xw_max,yw_min);line(xw_min,yw_max,xw_max,yw_max);line(xw_min,yw_min,xw_min,yw_max);line(xw_max,yw_min,xw_max,yw_max);getch();printf("Please input the position of the first point(x1,y1):\n");scanf("%d,%d",&x1,&y1);printf("Please input the position of the first point(x2,y2):\n");scanf("%d,%d",&x2,&y2);setcolor(YELLOW);line(x1,y1,x2,y2);getch();cleardevice();setcolor(GREEN);line(xw_min,yw_min,xw_max,yw_min);line(xw_min,yw_max,xw_max,yw_max);line(xw_min,yw_min,xw_min,yw_max);line(xw_max,yw_min,xw_max,yw_max);setcolor(RED);clip_a_line(x1,y1,x2,y2,xw_min,xw_max,yw_min,yw_max); outtextxy(50,50,"Cohen-SutherLand!");getch();closegraph();}。