改进的cohen-sutherland线段裁剪算法

合集下载

描述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裁剪算法就完成了。

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

计算机图形学Cohen-Sutherland直线裁剪算法实验

计算机图形学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();}实验结果:。

计算机图形学实验Cohen-Sutherland算法

计算机图形学实验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=C4C3C2C1。

为了保证窗口内直线端点的编码为零,编码规则定义如下:第一位:若端点位于窗口之左侧,即x<w xl ,则C 1=1,否则C 1=0。

第二位:若端点位于窗口之右侧,即x>w xr ,则C 2=1,否则C 2=0。

第三位:若端点位于窗口之下侧,即y<w yb ,则C 3=1,否则C 3=0。

第四位:若端点位于窗口之上侧,即y>w yt ,则C 4=1,否则C 4=0。

裁剪步骤如下:(1)若直线的两个端点的区域编码都为零,即RC 1|RC 2=0,说明直线两端点都在窗口内,应“简取”之。

(2)若直线的两个端点的区域编码都不为零,即RC 1&RC 2≠0,即直线位于窗外的同一侧,说明直线的两个端点都在窗口外,应“简弃”之。

(3)若直线既不满足“简取”也不满足“简弃”的条件,直线必然与窗口或窗口边界的延长线相交,需要计算直线与窗口边界的交点。

交点将直线分为两段,其中一段完全位于窗口外,可“简弃”之。

对另一段重复进行上述处理,直至该直线段完全被舍弃或找到完全位于窗口内的直线段为止。

[计算机图形学]复习Cohen-Sutherland直线段裁剪算法

[计算机图形学]复习Cohen-Sutherland直线段裁剪算法

[计算机图形学]复习Cohen-Sutherland直线段裁剪算法
关于Cohen-Sutherland 直线段裁剪算法思想概述
直线段裁剪是⼆维图形裁剪的基础,本质是判断直线段是否与窗⼝边界相交,如相交则进⼀步确定直线段上位于窗⼝内的部分。

算法思想:直线的端点赋予⼀组4位⼆进制码,称为RC(区域编码),裁剪窗⼝的四条边所在的直线可以把平⾯分为9个区域,对各个区域的编码也是四位,C3C2C1C0,分别代表上下右左四个窗⼝边界。

裁剪窗⼝所在的区域为0000,对于直线段上的端点进⾏编码,等于该端点所在的区域的编码。

编码后就容易判断两个端点的情况:
⽐如两个端点求与不等于0,即RC0&RC1≠0;说明该线段在裁剪窗⼝之外,应简弃;
两个端点RC编码按位或为0,即RC0|RC1=0。

说明直线段两个端点都在窗⼝内,应简取。

还有第三种情况:不满⾜前两种情况的,说明直线段与边界或其延长线有交点,要进⾏求交判断:
①此时直线段与边界相交,P0P1和两个边界相交,按左右下上的顺序计算交点,设交点为P,注意:总是要让直线段的⼀个顶点处于窗⼝之外,例如P0点。

这样P0点到交点P的直线段必然不可见,故可以将交点外的线段简弃。

②直线段与边界的延长线相交,直线段在窗⼝外,也不在窗⼝同⼀侧。

依旧按照左右下上顺序计算,将延长线与线段交点定为P,有PP0,位于窗⼝某侧,被简弃。

如果求裁剪后窗⼝内直线段的端点坐标,(那⼀般是求P1,以实际题⽬为准,看剪了哪部分),两点求直线⽅程,然后带⼊相交边界的x或y值可得。

改进的Cohen-Sutherland线段裁剪算法

改进的Cohen-Sutherland线段裁剪算法

改进的Cohen-Sutherland线段裁剪算法
王艳娟;肖刚强;任洪海
【期刊名称】《现代计算机(专业版)》
【年(卷),期】2007(000)002
【摘要】针对目前Conhen-Sutherland线段裁剪算法不能有效地判断出线段是否完全在窗口外的问题,提出了一种改进算法,通过添加一个判断条件,使得所有完全位于窗口外的线段都能快速地过滤出来,从而减少了求交点的次数,提高了运算效率.【总页数】2页(P15-16)
【作者】王艳娟;肖刚强;任洪海
【作者单位】大连交通大学软件学院,大连,116052;大连交通大学软件学院,大连,116052;大连交通大学软件学院,大连,116052
【正文语种】中文
【中图分类】TP3
【相关文献】
1.对Cohen-Sutherland线段裁剪算法的改进 [J], 孔德慧;尹宝才;刘媛媛
2.对Cohen-sutherland线段裁剪算法的分析及改进 [J], 王慧玲;冯雪花
3.改进的Cohen-Sutherland线段裁剪算法 [J], 纪召军;赵京东
4.对Cohen-Sutherland裁剪算法的分析与改进 [J], 郭旌巍;杨振州
5.对Cohen-Sutherland线段裁剪算法的一点改进 [J], 严圣华
因版权原因,仅展示原文概要,查看原文内容请购买。

