实验五:直线段裁剪算法的实现
图形学实验报告直线段的裁剪算法
实验报告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。
计算机图形学Cohen-Sutherland直线裁剪算法实验
《计算机图形学实验》报告任课教师:***2016年春季学期实验:Cohen-Sutherland直线裁剪算法实验时间:2016年11月3日实验地点:信息学院2204实验目的:掌握Cohen-Sutherland直线裁剪算法程序代码:#include <stdlib.h>#include <math.h>#include <iostream>#include<stdio.h>#include <Windows.h>#include <GL/GL.h>#include <glut.h>int a,b,a1,b1,pp0,pq0,pp1,pq1;void setPixel(GLint x,GLint y){glBegin(GL_POINTS);glVertex2i(x,y);glEnd();}void init(void){glClearColor(1.0,1.0,1.0,0.0);glMatrixMode(GL_PROJECTION);gluOrtho2D(0.0,200.0,0.0,150.0);}void LineDDA(int x0,int y0,int xEnd,int yEnd){ int dx = xEnd - x0;int dy = yEnd - y0;int steps,k;float xIncrement,yIncrement,x = x0,y = y0;if(abs(dx)>abs(dy))steps = abs(dx);elsesteps = abs(dy);xIncrement = float(dx)/float(steps);yIncrement = float(dy)/float(steps);for (k = 0;k<steps;k++){x+=xIncrement;y+=yIncrement;setPixel(x,y);}}//裁剪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;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;int x0=0;int y0=0;int x1=0;int y1=0;while(!done){code1 = encode(p1,winMin,winMax);code2 = encode(p2,winMin,winMax);if(accept(code1,code2)){done = true;plotLine = true;}//简取else if(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);//计算kif(code1 &winLeftBitCode){p1.y+=(winMin.x-p1.x)*m;p1.x = winMax.x;}else if(code1 &winBottomBitCode){if(p2.x != p1.x)p1.x+=(winMin.y - p1.y)/m;p1.y=winMin.y;}else if(code1 &winTopBitCode){if(p2.x != p1.x)p1.x +=(winMax.y - p1.y)/m;p1.y = winMax.y;}}//else}//whileif(plotLine){LineDDA(round(p1.x),round(p1.y),round(p2.x),round(p2.y));}}void cutwindow(int xmin,int ymin,int xmax,int ymax){LineDDA(xmin,ymin,xmin,ymax);LineDDA(xmin,ymin,xmax,ymin);LineDDA(xmin,ymax,xmax,ymax);LineDDA(xmax,ymin,xmax,ymax);}void display(){//DDA演示printf("DDA演示\n");glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0,0.0,0.0);glBegin(GL_LINES);wcPt2D min;min.x = a;min.y = b;wcPt2D max;max.x=a1;max.y=b1;wcPt2D p1;p1.x=pp0;p1.y=pq0;wcPt2D p2;p2.x=pp1;p2.y=pq1;cutwindow(min.x,min.y,max.x,max.y);//绘制窗口lineClipCohSuth(min,max,p1,p2);glEnd();glFlush();}void main(int argc,char ** argv){glutInit(&argc,argv);glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);glutInitWindowPosition(500,300);glutInitWindowSize(400,300);glutCreateWindow("直线裁剪");init();printf("请输入裁剪窗口左下角坐标\n");scanf("%d %d",&a,&b);printf("请输入裁剪窗口右上角坐标\n");scanf("%d %d",&a1,&b1);printf("请输入要裁剪的直线第一点坐标\n");scanf("%d %d",&pp0,&pq0);printf("请输入要裁剪的直线第二点坐标\n");scanf("%d %d",&pp1,&pq1);glutDisplayFunc(display);glutMainLoop();}实验结果:。
简述利用sutherland的直线段裁剪方法
简述利用sutherland的直线段裁剪方法Sutherland的直线段裁剪方法是一种常见的计算机图形学中的算法。
该算法的目的是在二维平面上裁剪出线段,使其仅显示线段与裁剪边界的
交集。
该算法的过程如下:
1.由裁剪边界确定一个裁剪窗口,其中包括一个左、右、上和下四个
裁剪边界。
2.通过比较线段的端点与裁剪边界,确定线段是否跨过裁剪边界,并
同时保存线段于裁剪边界的相交点。
3.计算出线段与裁剪边界相交点的参数值(也称交点)和线段的斜率,再根据这些值确定线段与裁剪窗口的交集。
4.把裁剪后的线段输出或者显示出来。
通过这种方法,可以有效地减少不必要的计算并缩短执行时间,同时
也可以减少对图形性能的影响。
它被广泛地应用于计算机图形学中,并在
裁剪方面被广泛地采用。
计算机图形学基础实验指导书
计算机图形学基础实验指导书目录实验一直线的生成 ............................................................... -..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,否则结束操作。
cohen-sutherland 直线段裁剪算法 -回复
cohen-sutherland 直线段裁剪算法-回复cohensutherland 直线段裁剪算法引言:在计算机图形学中,直线段的裁剪是一个重要的问题。
为了在屏幕上正确地显示直线段,我们需要将其裁剪为可见部分。
Cohen-Sutherland直线段裁剪算法是一种经典的裁剪算法,它能够高效地在屏幕上裁剪直线段。
本文将详细介绍Cohen-Sutherland算法的原理和步骤,以及如何使用该算法进行直线段裁剪。
第一部分:算法原理Cohen-Sutherland算法基于直线段的端点的位置与裁剪窗口的位置关系来判断直线段是否需要被裁剪。
裁剪窗口通常是一个矩形,也就是屏幕上显示图像的区域。
算法将直线段分为9个区域,并为每个区域分配一个区域码。
区域码使用二进制数表示,其中每一位表示一个边界。
区域码的每一位可以为1或0,分别表示点在边界的外侧或内侧。
第二部分:算法步骤Cohen-Sutherland算法包含以下步骤:1. 计算直线段的起点和终点的区域码。
根据直线段在裁剪窗口内的位置关系,分别为起点和终点分配区域码。
例如,如果起点在裁剪窗口的左上方,则起点的区域码为1001。
2. 检查直线段的起点和终点的区域码。
如果两个区域码都为0,表示直线段完全在裁剪窗口内,无需进行裁剪,直接显示。
如果两个区域码的与运算结果不为0,则表示直线段在裁剪窗口外且与裁剪窗口无交集,可以完全丢弃不显示。
3. 如果直线段的起点和终点的区域码不都为0,表示直线段与裁剪窗口存在交集。
此时,需要根据裁剪窗口的边界与直线段的交点,重新计算直线段的起点和终点,并更新区域码。
4. 循环执行步骤2和步骤3,直到直线段完全在裁剪窗口内或与裁剪窗口无交集。
第三部分:算法应用Cohen-Sutherland算法可以用于任意直线段的裁剪,下面是算法的具体应用步骤:1. 定义裁剪窗口的边界。
裁剪窗口可以是屏幕上的任意矩形。
2. 定义需要裁剪的直线段的起点和终点坐标。
论述cohen-suthorland直线段裁剪算法的编码原理 -回复
论述cohen-suthorland直线段裁剪算法的编码原理-回复论述Cohen-Sutherland直线段裁剪算法的编码原理引言:在计算机图形学中,直线裁剪是指将给定的线段按照一个给定的裁剪窗口进行裁剪,以便只保留位于窗口内的部分。
Cohen-Sutherland算法是一种用于二维直线段裁剪的算法,其本质是通过直线段两个端点的编码情况进行判断与剪辑。
本文将围绕Cohen-Sutherland直线段裁剪算法的编码原理进行详细的阐述。
一、Cohen-Sutherland算法的基本思想Cohen-Sutherland算法的基本思想是将二维平面划分成九个区域,适用于矩形裁剪窗口。
每个区域用一个4位编码来表示,分别代表裁剪窗口的上、下、左、右四个边。
通过对直线段两个端点的编码情况进行判断,可以将直线段分割成裁剪窗口内的部分和裁剪窗口外的部分。
二、Cohen-Sutherland编码规则Cohen-Sutherland编码规则将裁剪窗口划分成9个区域,分别用以下4位二进制编码进行表示:位值上下左右:: :: :: :: ::编码0000 0001 0010 0100其中,上方区域的编码为0000,下方区域的编码为0001,左方区域的编码为0010,右方区域的编码为0100。
三、编码过程Cohen-Sutherland算法的编码过程主要包括以下几个步骤:1. 对直线段的两个端点进行编码。
首先,需要确定直线段两个端点的编码情况。
对于每个端点,分别判断其是否在裁剪窗口的上、下、左、右四个边上。
如果端点在边上,则对应的编码位置为1,否则为0。
2. 判断直线段与裁剪窗口的位置关系。
根据直线段两个端点的编码情况,可以判断直线段与裁剪窗口的位置关系。
如果两个端点的编码都为0000,说明直线段完全在裁剪窗口内部,无需裁剪;如果两个端点的编码与运算的结果不为0000,说明直线段完全在裁剪窗口外部,直接裁剪掉。
如果以上两种情况都不满足,则需要进行进一步的处理。
计算机图形学实验报告实验2裁剪算法实验
一、实验目的:直线段的裁剪:编码裁剪算法,中点分割裁剪算法。
二、实验内容://BasicGraph.cpp//请将下列裁剪程序补充完整,并用注释说明是何种裁剪算法void Encode (int x,int y,int *code,int XL,int XR,int YB,int YT) {//请将此程序补充完整int c=0;if(x<XL) c=c|LEFT;else if(x>XR) c=c|RIGHT;if(y<YB) c=c|BOTTOM;else if(y>YT) c=c|TOP;(*code)=c;}//编码裁剪算法:void C_S_Line(POINT &p1,POINT &p2,int XL,int XR,int YB,int YT) {//请将此程序补充完整int x1,x2,y1,y2,x,y,code1,code2,code;x1=p1.x; x2=p2.x; y1=p1.y; y2=p2.y;Encode(x1,y1,&code1,XL,XR,YB,YT);Encode(x2,y2,&code2,XL,XR,YB,YT);while(code1!=0||code2!=0){if((code1&code2)!=0) return;code=code1;if(code1==0) code=code2;if((LEFT&code)!=0){x=XL;y=y1+(y2-y1)*(XL-x1)/(x2-x1);}else if((RIGHT&code)!=0){x=XR;y=y1+(y2-y1)*(XR-x1)/(x2-x1);}if((BOTTOM&code)!=0){y=YB;x=x1+(x2-x1)*(YB-y1)/(y2-y1);}else if((TOP&code)!=0){y=YT;x=x1+(x2-x1)*(YT-y1)/(y2-y1);}if(code==code1){x1=x;y1=y;Encode(x,y,&code1,XL,XR,YB,YT);}else{x2=x;y2=y;Encode(x,y,&code2,XL,XR,YB,YT);}}p1.x=x1;p1.y=y1;p2.x=x2;p2.y=y2;}int IsInArea(POINT point,int XL,int XR,int YB,int YT){//请将此程序补充完整if(point.x>=XL && point.x<=XR && point.y>YB && point.y<YT) return 1;else return 0;}int NotIntersect(POINT begin,POINT end,int XL,int XR,int YB,int YT) {//请将此程序补充完整int maxx,maxy,minx,miny;maxx=(begin.x>end.x)?begin.x:end.x;minx=(begin.x<end.x)?begin.x:end.x;maxy=(begin.y>end.y)?begin.y:end.y;miny=(begin.y<end.y)?begin.y:end.y;if(maxx<XL|| minx>XR||maxy<YB||miny>YT) return 1;else return 0;}//中点裁剪算法:POINT ClipMid(POINT begin,POINT end,int XL,int XR,int YB,int YT){//请将此程序补充完整POINT mid,temp;if(IsInArea(begin,XL,XR,YB,YT)) temp=begin;else if(NotIntersect(begin,end,XL,XR,YB,YT)) temp=begin;else{mid.x=(begin.x+end.x)/2;mid.y=(begin.y+end.y)/2;if(abs(mid.x-end.x)<=1&& abs(mid.y-end.y)<=1) temp=mid;else{if(NotIntersect(begin,mid,XL,XR,YB,YT))temp=ClipMid(mid,end,XL,XR,YB,YT);elsetemp=ClipMid(begin,mid,XL,XR,YB,YT);}}return temp;}//Liang-Barsky直线裁剪算法:void ClipParameter(POINT &p1,POINT &p2,int XL,int XR,int YB,int YT) {float u1=0.0,u2=1.0;float dx=p2.x-p1.x,dy=p2.y-p1.y;if(clipTest(-dx,p1.x-XL,&u1,&u2))if(clipTest(dx,XR-p1.x,&u1,&u2))if(clipTest(-dy,p1.y-YB,&u1,&u2))if(clipTest(dy,YT-p1.y,&u1,&u2)){if(u2<1.0){p2.x=p1.x+u2*dx;p2.y=p1.y+u2*dy;}if(u1>0.0){p1.x=p1.x+u1*dx;p1.y=p1.y+u1*dy;}}}int clipTest(float p,float q,float *u1,float *u2){float r;int remainFlag=1;if(p<0.0){r=q/p;if(r>*u2) remainFlag=0;else if(r>*u1) *u1=r;}else if(p>0.0){r=q/p;if(r<*u1) remainFlag=0;else if(r<*u2) *u2=r;}else //*p=0if(q<0.0) remainFlag=0;return remainFlag;}//逐边裁剪算法://typedef struct tRes { int yes,isIn; POINT pout;} Res;Res TestIntersect(int edge,int type,POINT p1,POINT p2){//判断p2是否在所裁剪的窗边edge的内侧,是否与p1点分别在窗边edge的异侧float dx,dy,m;Res res;int isIn=0,yes=0;POINT pout;dy=p2.y-p1.y;dx=p2.x-p1.x;m=dy/dx;switch(type){case 1: /*right*/if(p2.x<=edge){isIn=1;if(p1.x>edge)yes=1;}else if(p1.x<=edge)yes=1;break;case 2: /*bottom*/if(p2.y>=edge){isIn=1;if(p1.y<edge)yes=1;}else if(p1.y>=edge)yes=1;break;case 3: /*left*/if(p2.x>=edge){isIn=1;if(p1.x<edge)yes=1;}else if(p1.x>=edge)yes=1;break;case 4: /*top*/if(p2.y<=edge){isIn=1;if(p1.y>edge)yes=1;}else if(p1.y<=edge)yes=1;default: break;}if(yes){if((type==1) || (type==3)){ pout.x=edge;pout.y=p1.y+m*(pout.x-p1.x);}if((type==2) || (type==4)){ pout.y=edge;pout.x=p1.x+(pout.y-p1.y)/m;}}res.isIn=isIn;res.yes=yes;res.pout=pout;return res;}int clipSingleEdge(int edge,int type,int nin,POINT pin[50],POINT pout[50])/*对多边形pin与窗边edge进行裁剪,返回裁剪后的多边形pout及点数*/ {int i,k=0;POINT p;Res res;p.x=pin[nin-1].x;p.y=pin[nin-1].y;for(i=0;i<nin;i++){res=TestIntersect(edge,type,p,pin[i]);if(res.yes){ pout[k].x=res.pout.x;pout[k].y=res.pout.y;k++;} if(res.isIn){ pout[k].x=pin[i].x;pout[k].y=pin[i].y;k++;}p.x=pin[i].x;p.y=pin[i].y;}return k;}void ClipEdgePolygon(POINT ps[50],int &n,int XL,int XR,int YB,int YT) { /*对多边形ps进行逐边裁剪*/int n1=0,n2=0;POINT pt[50];n1=clipSingleEdge(XR,1,n,ps,pt);n2=clipSingleEdge(YB,2,n1,pt,ps);n1=clipSingleEdge(XL,3,n2,ps,pt);n2=clipSingleEdge(YT,4,n1,pt,ps);n=n2;}//多边形编码裁剪算法:void ClipEncodePolygon(POINT ps[50],int &n,int XL,int XR,int YB,int YT) {POINT tp[50];int k=0,m;int code1,code2,code;int x,y;for(int i=0;i<n-1;i++){Encode(ps[i].x,ps[i].y,&code1,XL,XR,YB,YT);Encode(ps[i+1].x,ps[i+1].y,&code2,XL,XR,YB,YT);code=code1;m=i;for(int j=0;j<2;j++){if((code1 & code2)!=0) //线段两端都在窗口外的同一侧{switch(code){case 1:x=XL;y=ps[m].y;break;case 2:x=XR;y=ps[m].y;break;case 4:x=ps[m].x;y=YB;break;case 5:x=XL;y=YB;break;case 6:x=XR;y=YB;break;case 8:x=ps[m].x;y=YT;break;case 9:x=XL;y=YT;break;case 10:x=XR;y=YT;break;}tp[k].x=x;tp[k].y=y;k++;}else if((code1 & code2)==0) //线段两端不在窗口的同一侧{if(code==0){tp[k]=ps[m];k++;}else if ((LEFT & code) !=0) //线段与左边界相交 {x=XL;y=ps[i].y+(ps[i+1].y-ps[i].y)*(XL-ps[i].x)/(ps[i+1].x-ps[i].x);if(y>YB && y<YT){tp[k].x=x;tp[k].y=y;k++;}}else if((TOP & code)!=0) //线段与上边界相交{y=YT;x=ps[i].x+(ps[i+1].x-ps[i].x)*(YT-ps[i].y)/(ps[i+1].y-ps[i].y);if(x>XL && x<XR){tp[k].x=x;tp[k].y=y;k++;}}else if((RIGHT & code)!=0) //线段与右边界相交 {x=XR;y=ps[i].y+(ps[i+1].y-ps[i].y)*(XR-ps[i].x)/(ps[i+1].x-ps[i].x);if(y>YB && y<YT){tp[k].x=x;tp[k].y=y;k++;}}else if((BOTTOM & code) != 0) //线段与下边界相交 {y=YB;x=ps[i].x+(ps[i+1].x-ps[i].x)*(YB-ps[i].y)/(ps[i+1].y-ps[i].y);if(x>XL && x<XR){tp[k].x=x;tp[k].y=y;k++;}}}code=code2;m++;}//for(j)}//for(i)for(i=0;i<k;i++)ps[i]=tp[i];n=k;}//函数的调用,裁剪窗口的调整//DrawView.cpp文件//裁剪窗口的调整CDrawView::CDrawView(){/************请在此函数中将裁剪窗口大小调整为长度100单位像素,宽度50单位像素的矩形********/// TODO: add construction code here//m_pWidth=1;m_pStyle=PEN_STYLE_SOLID;m_pColor=RGB(0,0,0);m_FFlag=0;m_FColor=RGB(0,0,0);m_HFlag=0;CurrentDraw=DRAW_VCLINE;m_Num=0;m_Drag=0;m_HCursor=AfxGetApp()->LoadStandardCursor(IDC_CROSS);//DrawType=0;ClipFlag=0;ClipType=-1;XL=200;XR=300;YB=150;YT=200;//XL=200;XR=500;YB=150;YT=400;ClipWindowColor=RGB(192,192,50);}void CDrawView::OnDraw(CDC* pDC){CDrawDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);// TODO: add draw code for native data hereif(ClipFlag){CPen NewPen,*pOldPen;NewPen.CreatePen(PS_DASH,1,ClipWindowColor);pOldPen=pDC->SelectObject(&NewPen);pDC->MoveTo(XL,YB);pDC->LineTo(XR,YB);pDC->LineTo(XR,YT);pDC->LineTo(XL,YT);pDC->LineTo(XL,YB);}int index;index=pDoc->GetShapeNumber();for(int i=0;i<index;i++)pDoc->GetShape(i)->Drawing(pDC);}void CDrawView::OnInitialUpdate(){CSize sizeTotal;sizeTotal.cx = 640; sizeTotal.cy = 480;SetScrollSizes(MM_TEXT, sizeTotal);// TODO: Add your specialized code here and/or call the base class }void CDrawView::OnLButtonDown(UINT nFlags, CPoint point){// TODO: Add your message handler code here and/or call defaultCClientDC dc(this);OnPrepareDC(&dc);dc.DPtoLP(&point);m_pPrev=point;m_pOrigin=point; //点击鼠标左键作为拖动绘图的第一点m_Drag=1;SetCapture();RECT rect;GetClientRect(&rect);ClientToScreen(&rect);ClipCursor(&rect);CScrollView::OnLButtonDown(nFlags, point);}//函数调用处void CDrawView::OnLButtonUp(UINT nFlags, CPoint point){// TODO: Add your message handler code here and/or call defaultif(m_Drag){m_Drag=0;ReleaseCapture();ClipCursor(NULL);CDrawDoc *pDoc=GetDocument();CShape *pShape;POINT p1,p2;if(CurrentDraw==DRAW_VCLINE || CurrentDraw==DRAW_DDALINE ||CurrentDraw==DRAW_MIDLINE || CurrentDraw==DRAW_BSHLINE){if(ClipFlag){switch(ClipType){/****************编码裁剪函数调用处*************/case CLIP_ENCODE:C_S_Line(m_pOrigin,m_pPrev,XL,XR,YB,YT); break; /****************中点分割裁剪函数调用处************/case CLIP_MIDPOINT: ClipMid(m_pPrev,m_pOrigin,XL,XR,YB,YT);p1=ClipMid(m_pPrev,m_pOrigin,XL,XR,YB,YT);p2=ClipMid(m_pOrigin,m_pPrev,XL,XR,YB,YT);m_pOrigin=p1;m_pPrev=p2;break;case CLIP_PARAMETER:ClipParameter(m_pOrigin,m_pPrev,XL,XR,YB,YT);break;}}pShape=newCLine(m_pOrigin,m_pPrev,m_pWidth,m_pStyle,m_pColor,DrawType);pDoc->AddShape(pShape);}if(CurrentDraw==DRAW_RECTANGLE){if(ClipType==CLIP_WINDOW){XL=m_pOrigin.x;XR=m_pPrev.x;YB=m_pOrigin.y;YT=m_pPrev.y;}else{pShape=newCRectangle(m_pOrigin,m_pPrev,m_pWidth,m_pStyle,m_pColor,m_FFlag,m_FColor,m_HFlag,m_Hatch);pDoc->AddShape(pShape);}}if( CurrentDraw==DRAW_VCCIRCLE || CurrentDraw==DRAW_MIDCIRCLE || CurrentDraw==DRAW_BSHCIRCLE){pShape=newCCircle(m_pOrigin,m_pPrev,m_pWidth,m_pStyle,m_pColor,m_FFlag,m_FColor,m_HFlag,m_Hatch,DrawType);pDoc->AddShape(pShape);}if(CurrentDraw==DRAW_VCELLIPSE || CurrentDraw==DRAW_MIDELLIPSE) {pShape=newCEllipse(m_pOrigin,m_pPrev,m_pWidth,m_pStyle,m_pColor,m_FFlag,m_FColor,m_HFlag,m_Hatch,DrawType);pDoc->AddShape(pShape);}pDoc->UpdateAllViews(NULL);}CScrollView::OnLButtonUp(nFlags, point);}三实验结果:四、实验总结通过这次试验使我了解到如何运用计算机程序对窗口进行剪裁,了解到编码剪裁算法直观方便,速度较快,中点分割剪裁算法不用进行乘除运算,剪裁效率高,Liang-Barsky直线裁剪算法更快。
裁剪算法设计实验报告(3篇)
第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)定义窗口边界首先,定义窗口边界,包括左边界、右边界、上边界和下边界。
直线段剪裁实验报告
直线段剪裁实验报告摘要:本实验旨在通过剪裁算法对直线段进行处理,并观察其效果。
我们使用了一种常见的直线段剪裁算法——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-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(即都在可视范围内),则可以直接输出该线段;否则,执行下一步。
计算机图形学5.5裁剪算法
如何判定线段应该与窗口的哪条边求交呢?
编码中对应位为1的窗口边。
计算线段P1(x1,y1)P2(x2,y2)与窗口边界的交点 Code代表线段某个端点的编码。 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);}
P4 (1010)
上下右左 □□□□
P1 (1001)
Y=YT
P3: 0110 P4:& 1010
0010
X=XL
P1: 1001 P2:& 0010
0000
P2 (0010)
X=XR
Y=YB P3 (0110)
对于三维裁剪,需要6位编码。
一旦给定所有的线段端点的区域码,就可以快速 判断哪条直线完全在剪取窗口内,哪条直线完全在 窗口外。所以得到一个规律:
4.求交:假定直线的端点坐标为(x1, y1)和(x2, y2) (1)左、右边界交点的计算:y=y1+k(x-x1); (2)上、下边界交点的计算:x=x1+(y-y1)/k。
Cohen-Sutherland端点编码算法
优点:简单,易于实现。 特点:用编码方法可快速判断线段的完全可见和 显然不可见。
cohensutherland裁剪算法实验报告
cohensutherland裁剪算法实验报告Cohen-Sutherland裁剪算法是计算机图形学中一种常用的线段裁剪算法,它能够快速地确定一个线段是否在一个给定的窗口内部,以及剪切后的线段如何变化。
该算法的基本思想是将给定的窗口划分为九个区域,其中一种情况是窗口内没有线段,另一种情况是线段完全位于窗口内部,其他情况下需要进行裁剪处理。
具体来说,算法根据线段的起点和终点的位置判断其所处区域,并使用二进制编码进行表示。
Cohen-Sutherland裁剪算法使用四位标记,分别表示线段位于左、右、下、上四个区域。
二进制编码规则如下:左边界:0001右边界:0010下边界:0100上边界:1000当线段的二进制编码全为0时,表示线段完全位于窗口内部;当线段的二进制编码与给定窗口的二进制编码进行与运算时,结果全为0时,表示线段与窗口无交集;其他情况下则需要进行裁剪。
裁剪的具体过程如下:1. 首先计算线段起点和终点的编码,并确定是否需要裁剪;2. 若线段的编码全为0,则直接绘制该线段;3. 若线段与窗口的编码进行与运算结果全为0,则表明线段与窗口无交集,不进行绘制;4. 若线段需要进行裁剪,则计算线段与窗口的交点,并更新线段的起点和终点;5. 重复步骤2-4,直到线段裁剪完成。
Cohen-Sutherland裁剪算法的优点在于能够快速地判断线段是否与窗口有交集,并进行有效的裁剪处理。
它只需要对线段起点和终点进行编码,并进行一系列的与运算和位运算即可完成整个裁剪过程。
此外,该算法也适用于三维空间中的线段裁剪。
然而,Cohen-Sutherland裁剪算法也存在一些局限性。
当线段与窗口有交集时,该算法只能找到线段与窗口的交点,而无法找到线段与窗口的所有交点。
此外,在处理多边形的裁剪时,该算法效果不佳。
总结起来,Cohen-Sutherland裁剪算法是一种简单且高效的线段裁剪算法,适用于二维和三维空间中的线段裁剪。
计算机图形学实验五直线段裁剪
计算机图形学实验报告黔南民族师范学院信息与计算科学撰写人姓名: __ 撰写时间: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();}成绩评定:指导教师:。
一编程实现直线段的裁剪算法
实验一编程实现直线段的裁剪算法课程名称:图形学任课老师谢伙生老师年级03级班级计算机(6)班姓名沈睿汀学号S030300833一、实验要求1、裁剪算法选用Cohen-Sutherland算法;2、界面设计友好、直观。
二、实验环境说明(1)本系统基于JA V A编程环境,使用JBuilder X作为相关的开发工具,因此系统的运行与其它用VC++开发的系统略有不同。
(2)在WINDOWS-XP下运行本程序的时候,请先安装j2re-1_4_2_04-windows-i586-p.exe,然后,才能正常运行,windows环境下双击030300833Cutline.exe。
三、算法与数据结构(程序设计)核心算法Cohen-Sutherland的编写过程如下(在Sutherland.java文件中可以看到具体代码):(1)新建一个类Sutherland,并在类在声明一个构造函数Sutherland(int wyt, int wyb, int wxl, int wxr) ,传递矩形的四个边界参数,并对类中的共有属性进行初始化。
(2)声明一个端点编码方法private void codingPoint(int x, int y, int[] p),根据书上的编码规则对端点进行编码。
(3)声明一个方法public void setPoint(int x1, int y1, int x2, int y2)来设置直线段的两端点坐标。
(4)声明两个方法private int OR(int[] op1, int[] op2)和private int AND(int[] op1, int[] op2)来分别实现编码后的端点的相或和相与。
并编写一个方法isInWindow(int[] op)来判断点op是否在窗口中。
(5)编写两个方法private int caculateY(int x1, int y1, int x2, int y2, int x) 和private int caculateX(int x1, int y1, int x2, int y2, int y)来分别求出未知的端点坐标,接着利用这两个方法又编写一个方法private void caculateCrossPoint()来对直线段和相应的窗口边界进行求交处理。
图形学实验报告--线段裁剪
计算机科学与技术学院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,添加消息处理函数,建立类向导,最后添加程序代码。
计算机图形学-实验五 直线和多边形的裁剪
大学实验报告学院:计算机科学与信息学院专业:软件工程班级: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 x = XL;y = y1 + (y2 - y1) * (XL - x1) / (x2 - x1);// 求直线与矩形窗口的左边界的交点} else if ((RIGHT & code) != 0) {// 直线的端点与矩形窗口的右边编码相与!=0x = XR;y = y1 + (y2 - y1) * (XR - x1) / (x2 - x1);// 求直线与矩形窗口的右边界的交点} else if ((BOTTOM & code) != 0) {// 直线的端点与矩形窗口的下边编码相与!=0y = YB;x = x1 + (x2 - x1) * (YB - y1) / (y2 - y1);// 求直线与矩形窗口的下边界的交点} else if ((TOP & code) != 0) {// 直线的端点与矩形窗口的上边编码相与!=0y = YT;x = x1 + (x2 - x1) * (YT - y1) / (y2 - y1);// 直线的端点与矩形窗口的上// 边编码相与!=0}if (code == code1) {x1 = x;y1 = y;code1 = encode(x, y);} else {x2 = x;y2 = y;code2 = encode(x, y);}}g.drawLine((int) (x1 + 0.5), (int) (y1 + 0.5), (int) (x2 + 0.5),(int) (y2 + 0.5));}二、多边形裁剪的核心代码为:通过点集画直线或者多边形:private void draw() {//通过点集画直线或者多边形for (int i = 1; i < points.size(); i++) {Point p1 = new Point();p1 = points.get(i);int x1 = (int) p1.getX();int y1 = (int) p1.getY();Point p2 = new Point();p2 = points.get(i - 1);int x2 = (int) p2.getX();int y2 = (int) p2.getY();g.drawLine(x1, y1, x2, 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;}} else if (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;}判断点是否在裁剪边的可见侧:private boolean inside(Point point, Point[] edge) {//判断点是否在裁剪边的可见侧// 裁剪边为窗口下边if ((edge[0].y == edge[1].y) && (edge[0].x < edge[1].x)) {if (point.y >= edge[0].y) {return true;}}// 裁剪边为窗口上边if ((edge[0].y == edge[1].y) && (edge[0].x > edge[1].x)) {if (point.y <= edge[0].y) {return true;}}// 裁剪边为窗口右边if ((edge[0].x == edge[1].x) && (edge[0].y < edge[1].y)) {if (point.x <= edge[0].x) {return true;}}// 裁剪边为窗口左边if ((edge[0].x == edge[1].x) && (edge[0].y > edge[1].y)) {if (point.x >= edge[0].x) {return true;}}return false;}直线段与窗口边界求交: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.x = s.x + (edge[0].y - s.y) * (p.x - s.x) / (p.y - s.y);} else if (edge[0].x == edge[1].x) {// 垂直裁剪边t.x = edge[0].x;t.y = s.y + (edge[0].x - s.x) * (p.y - s.y) / (p.x - s.x);}return t;}鼠标的监听类(部类):class MouseMonitor extends MouseAdapter {//通过鼠标的单击获取点,并画出直线或者多边形public void mouseClicked(MouseEvent e) {points.add(e.getPoint());if (points.size() > 1) {draw();}}}键盘的监听类(部类):class KeyMonitor extends KeyAdapter {// 键盘控制public void 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(XL, YB, XR - XL, YT - YB);//存放裁剪窗口的边top = new Point[2];// 存放裁剪窗口的上边top[0] = new Point(XL, YB);top[1] = new Point(XR, YB);right = new Point[2];//存放裁剪窗口的右边right[0] = new Point(XR, YB);right[1] = new Point(XR, YT);bottom = new Point[2];//存放裁剪窗口的下边bottom[0] = new Point(XR, YT);bottom[1] = new Point(XL, YT);left = new Point[2];//存放裁剪窗口的左边left[0] = new Point(XL, YT);left[1] = new Point(XL, YB);break;case KeyEvent.VK_A://对直线段进行裁剪g.setColor(Color.GREEN);Point p1 = points.get(0);Point p2 = points.get(1);lineCut(p1.getX(), p1.getY(), p2.getX(), 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);//得到多边形与裁剪窗口左边的交点第二种情况:线段在裁剪窗口的部,线段完全可见。
直线段裁剪直接求交算法
直线段裁剪直接求交算法
直线段裁剪直接求交算法是一种用于判断直线段与矩形窗口相交的算法。
该算法通过比较直线段上的点与窗口的边界来确定直线段是否与窗口相交。
算法步骤如下:
1. 初始化变量:
`left`、`right`、`top`、`bottom` 分别表示窗口的左、右、上、下边界坐标。
`x1`、`y1`、`x2`、`y2` 分别表示直线段的起点和终点的x 和y 坐标。
`px`、`py` 表示直线段上的任意一点的坐标。
2. 如果直线段的起点或终点在窗口边界上,则认为直线段与窗口相交。
3. 如果直线段完全位于窗口内部,则认为直线段与窗口相交。
4. 如果直线段完全位于窗口外部,则认为直线段与窗口不相交。
5. 如果直线段与窗口的边界相交,则计算交点坐标,并判断交点是否位于直线段上。
如果交点位于直线段上,则认为直线段与窗口相交。
6. 返回结果:如果直线段与窗口相交,则返回 True;否则返回 False。
以下是该算法的 Python 代码实现:
例如,对于直线段 `(1, 1, 3, 3)` 和窗口 `(0, 0, 4, 4)`,该算法将返回 True,因为直线段与窗口相交。
对于直线段 `(2, 2, 1, 1)` 和窗口 `(0, 0, 4, 4)`,该算法将返回 False,因为直线段与窗口不相交。
直线裁剪算法研究
直线裁剪算法研究直线裁剪算法是计算机图形学中的一种技术,用于将给定的直线段裁剪为可见部分。
在计算机中,直线由起点和终点坐标表示。
直线裁剪算法主要用于将不在可见区域内的线段进行剪裁,从而提高绘制效率,减少不必要的计算。
在直线裁剪算法中,常用的有Cohen-Sutherland算法、Liang-Barsky算法、中点画线算法和Bresenham算法等。
Cohen-Sutherland算法是最早提出的直线裁剪算法之一、该算法将可视区域分为9个区域,并用二进制编码表示。
对于给定的直线段,算法通过判断线段的起点和终点在可视区域内部或外部的区域位置,进而判断直线是否与可视区域相交。
如果线段完全在可视区域外部,则直接舍弃;如果线段完全在可视区域内部,则保留;如果线段与可视区域有交点,则计算交点,然后根据裁剪后的交点来得到裁剪后的线段。
Liang-Barsky算法是对Cohen-Sutherland算法的改进。
该算法通过参数化线段,并根据线段与裁剪窗口的交点,分别对起点和终点进行参数的调整。
通过对参数的调整,可以得到裁剪后的线段。
Liang-Barsky算法相比于Cohen-Sutherland算法在性能上有所提升。
中点画线算法是一种基于点的线段绘制算法,也可用于直线裁剪。
该算法在绘制线段过程中,每一步都将当前的点与直线的斜率进行比较,根据斜率的大小来决定是向上绘制还是向右上绘制。
根据直线的方向和可视区域的位置,可以在绘制的过程中进行一些判断,从而实现直线裁剪。
Bresenham算法是一种广泛应用于计算机图形学中的线段绘制算法,也可用于直线裁剪。
该算法使用整数运算来计算像素的位置和选择绘制的像素颜色,从而实现高效的线段绘制。
同样地,通过在绘制的过程中加入一些判断,可以实现直线的裁剪。
总结来说,直线裁剪算法是计算机图形学中的重要技术,用于将给定的直线段裁剪为可见部分。
不同的算法有其优缺点,根据具体的需求选择合适的算法可以提高绘制效率,减少不必要的计算。
直线的裁剪
直线的裁剪姓名:李苗苗学号:2009154124 系别:计算机系指导老师:张俊花二○一二年六月直线的裁剪李苗苗摘要:计算机图形学的一个主要目的就是利用计算机产生另人赏心悦目的真实感图形,在生活中得到广泛的运用。
利用Cohen-Sutherland算法对直线进行裁剪并且理解和掌握Cohen-Sutherland裁剪算法。
关键字:Cohen_Sutherland算法、直线裁剪1.提出问题计算机图形学的一个主要目的就是利用计算机产生另人赏心悦目的真实感图形,在生活中得到广泛的运用。
而图形的变换与裁剪是图形学中重要的一部分,那么怎样对一条直线进行裁剪呢?这里利用Cohen-Sutherland算法。
2.目的1.利用Cohen-Sutherland算法对直线进行裁剪并且理解和掌握Cohen-Sutherland裁剪算法。
2.掌握用Cohen_Sutherland裁剪算法裁减多边形的基本过程。
3.内容用Cohen_Sutherland算法编程实现用矩形窗口对直线的裁剪。
4.原理分析Cohen-Sutherland直线剪裁算法以区域编码为基础,将窗口及其周围的,8个方向以4 bit的二进制数进行编码。
下图所示的编码方法将窗口及其邻域分为5个区域:⑴内域:区域(0000)。
⑵上域:区域(1001, 1000, 1010)。
⑶下域:区域(0101, 0100, 0110)。
⑷左域:区域(1001, 0001, 0101)。
⑸右域:区域(1010, 0010, 0110)。
当线段的两个端点的编码的逻辑“与”非零时,线段为显然不可见的,对某线段的两个端点的区号进行位与运算,可知这两个端点是否同在视区的上、下、左、右;该算法的思想是:对于每条线段P1P2分为三种情况处理。
(1)若P1P2完全在窗口内,则显示该线段P1P2简称“取”之。
(2)若P1P2明显在窗口外,则丢弃该线段,简称“弃”之。
(3)若线段既不满足“取”的条件,也不满足“弃”的条件,则在交点处把线段分为两段。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
if(s1==0&&s2==1) line(x1,y1,x21,y21); //说明第二个端点不在窗口内,第一个在,直线与窗口有一个交点
}
}
void main()
{
#include "graphics.h"
#include "conio.h"
#include "math.h"
#include "stdio.h"
intw1=90, w2=270, w3=40, w4=160; //定义窗口的几个关键点坐标
voidclipline(char *a,int&x,int&y,intx1,int y1,int x2,int y2) //求出与区域中各个方向边的交点
outtextxy(150,300," 计算1213班 201221121027 邹建华");
getch();
closegraph(); //关闭图形系统
}
else if((a[0]-48)*(b[0]-48)+(a[1]-48)*(b[1]-48)+(a[2]-48)*(b[2]-48)+(a[3]-48)*(b[3]-48)==0)
{ //两端点四位编码的逻辑乘为0
if(!(a[0]=='0'&&a[1]=='0'&&a[2]=='0'&&a[3]=='0')) //第一个端点不在窗口内,求与窗口交点
if(yi<w3) *(a+2)='1'; //下
if(yi>w4) *(a+3)='1'; //上
return;
}
voidclipdraw(intx1,inty1, char *a,intx2,inty2, char *b)
{
intx11,y11,x21,y21;
ints1=0,s2=0;
code(x1,y1,a); //得到直线第一个端点的编码
{
intxt1=0,yt1=0,xt2=0,yt2=0,xt3=0,yt3=0,xt4=0,yt4=0;
if(*a=='1')
{
yt1=y1+(y2-y1)*(w1-x1)/(x2-x1);
xt1=w1;
} //求左交点
if(*(a+1)=='1')
{
yt2=y1+(y2-y1)*(w2-x1)/(x2-x1);
if(xt4<=270 && xt4>=90 && yt4<=160 && yt4>=40) { x=xt4; y=yt4;}
}
void code(intxi,intyi, char *a) //四位编码的实现
{
if(xi<w1) *a='1'; //左
if(xi>w2) *(a+1)='1'; //右
intx1=50,y1=20,x2=250,y2=200;
char a[4]={'0','0','0','0'};
char b[4]={'0','0','0','0'}; //分别初始化两个端点的编码数组
intdriver=VGA, mode=VGAHI;
initgraph(&driver,&mode,"");
cleardevice(); //清除屏幕
setcolor(GREEN);
rectangle(w1,w3,w2,w4); //再次画出窗口
setcolor(RED);
clipdraw(x1,y1,a,x2,y2,b); //画出保留在窗口内的直线
setcolor(WHITE);
settextstyle(16, 0, _T("宋体"));
xt2=w2;
} //求右交点
if(*(a+2)=='1')
{
xt3=x1+(x2-x1)*(w3-y1)/(y2-y1);
yt3=w3;
} //求下交点
if(*(a+3)=='1')
{
xt4=x1+(x2-x1)*(w4-y1)/(y2-y1);
yt4=w4;
} //求上交点
//有可能会求出两个交点,例如左交点和上交点,必然有一个是超出窗口范围的
2、实现直线的编码裁剪算法,在屏幕上用一个封闭矩形裁剪任意一条直线。
3、编写上述算法程序,在工作区域当中运行并显示算法效果;
4、将直线段裁剪模块添加到设计的图形实验系统当中;
5、完成代码编写、调试;
6、尝试实现梁友栋裁剪算法;
三、实验过程及结果分析
1、直线的编码裁剪算法流程图及显示结果:
Cohen-Surtherland算法
实验五:直线段裁剪算法的实现
班级计算1213学号201221121027姓名邹建华
指导教师王丰日期2014.12.15成绩
一、实验目的和要求:
1、了解二维图形裁剪的原理(点的裁剪、直线的裁剪、多边形的裁剪);
2、实现直线段的裁剪算法;
二、实验内容
1、理解直线裁剪的原理(Cohen-Surtherland算法、梁友栋算法)
{
clipline(a,x11,y11,x1,y1,x2,y2);
s1=1;
}
if(!(b[0]=='0'&&b[1]=='0'&&b[2]=='0'&&b[3]=='0')) //第二个端点不在窗口内,求与窗口交点
{
clipline(b,x21,y21,x1,y1,x2,y2);
s2=1;
}
if(s1==1&&s2==1) line(x11,y11,x21,y21); //说明两个端点均不在窗口内,直线与窗口有两个交点
//必须将其排除
if(xt1<=270 && xt1>=90 && yt1<=160 && yt1>=40) { x=xt1; y=yt1;}
if(xt2<=270 && xt2>=90 && yt2<=160 && yt2>=40) { x=xt2; y=yt2;}
if(xt3<=270 && xt3>=90 && yt3<=160 && yt3>=40) { x=xt3; y=yt3;}
code(x2,y2,b); //得到直线第二个端点的编码
if(*a=='0' && *b=='0' && *(a+1)=='0' && *(b+1)=='0' && *(a+2)=='0' && *(b+2)=='0' && *(a+3)=='0' && *(b+3)=='0')
line(x1,y1,x2,y2); //若两个端点的编码全为0,则直线完全可见
setcolor(GREEN);
rectangle(w1,w3,w2,w4); //画出窗口
setcolor(YELLOW);
line(x1,y1,x2,y2); //画出裁剪之前的直线
setcolor(WHITE);
settextstyle(16, 0, _T("宋体");
outtextxy(150,300,"计算1213班 201221121027 邹建华");