cohen-sutherland 直线段裁剪算法 -回复

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. 定义需要裁剪的直线段的起点和终点坐标。

CohenSutherland裁剪算法并使用OpenGL实践

CohenSutherland裁剪算法并使用OpenGL实践

CohenSutherland裁剪算法并使⽤OpenGL实践 还是其⼏天写的,这是最简单的⼀个直线裁剪算法了吧,它针对的是⼀个矩形和⼀条线段。

并且还是边与坐标轴平⾏的矩形。

在实际应⽤上应该会经常⽤于屏幕对各种线段的裁剪吧。

算法很简单效率也很⾼。

⾸先是算法的两种特例:平凡接受和平凡拒绝。

(图⽚来⾃《计算机图形学(OpenGL)》第三版) 当线段的两个端点都在矩形内部,则平凡接受,不需要裁剪。

如图中的AB。

⽽当线段的两个端点都在某条边的外边时,平凡拒绝,也不需要裁剪。

如图中的CD。

检测这两种情况的⽅法可以先形成两个端点的码字,如下:那么可以得到如下的⼏种码字: 如果两个点都在矩形内部,那么码字应该都是FFFF,则平凡接受,返回当前线段就好。

⽽如果两个点的某⼀位都是T,则说明他们都在矩形某条边的外⾯,则平凡拒绝。

如图3.17中的CD,对应的码字分别应是FTTF和FFTF,在第三位上都是T,他们都在矩形的右边,则平凡拒绝。

我们运⾏这样的算法来裁剪⼀条线段: 最后,代码如下:1 #include <GL/gl.h>2 #include <GL/glu.h>3 #include <GL/glut.h>4 #include <cmath>5 #include <iostream>6using namespace std;78struct Point2D9 {10float _x, _y;11 Point2D()12 {13 _x = 0.0f;14 _y = 0.0f;15 }16 Point2D(const Point2D& p)17 {18 _x = p._x;19 _y = p._y;20 }21 Point2D(float xx, float yy)22 {23 _x = xx;24 _y = yy;25 }26 Point2D& operator=(const Point2D& p)27 {28 _x = p._x;29 _y = p._y;30return *this;31 }32 Point2D& operator+(const Point2D& p)33 {34 Point2D temp;35 temp._x = _x + p._x;36 temp._y = _y + p._y;37return temp;38 }39 Point2D& operator-(const Point2D& p)40 {41 Point2D temp(_x - p._x, _y - p._y);42return temp;43 }44float operator*(const Point2D& p)45 {46return _x * p._x + _y * p._y;47 }4849float length()50 {51return sqrtf(_x * _x + _y * _y);52 }53 };5455struct Line2D56 {57 Point2D _start;58 Point2D _end;59float _length;6061 Line2D() : _start(), _end()62 {63 _length = 0.0f;64 }65 Line2D(const Point2D& start, const Point2D& end) : _start(start), _end(end)66 {67 }68 Line2D(const Line2D& line) : _start(line._start), _end(line._end)69 {}7071float length()72 {73 _length = (_end - _start).length();74 }7576 Line2D& operator = (const Line2D& line)77 {78 _start = line._start;79 _end = line._end;80 }81 };8283struct Rect84 {85float _left;86float _right;87float _up;88float _down;8990float width()91 {92return _right - _left;93 }94float height()95 {96return _down - _up;97 }98 };99100enum CutRes101 {102 CR_ACCEPTED = 0,103 CR_REFUSED = 1,104 };105106enum CSBIT107 {108 CB_BELOW = 0x01,//0001109 CB_RIGHT = 0x02,//0010110 CB_ABOVE = 0x04,//0100111 CB_LEFT = 0x08,//1000112113 CB_BELOW_INV = 0xfe,//1111 1110114 CB_RIGHT_INV = 0xfd,//1111 1101115 CB_ABOVE_INV = 0xfb,//1111 1011116 CB_LEFT_INV = 0xf7,//1111 0111117 };118119 typedef unsigned char KEY;120121/*Global Varibles*/122const int SCREEN_WIDTH = 800;123const int SCREEN_HEIGHT = 600;124 Point2D g_Start;125 Point2D g_End;126 Line2D src;127 Line2D dest;128bool acc;129 Rect g_Rect;130int g_Count;131132 KEY GenKey(const Point2D& p, const Rect& r) 133 {134 KEY key = 0;135136if(p._y > r._down)137 {138 key |= CB_BELOW;139 }140if(p._y < r._up)141 {142 key |= CB_ABOVE;143 }144if(p._x < r._left)145 {146 key |= CB_LEFT;147 }148if(p._x > r._right)149 {150 key |= CB_RIGHT;151 }152153return key;154 }155156void ShowKey(KEY key)157 {158if(key & CB_LEFT)159 cout << "T";160else161 cout << "F";162163if(key & CB_ABOVE)164 cout << "T";165else166 cout << "F";167168if(key & CB_RIGHT)169 cout << "T";170else171 cout << "F";172173if(key & CB_BELOW)174 cout << "T";175else176 cout << "F";177 }178179/*180key: TTFF181left above right below182*/183int Cohen_Sutherland(const Line2D& src, Line2D& dest, const Rect& rect)184 {185 cout << "===============In Cohen_Sutherland===============\n";186 Point2D start = src._start;187 Point2D end = src._end;188 KEY s, e;189 dest = src;190191for(unsigned int i = 0; i < 4; ++i)192 {193 cout << "\nNow Line: start(" << start._x << ", " << start._y <<") end(" << end._x << ", " << end._y << ")\n"; 194195 s = GenKey(start, rect);196 e = GenKey(end, rect);197 cout << "Key of Line: start ";ShowKey(s);cout << " end: ";ShowKey(e); cout << endl;198199if((s == e) && (s == 0))200 {201//accept, all point inside the rect202 dest._start = start;203 dest._end = end;204return CR_ACCEPTED;205 }206int _b = 1 << i;207if((s & _b) && (e & _b))208 {209//all point at same side210return CR_REFUSED;211 }212213switch(i)214 {215case0:216 {217//below218if(s & _b)219 {220float scale = (rect._down - end._y) / (start._y - end._y);221 start._x = (start._x - end._x) * scale + end._x;222 start._y = rect._down;223 cout << "Start Below Rect. Cutted: " << start._x << ", " << start._y << endl;224 }225if(e & _b)226 {227float scale = (rect._down - start._y) / (end._y - start._y);228 end._x = (end._x - start._x) * scale + start._x;229 end._y = rect._down;230 cout << "end Below Rect. Cutted: " << end._x << ", " << end._y << endl;231 }232 }break;233case1:234 {235//right236if(s & _b)237 {238float scale = (rect._right - end._x) / (start._x - end._x);239 start._x = rect._right;240 start._y = (start._y - end._y) * scale + end._y;241 cout << "start right Rect. Cutted: " << start._x << ", " << start._y << endl;242 }243if(e & _b)244 {245float scale = (rect._right - start._x) / (end._x - start._x);246 end._x = rect._right;247 end._y = (end._y - start._y) * scale + start._y;248 cout << "end right Rect. Cutted: " << end._x << ", " << end._y << endl;250 }break;251case2:252 {253//above254if(s & _b)255 {256float scale = (rect._up - end._y) / (start._y - end._y);257 start._x = (start._x - end._x) * scale + end._x;258 start._y = rect._up;259 cout << "start above Rect. Cutted: " << start._x << ", " << start._y << endl;260 }261if(e & _b)262 {263float scale = (rect._up - start._y) / (end._y - start._y);264 end._x = (end._x - start._x) * scale + start._x;265 end._y = rect._up;266 cout << "end above Rect. Cutted: " << end._x << ", " << end._y << endl;267 }268 }break;269case3:270 {271//left272if(s & _b)273 {274float scale = (rect._left - end._x) / (start._x - end._x);275 start._x = rect._left;276 start._y = (start._y - end._y) * scale + end._y;277 cout << "start left Rect. Cutted: " << start._x << ", " << start._y << endl;278 }279if(e & _b)280 {281float scale = (rect._left - start._x) / (end._x - start._x);282 end._x = rect._left;283 end._y = (end._y - start._y) * scale + start._y;284 cout << "end left Rect. Cutted: " << end._x << ", " << end._y << endl;285 }286 }break;287 }288 }289 s = GenKey(start, rect);290 e = GenKey(end, rect);291292 cout << "At Last, Key of Line: start ";ShowKey(s);cout << " end: ";ShowKey(e); cout << endl;293if((s == e) && (s == 0))294 {295//accept, all point inside the rect296 dest._start = start;297 dest._end = end;298return CR_ACCEPTED;299 }300else301 {302return CR_REFUSED;303 }304 }305306void myInit()307 {308/*309 Output Info310*/311312 g_Rect._up = 100;313 g_Rect._down = 500;314 g_Rect._left = 100;315 g_Rect._right = 700;316 g_Count = 0;317 acc = false;318 cout << "Rect: {" << g_Rect._left << ", " << g_Rect._up << ", " << g_Rect._right << ", "<< g_Rect._down << "}\n"; 319320 glClearColor((float)0x66 / 0x100, (float)0xcc / 0x100, 1.0, 0.0);321 glColor3f(0.0f, 0.0f, 0.0f);//Map Color Black322 glPointSize(1.0);323 glMatrixMode(GL_PROJECTION);324325 glLoadIdentity();326 gluOrtho2D(0.0, (GLdouble)SCREEN_WIDTH, (GLdouble)SCREEN_HEIGHT, 0.0);327 glViewport(0.0, SCREEN_WIDTH, 0.0, SCREEN_HEIGHT);328 }329330void myMouse(int button, int state, int x, int y)331 {332if(button != GLUT_LEFT_BUTTON || state != GLUT_DOWN)334335 cout << "MyMouse Called with " << x << ", " << y << endl; 336switch(g_Count)337 {338case0:339 {340 ++g_Count;341 g_Start._x = x;342 g_Start._y = y;343 src._start = g_Start;344 }break;345case1:346 {347 ++g_Count;348 g_End._x = x;349 g_End._y = y;350 src._end = g_End;351 acc = Cohen_Sutherland(src, dest, g_Rect);352if(acc)353 {354 cout << "Refused.\n";355 }356else357 cout << "Accept.\n";358359 glutPostRedisplay();360 }break;361case2:362 {363 g_Start._x = x;364 g_Start._y = y;365 src._start = g_Start;366 g_Count = 1;367 }break;368 }369 }370371void myDisplay()372 {373 glClear(GL_COLOR_BUFFER_BIT);374375//Draw Rect376377 glColor3f(0.0f, 0.0f, 0.0f);//Rect378 glPointSize(2.0);379 glBegin(GL_LINE_STRIP);380 glVertex2d(g_Rect._left, g_Rect._up);381 glVertex2d(g_Rect._right, g_Rect._up);382 glVertex2d(g_Rect._right, g_Rect._down);383 glVertex2d(g_Rect._left, g_Rect._down);384 glVertex2d(g_Rect._left, g_Rect._up);385 glEnd();386387if(g_Count == 2)388 {389//Draw Line390 glColor3f(1.0f, 0.0f, 0.0f);//Normal Line, Red391 glPointSize(2.0);392 glBegin(GL_LINES);393 glVertex2d(src._start._x, src._start._y);394 glVertex2d(src._end._x, src._end._y);395 cout << "\nDraw Line\n";396if(acc == CR_ACCEPTED)397 {398//Draw Cutted Line399 glColor3f(0.0f, 1.0f, 0.0f);//Normal Line, Green400 glPointSize(2.0);401 glVertex2d(dest._start._x, dest._start._y);402 glVertex2d(dest._end._x, dest._end._y);403 cout << "\nDraw CutLine\n";404 }405 glEnd();406 }407408//glutSwapBuffers();409 glFlush();410//cout << "Render Over\n";411 }412413int main(int argc, char* argv[])414 {415 glutInit(&argc, argv);416//glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);417 glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);418 glutInitWindowSize(SCREEN_WIDTH, SCREEN_HEIGHT);419 glutInitWindowPosition(0, 0);420 glutCreateWindow("Cohen Sutherland");421 glutDisplayFunc(myDisplay);422 glutMouseFunc(myMouse);423424 myInit();425 glutMainLoop();426427return0;428 }Cohen_Sutherland_with_GL 程序最上⾯是⼀些数据结构的定义,包括Point2D、Line2D、Rect等。

直线裁剪算法研究(Cohen_Sutherland算法和Liang_Barsky算法)

直线裁剪算法研究(Cohen_Sutherland算法和Liang_Barsky算法)

直线裁剪算法研究摘要:直线裁剪是计算机图形学中的一个重要技术,在对常见的直经线裁剪的算法分析的基础上,针对Cohen-Sutherland算法和Liang-Barsky算法进行了分析研究。

并对两种算法了计算直线与窗口边界的交点时,进行了有效有比较。

关键词:裁剪;算法;Cohen-Sutherland;Liang-Barsky;1 引言直线是图形系统中使用最多的一个基本元素。

所以对于直线段的裁剪算法是被研究最深入的一类算法,目前在矩形窗口的直线裁剪算法中,出现了许多有效的算法。

其中比较著名的有:Cohen-Sutherland算法、中点分割算法、Liang-Ba rsky算法、Sobkow-Pospisil-Yang 算法,及Nicholl-Lee-Ncholl算法等。

2 直线裁剪的基本原理图1所示的为直线与窗口边界之间可能出现的几种关系。

可以通过检查直线的两个端点是否在窗口之确定如何对此直线裁剪。

如果一直线的两个端点均在窗口边界之(如图1中P5到P6的直线),则此直线应保留。

如果一条直线的一个端点在窗口外(如P9)另一个点在窗口(如P10),则应从直线与边界的交点(P9)处裁剪掉边界之外的线段。

如果直线的两个端点均在边界外,则可分为两种情况:一种情况是该直线全部在窗口之外;另一种情况是直线穿过两个窗口边界。

图中从P3到P4的直线属于前一种情况,应全部裁剪掉;从P7到P8的直线属于后一种情况,应保留P7到P8的线段,其余部分均裁剪掉。

图1直线相对干窗口边界的栽剪直线裁剪算法应首先确定哪些直线全部保留或全部裁剪,剩下的即为部分裁剪的直线。

对于部分裁剪的直线则首先要求出这些直线与窗口边界的交点,把从交点开始在边界外的部分裁剪掉。

一个复杂的画面中可能包含有几千条直线,为了提高算法效率,加快裁剪速度,应当采用计算量较小的算法求直线与窗口边界的交点。

3 cohen-sutherland直线裁剪算法Cohen-Sutherland算法的大意是:对于每条线段P1P2,分为3种情况处理。

计算机图形学裁剪算法

计算机图形学裁剪算法

一、实验目标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线段裁剪算法

改进的Cohen-Sutherland线段裁剪算法

线段裁剪是计算机图形学需要解决的最基本问题之一,它是多边形裁剪的基础,也是图形消隐的基础。

线段裁剪的效率对于整个图形系统的速度具有举足轻重的作用。

任意多边形窗口的线段裁剪相对复杂,其效率一般低于凸多边形窗口的线段裁剪。

矩形窗口是一种特殊的凸多边形,它是应用中使用最多的。

矩形窗口的线段裁剪效率一般高于其他凸多边形的线段裁剪效率。

具有代表性的线段裁剪算法有:Cohen-Sut her l and 算法、中点分割法、Cyr us -Be c k 算法和Li a ng-B ar sky 算法[1],还有N i chol l -L ee-N i chol l 算法[2],A ndr e ev-Sof i ans ka 算法[3],王骏-梁有栋-彭群生算法[4],刘勇奎-颜叶-石教英算法[5],汪灏泓-吴锐迅-蔡士杰算法[6],穆玉杰-陈泽志-张晓鹏[7],还有一些上述算法的改进算法[8-11]。

在这些算法中,刘勇奎-颜叶-石教英算法是适合于任意多形窗口的线段裁剪,Cyr us -Be c k 算法是适合于凸多边形窗口的线段裁剪,其他算法都是真对矩形窗口的线段裁剪。

其中,中点分割法[1]和陆国栋-吴晖算法[8]易于用硬件实现。

C ohe n-Sut he r l and 裁剪算法是一经典的矩形窗口线段裁剪算法,它在同类算法中是一效率适中的算法。

由于其思路简单,编程方便,因而实际应用中被经常采用。

也有学者对Cohe n-Sut he r l a nd 算法进行了改进[9,10],以进一步提高运算效率,但这些改进算法均破坏了Cohen-Sut he r l a nd 算法的编码思想,使算法复杂度大大增加,而运算效率提高不多。

本文在分析了Cohen-Sut he r l a nd 裁剪算法的编码方法后,提出了交点的分类编码,使编码效率大大提高,从而在不改变C ohen-Sut he r l a nd 编码思想的基础上提高了算法的效率,完善了C ohe n-Sut her l and 裁剪算法。

cohen-sutherland 直线段裁剪算法

cohen-sutherland 直线段裁剪算法

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

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

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

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

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

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

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

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

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

论述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(即都在可视范围内),则可以直接输出该线段;否则,执行下一步。

简述cohen-sutherland直线段的裁剪算法

简述cohen-sutherland直线段的裁剪算法

简述Cohen-Sutherland直线段的裁剪算法Cohen-Sutherland算法是一种经典的直线段裁剪算法,常用于计算机图形学中。

该算法对于裁剪窗口和直线段分别进行编码,通过比较编码来确定是否需要进行裁剪。

下面是Cohen-Sutherland算法的伪代码:function CohenSutherlandLineClip(x0, y0, x1, y1, xmin, ymin, xmax, ymax)OUTCODE_INSIDE = 0 // 线段完全在裁剪窗口内部OUTCODE_LEFT = 1 // 线段位于裁剪窗口左侧OUTCODE_RIGHT = 2 // 线段位于裁剪窗口右侧OUTCODE_BOTTOM = 4 // 线段位于裁剪窗口底部OUTCODE_TOP = 8 // 线段位于裁剪窗口顶部// 初始化线段的编码code0 = computeOutCode(x0, y0, xmin, ymin, xmax, ymax) code1 = computeOutCode(x1, y1, xmin, ymin, xmax, ymax)while (true) {if (code0 == 0 and code1 == 0) {// 线段完全在裁剪窗口内部return (x0, y0, x1, y1)} else if ((code0 & code1) != 0) {// 线段完全在裁剪窗口外部,可以丢弃return null} else {// 需要裁剪的部分x = 0y = 0codeOut = code0 != 0 ? code0 : code1// 计算交点if ((codeOut & OUTCODE_TOP) != 0) {x = x0 + (x1 - x0) * (ymax - y0) / (y1 - y0) y = ymax} else if ((codeOut & OUTCODE_BOTTOM) != 0) { x = x0 + (x1 - x0) * (ymin - y0) / (y1 - y0) y = ymin} else if ((codeOut & OUTCODE_RIGHT) != 0) { y = y0 + (y1 - y0) * (xmax - x0) / (x1 - x0) x = xmax} else if ((codeOut & OUTCODE_LEFT) != 0) { y = y0 + (y1 - y0) * (xmin - x0) / (x1 - x0) x = xmin}// 更新交点和编码if (codeOut == code0) {x0 = xy0 = ycode0 = computeOutCode(x0, y0, xmin, ymin, xmax, ymax)} else {x1 = xy1 = ycode1 = computeOutCode(x1, y1, xmin, ymin, xmax, ymax)}}}}function computeOutCode(x, y, xmin, ymin, xmax, ymax) code = 0if (x < xmin) {code = code | OUTCODE_LEFT} else if (x > xmax) {code = code | OUTCODE_RIGHT}if (y < ymin) {code = code | OUTCODE_BOTTOM} else if (y > ymax) {code = code | OUTCODE_TOP}return code}以上是一个简单的Cohen-Sutherland直线段裁剪算法的实现。

二维裁剪算法Cohen_Sutherland的实现

二维裁剪算法Cohen_Sutherland的实现

{
int nCode1 = 0;
int nCode2 = 0;
nCode1 = Encode(P1.x, P1.y);
nCode2 = Encode(P2.x, P2.y);
if(nCode1 ==0 && nCode2 ==0)
return;
//直 线 在 裁 剪 窗 口 内 , 直 接 返 回
else if((nCode1 & nCode2) != 0)
void CClipzccView::OnClipLineCohenSutherland() {
// TODO: Add your command handler code here
CPoint P1 = CPoint(80,400); CPoint P2 = CPoint(200,80); CDC *pDC = this->GetDC(); CPen newPen(PS_SOLID,2,RGB(255,0,0)); //用红色 2 个线宽绘制被裁剪初始直线 CPen *pOldPen=pDC->SelectObject(&newPen); pDC->MoveTo(P1); pDC->LineTo(P2); pDC->SelectObject(pOldPen);
{
int nCode1 = 0;
int nCode2 = 0;
nCode1 = Encode(P1.x, P1.y);
nCode2 = Encode(P2.x, P2.y);
if(nCode1 ==0 && nCode2 ==0)
return;
//直线在裁剪窗口内,直接返回
else if((nCode1 & nCode2) != 0)

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页。

直线段裁剪的Cohen-Sutherland算法实现

直线段裁剪的Cohen-Sutherland算法实现

直线段裁剪的Cohen-Sutherland算法实现package myProject;import java.util.*;class Point{public int x,y; //点的横纵坐标public Point(int x,int y){this.x=x;this.y=y;}}class Window{public int wxl,wxr,wyb,wyt; //窗口边界值public Window(int wxl,int wxr,int wyb,int wyt){this.wxl=wxl;this.wxr=wxr;this.wyb=wyb;this.wyt=wyt;}}public class cutLine {public static void main(String[] args) {Scanner sc=new Scanner(System.in);System.out.print("Please input the Line's 2 Point\np1: ");Point p1=new Point(sc.nextInt(),sc.nextInt());System.out.print("p2: ");Point p2=new Point(sc.nextInt(),sc.nextInt());System.out.println("Please input the window's wxl,wxr,wyb,wyt:");Window win=newWindow(sc.nextInt(),sc.nextInt(),sc.nextInt(),sc.nextInt());cutLine cut=new cutLine();cut.run(p1, p2, win);if(cut.result==false)System.out.println("The Line has been abandoned");elseSystem.out.println("After cut,the coordinate of the line:");System.out.println("p1:"+cut.resultP1.x+""+cut.resultP1.y+"\np2:"+cut.resultP2.x+" "+cut.resultP2.y);}Point resultP1=new Point(0,0);Point resultP2=new Point(0,0);boolean result=false;byte getCode(Point p,Window win){byte code=0;if(p.x<win.wxl)< p="">code+=1;if(p.x>win.wxr)code+=2;if(p.y<win.wyb)< p="">code+=4;if(p.y>win.wyt)code+=8;return code;}void run(Point p1,Point p2,Window win){byte codeP1=getCode(p1,win);byte codeP2=getCode(p2,win);if(codeP1==0&&codeP2==0){result=true;this.resultP1=p1;this.resultP2=p2;return;}if((codeP1&codeP2)!=0){result=false;return;}if(codeP1==0){search(p2,p1,win,codeP2); //如果P1在窗口内,通过外侧的P2找交点}else {search(p1,p2,win,codeP1);//如果P2在窗口内,通过外侧的P1找交点}//确保了search函数里第一个参数在窗口外run(p1,p2,win); //递归调用此函数来求}void search(Point outP,Point stayP,Window win,byte code){ if((code&1)!=0){outP.y=(int)(outP.y-stayP.y)/(outP.x-stayP.x)*(win.wxl-outP.x)+outP.y;outP.x=win.wxl;}else if((code&8)!=0){outP.x=(int)(outP.x-stayP.x)/(outP.y-stayP.y)*(win.wyt-outP.y)+outP.x;outP.y=win.wyt;}else if((code&2)!=0){outP.y=(int)(outP.y-stayP.y)/(outP.x-stayP.x)*(win.wxr-outP.x)+outP.y;outP.x=win.wxr;}else if((code&4)!=0){outP.x=(int)(outP.x-stayP.x)/(outP.y-stayP.y)*(win.wyt-outP.y)+outP.x;outP.y=win.wyb;}}}</win.wyb)<></win.wxl)<>。

图形学实验报告--线段裁剪

图形学实验报告--线段裁剪

计算机科学与技术学院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,添加消息处理函数,建立类向导,最后添加程序代码。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

改进的cohen-sutherland线段裁剪算法
王艳娟肖刚强任洪海
(大连交通大学软件学院116052)
摘要:针对目前的conhen-sutherland线段裁剪算法不能有效地判断出线段是否完全在窗口外的问题,提出了一种改进的conhen-sutherland线段裁剪算法,通过添加一个判断条件,使得所有完全位于窗口外的线段都能快速的过滤出来,从而减少了求交点的次数,提高了运算效率。

关键词:裁剪算法,cohen-sutherland线裁剪算法,求交运算0.引言
线段裁剪是复杂图元裁剪的基础,各种非线性边界都可以用直线段来近似,以减少计算量。

目前广泛使用的3种经典裁剪算法分别是梁友栋-Barsky参数裁剪算法、
Cohen-sutherland编码裁剪算法和Nicholl-Lee-Nicholl多区域判别算法。

这些算法各有特色,梁友栋-Barsky裁剪算法利用线段的参数表示形式,把被裁剪线段所在直线与矩形裁剪窗口边框线的交点坐标的计算,简化为对交点对应的参数值的计算,再根据交点参数与被裁剪线段的参数定义区间比较的结果,确定出有效的交点,从而得到裁剪后应保留的部分线段。

Cohen-sutherland裁剪算法是一个最早开发的快速线段裁
剪算法,应用较为广泛。

该算法通过初始测试来减少交点计算,从而减少线段裁剪算法所用的时间。

Nicholl-Lee-Nicholl 算法通过在裁剪窗口边界创立多个区域,从而避免对一个直线段进行多次裁剪。

由于Cohen-sutherland线段裁剪算法实现简单,应用广泛,本文对此算法进行了一些改进。

1.Cohen-sutherland线段裁剪算法描述
Cohen-sutherland线段裁剪算法对每条线段的端点都赋予一个四位二进制编码,称为‘区域码’。

区域码的每一位用来标示端点相对于相应裁剪边界的里面还是外面,分别用‘0’和‘1’表示。

这样,四个窗口边界一起生成了九个区域,每个区域都有一个唯一的区域码,如图1所示。

图1 裁剪窗口的九个位置区域码
一旦给所有的线段端点建立了区域码,就可以快速判断哪条线段完全在裁剪窗口内,哪条线段完全在窗口之外。

完全在窗口边界内的线段,其两个端点的区域码均为0000,因此保留这些线段。

若两个端点的区域码中,有某一相同位置
都为1,则该线段完全落在裁剪矩形之外,因此丢弃这些线段。

测试线段是否在内部或外部的方法是对两个端点的区域码进行逻辑操作,如果两个端点的区域码进行逻辑或的结果为0000,则线段完全位于裁剪区域之内。

如果两个端点的区域码进行逻辑与操作的结果不是真(不为0000),则线段完全位于裁剪区域之外。

对于不能判断为完全在窗口外或窗口内的线段,则要测试其与窗口边界的交点。

2.Cohen-sutherland 线段裁剪算法改进
Cohen-sutherland 算法对那些不与边框相交的线段进行裁剪时效率较高,而对与窗口边界有交点的线段裁剪效率较低,而且很多时候,被裁剪线段仅与窗口边界的延长线相交,
而没有穿过窗口内部,Cohen-sutherland 算法计算了所有的交
点后,结果却是完全舍弃,如图2中线A 。

由于求交运算是裁剪算法中最耗时的部分,任何的算法都应该尽量避免求交运算,Cohen-sutherland 算法中,这样无效的交点计算降低了算法的效率。

针对这个问题有很多学者进行了改进,如文献[3][4],这些方法大都是进行了较多的区域划分和判断,比较复杂。

本文提出了一种简单易行的判断方法,可以快速的判断出线段是否完全在窗口外,从而减少计算量。

线A
线B 线C
图2 线段与裁剪窗口的位置关系
本文算法思想如下:
直线段P 1P 2的编码裁剪
如果线段完全在窗口外,那么有两种可能:
(1)线段两端点的编码中有某一相同位置都为1,即两个端点编码进行逻辑与操作的结果为真,如图2中线C。

(2)裁剪窗口完全位于线段的同侧,如图2中线A。

对于这种情况可以如下判断:将裁剪窗口的四个端点代入直线方程,如果符号相同,说明窗口在线段的同侧,即线段完全在窗口外;否则,说明线段和窗口有交点。

改进的Cohen-sutherland算法可以描述如下:
首先对被裁剪线段两个端点进行编码。

然后进行如下测试:
(1)将两端点的区域码进行逻辑或运算,如果结果为0000,说明线段完全在窗口内,可以完全保留。

(2)将两端点的区域码进行逻辑与运算,如果结果为真(不是0000),说明线段完全在窗口外,可以完全舍弃。

(3)将窗口的四个顶点代入直线方程,如果符号相同,说明线段完全在窗口外,可以完全舍弃。

对于上述情况均不满足的线段,需要进行求交运算,这些线段必穿过窗口内部。

通过添加这样一个判断条件将算法的求交次数大大减少,从而提高了算法的效率。

3.算法部分代码
……
class Point{
……
}
Point point1;
Int reject2(point p1, point1 p2){
If(((winMin.y-p1.y)/(winMin.x-p1.x)-(p2.y-p1.y)/(p2.x-p1.x)>0) &……)
……
}
int done=false,plotLine=false;
while(!done){
code1=encode(p1,winMin,winMax);
code2=encode(p2,winMin,winMax);
if(accept(code1,code2)){
done=true;
plotLine=true;
}
else
if(reject1(code1,code2))
done=true;
else
if(reject2(p1,p2))
done=true;
else {
......
4.结论
直线裁剪算法是计算机图形学领域的一个基本问题,提高线裁剪算法的效率在计算机图形学的各个应用领域中都
有着重大的意义。

线段与窗口边界的交点计算是线裁剪函数的耗时部分,本文通过对cohen-sutherland线裁剪算法进行了改进,从而减少了求交次数,提高了算法的效率。

参考文献
[1] Donald Hearn, 计算机图形学[M],第三版,北京,电子工业出版社,2005
[2]孙家广, 杨长贵, 计算机图形学基础[M],第三版, 北京,清华大学出版社,2002
[3]孔德惠等,对cohen-sutherland线段裁剪算法的改进[J],北京工业大学学报,2002
[4]郭长友等,一种快速的二维线段裁减新算法[J],福建电脑,2006。

相关文档
最新文档