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直线剪裁算法
(3)onside(int[]):该方法判断直线两端点是否在区域内
(4)outside(int[]):该方法判断直线是否在同一端
(5)cutYourLine(int,int,int,int):该方法用于获取直线与区域的两个交点坐标
实验总结以及心得体会:
评定成绩:批阅老师:2017年月日
附页:
(1)paintComoponet(Graphics):void ,该方法主要用于画图,通过调用encode(int,int,int,int)方法、onside(int[])方法、outside(int[])方法和cutYourLIne(int,int,int,int)方法判断直线的类型和获取在区域内的两个直线端点坐标,画出区域内的直线
实验报告
专业:软件工程班级:学号:姓名:
课程名称:图形图像处理2017– 2017年度第2学期
课程类别:专业选修实验时间:2017年月日
实验名称:Cohen-Suths7 , Windows XP等都可,
使用Eclipse做实验。
实验目的和要求:
编写线段裁剪算法程序,验证算法的正确性
实验内容:
对于每条线段P1P2分为三种情况处理。
(1)若P1P2完全在窗口内,则显示该线段P1P2简称“取”之。
(2)若P1P2明显在窗口外,则丢弃该线段,简称“弃”之。
(3)若线段既不满足“取”的条件,也不满足“弃”的条件,则在交点处把线段分为两段。其中一段完全在窗口外,可弃之。然后对另一段重复上述处理。
实验截图如下:
cohen-sutherland裁剪算法例题
cohen-sutherland裁剪算法例题一、算法简介Cohen-Sutherland裁剪算法是一种用于图像处理的算法,用于确定一个像素点是否被剪裁,即是否需要被剔除。
该算法基于一个简单的原理:对于一个像素点,如果它的坐标位于某个特定区域(例如矩形区域)之外,那么它就不属于原始图像的裁剪区域,可以被剔除。
二、算法步骤1.初始化:设定一个裁剪区域的起始坐标(xmin,ymin)和结束坐标(xmax,ymax)。
2.将裁剪区域的坐标转化为四舍五入的整数坐标(xm,ym,xm+1,ym+1)。
3.判断像素点(x,y)是否在裁剪区域内:a.如果(x>=xminandx<=xmaxandy>=yminandy<=ym),则像素点在裁剪区域内。
b.否则,像素点不在裁剪区域内。
4.根据像素点的位置,确定是否需要剔除该像素点:a.如果像素点在裁剪区域内,则保留该像素点。
b.如果像素点不在裁剪区域内,则剔除该像素点。
三、算法应用Cohen-Sutherland裁剪算法在图像处理中非常有用,它可以有效地剔除不需要的像素点,提高图像的质量和清晰度。
例如,在图像缩放、剪裁、滤镜处理等操作中,都需要用到Cohen-Sutherland裁剪算法。
四、例题实现以下是一个使用Python实现的Cohen-Sutherland裁剪算法的例子:```pythondefcohen_sutherland(image,xmin,ymin,xmax,ymax):#将坐标转化为四舍五入的整数坐标xm,ym=int(xmin),int(ymin)xm_next,ym_next=int(xmax),int(ymax)+1#加上1是为了避免下溢image_clipped=[list(i)foriinimage]#创建一个新的列表用于存放裁剪后的图像数据foriinrange(len(image)):forjinrange(len(image[i])):if(j>=ymori>=xmorj<ym_next-ymori<xm_next-xm):#如果像素点不在裁剪区域内image_clipped[i][j]=""#剔除该像素点,用空格代替else:#在裁剪区域内,保留该像素点image_clipped[i][j]=image[i][j]#不作任何修改returnimage_clipped```五、示例应用以下是一个使用Cohen-Sutherland裁剪算法进行图像剪裁的示例:假设有一张名为"input.jpg"的图像,要将其中的一部分剪裁掉。
[计算机图形学]复习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裁剪算法#include <iostream>#include <windows.h>#include <gl/glut.h>using namespace std;#include <GL/glut.h>#include <cstdio>#define LEFT 1#define RIGHT 2#define BOTTOM 4#define TOP 8int x1=150,y1=50, x2=50, y2=250, XL=100, XR=300, YB=100, YT=200; //(x1,y1)、(x2,y2)为直线段的端点,XL为左边界,XR为右边界,YB为下边界,YT为上边界int x1_init = 150, y1_init = 50, x2_init = 50, y2_init = 250; //将直线段端点备份,以便画出裁剪前的直线段int encode(int x,int y){int c = 0;if (x < XL) c |= LEFT;if (x > XR) c |= RIGHT;if (y < YB) c |= BOTTOM;if (y > YT) c |= TOP;return c;}void CS_LineClip() //Cohen-Sutherland裁剪算法{int x, y;int code1, code2, code;code1 = encode(x1, y1);code2 = encode(x2, y2);while (code1 != 0 || code2 != 0){if (code1 & code2)return;if (code1 != 0)code = code1;elsecode = code2;if (LEFT & code){x = XL;y = y1 + (y2 - y1)*(XL - x1) / (x2 - x1);}else if (RIGHT & code){x = XR;y = y1 + (y2 - y1)*(XR - x1) / (x2 - x1);}else if (BOTTOM & code){y = YB;x = x1 + (x2 - x1)*(YB - y1) / (y2 - y1);}else if (TOP & code){y = YT;x = x1 + (x2 - x1)*(YT - y1) / (y2 - y1);}if (code == code1){x1 = x; y1 = y; code1 = encode(x1, y1);}else{x2 = x; y2 = y; code2 = encode(x2, y2);}}}void init() //初始化函数{glClearColor(1.0, 1.0, 1.0, 0.0); //设置背景颜⾊glMatrixMode(GL_PROJECTION); // 设置投影参数 gluOrtho2D(0.0, 600.0, 0.0, 400.0); // 设置场景的⼤⼩ CS_LineClip(); //执⾏⼀次裁剪算法}void mydisplay() //显⽰函数{//绘制⽅形边界glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0, 0.0, 0.0);glPointSize(2);glBegin(GL_LINE_LOOP);glVertex2i(XL, YT);glVertex2i(XL, YB);glVertex2i(XR, YB);glVertex2i(XR, YT);glEnd();glFlush();//绘制未裁剪前的线段glBegin(GL_LINES);glVertex2i(x1_init, y1_init);glVertex2i(x2_init, y2_init);glEnd();glFlush();//绘制裁剪后的线段glColor3f(0.0, 0.0, 0.0);glBegin(GL_LINES);glVertex2i(x1, y1);glVertex2i(x2, y2);glEnd();glFlush();}int main(int argc, char *argv[]){glutInit(&argc, argv);glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); glutInitWindowPosition(100, 100);glutInitWindowSize(400, 400);glutCreateWindow("Cohen-Sutherland裁剪算法");init();glutDisplayFunc(&mydisplay);glutMainLoop();return 0;}。
计算机图形学实验Cohen-Sutherland算法
实验5-6一、实验题目请按照图5-32所示,使用对话框输入直线段的起点和终点坐标。
在屏幕客户区左侧区域绘制输入直线段和“窗口”,在屏幕客户区右侧区域绘制“视区”并输出裁剪结果。
这里需要用到窗视变换公式。
请使用Cohen-Sutherland 算法编程实现。
二、实验思想Cohen-Sutherland 直线裁剪算法是最早流行的编码算法。
每条直线的端点都被赋予一组四位二进制代码,称为区域编码(Region Code ,RC),用来标识直线端点相对于窗口边界及其延长线的位置。
假设窗口是标准矩形,由上(y=w yt )、下(y=w yb )、左(x=w xl )、右(x=w xr )四条边组成,如图5-23所示。
延长窗口四条边形成9个区域,如图5-24所示。
这样根据直线的任一端点P(x,y)所处的窗口区域位置,可以赋予一组4位二进制区域码RC =C 4C 3C 2C 1。
w yb w yt wxr w xl为了保证窗口内直线端点的编码为零,编码规则定义如下:第一位:若端点位于窗口之左侧,即x<w xl,则C1=1,否则C1=0。
第二位:若端点位于窗口之右侧,即x>w xr,则C2=1,否则C2=0。
第三位:若端点位于窗口之下侧,即y<w yb,则C3=1,否则C3=0。
第四位:若端点位于窗口之上侧,即y>w yt,则C4=1,否则C4=0。
裁剪步骤如下:(1)若直线的两个端点的区域编码都为零,即RC1|RC2=0,说明直线两端点都在窗口内,应“简取”之。
(2)若直线的两个端点的区域编码都不为零,即RC1&RC2≠0,即直线位于窗外的同一侧,说明直线的两个端点都在窗口外,应“简弃”之。
(3)若直线既不满足“简取”也不满足“简弃”的条件,直线必然与窗口或窗口边界的延长线相交,需要计算直线与窗口边界的交点。
交点将直线分为两段,其中一段完全位于窗口外,可“简弃”之。
对另一段重复进行上述处理,直至该直线段完全被舍弃或找到完全位于窗口内的直线段为止。
计算机图形学实验指导书--实验2使用线段剪裁
实验2使用线段剪裁Cohen——sutherland算法一.实验目的及要求根据Cohen——sutherland算法,掌握直线剪裁的程序设计方法。
注意,不能使用语言库中的画圆函数。
二.理论基础将不需要裁剪的直线挑出,并删去其中在窗外的直线,然后对其余直线,逐条与窗框求交点,并将窗框外的部分删去。
采用Cohen-Sutherland直线剪裁的算法一区域编码为基础,将窗口及周围的八个方向以4位的二进制数进行编码。
4个位分代表窗外上,下,左右的编码值。
三、算法分析1. Cohen—SutherLand直线裁剪算法裁剪的实质,就是决定图形中那些点、线段、文字、以及多边形在窗口之内。
Cohen—SutherLand直线裁剪算法的基本大意是:对于每条线段P1P2,分为三种情况处理。
1) 若P1P2完全在窗口内,则显示该线段P1P2,简称“取”之。
2) 若P1P2明显在窗口外,则丢弃该线段P1P2,简称“弃”之。
3) 若线段既不满足“取”的条件,也不满足“弃”的条件,则把线段分为两段。
其中一段完全在窗口外,可弃之。
然后对另一段重复上述处理。
为了使计算机能够快速地判断一条线段与窗口属何种关系,采用如下的编码方法。
延长窗口的边,把未经裁剪的图形区域分为9个区,每个区具有一个四位代码,即四位二进制数,从左到右各位依次表示上、下、左、右。
裁剪一条线段时,先求出端点P1P2所在的区号code1和code2。
若code1=0且code2=0,则说明P1和P2均在窗口内,那么整条线段也比在窗口内,应取之。
若code1和code2经按位与运算后的结果code1&code2不为0,则说明两个端点同在窗口的上方、下方、左方或右方。
若上述两种条件均不成立,则按第三种情况处理,求出线段与窗口某边的交点,在交点处把线段一分为二,其中必有一段完全在窗口外,可以弃之。
再对另一段重复进行上述处理。
计算线段与窗口边界(或其延长线)的交点,属于线段与直线求交问题。
裁剪算法——cohen-sutherland算法
裁剪算法——cohen-sutherland算法实验环境:VC6.0算法思想: 延长窗⼝的边,将⼆维平⾯分成9个区域,每个区域赋予4位编码C t C b C r C l,裁剪⼀条线段P1P2时,先求出所在的区号code1,code2。
若code1=0,且code2=0,则线段P1P2在窗⼝内,应取之。
若按位与运算code1&code2,则说明两个端点同时在窗⼝的上⽅、下⽅、左⽅或右⽅,则可判断线段完全在窗⼝外,可弃之;否则,按第三种情况处理,求出线段与窗⼝某边的交点,在交点处把线段⼀分为⼆,其中必有⼀段在窗⼝外,可弃之,再对另⼀段重复上述处理。
100110001010000100000010010********* 多边形裁剪编码程序实现:#include "stdafx.h"#include<stdio.h>#include<conio.h>#include<graphics.h>#define LEFT 1#define RIGHT 2#define BOTTOM 4#define TOP 8void midpointLine(int x0,int y0,int x1,int y1,int color)//中点画线算法{int a,b,d1,d2,d,x,y;a=y0-y1;b=x1-x0;d=2*a+b;d1=2*a;d2=2*(a+b);x=x0;y=y0;putpixel(x,y,color);while(x<x1){if(d<0){x++;y++;d+=d2;}else{x++;d+=d1;}putpixel(x,y,color);}}int encode(int x,int y,int XL,int XR,int YB,int YT)//编码{int c=0;if(x<XL) c|=LEFT;if(x>XR) c|=RIGHT;if(y<YB) c|=BOTTOM;if(y>YT) c|=TOP;return c;}void C_SLineClip(int x1,int y1,int x2,int y2,int XL,int XR,int YB,int YT){int code1,code2,code,x,y;code1=encode(x1,y1,XL,XR,YB,YT);code2=encode(x2,y2,XL,XR,YB,YT);while((code1 != 0) || (code2 != 0)){if((code1 & code2) != 0){midpointLine(x1,y1,x2,y2,RGB(0, 255, 0));//如果直线在裁剪窗⼝外就⽤绿⾊画出printf("线段在窗⼝外!");return;}if(code1 != 0) code=code1;else code=code2;if((LEFT & code) != 0){x=XL;y=y1+(y2-y1)*(XL-x1)/(x2-x1);}else if((RIGHT & code) != 0){x=XR;y=y1+(y2-y1)*(XR-x1)/(x2-x1);}else if((BOTTOM & code) != 0){y=YB;x=x1+(x2-x1)*(YB-y1)/(y2-y1);}else if((TOP & code) != 0){y=YT;x=x1+(x2-x1)*(YT-y1)/(y2-y1);}if(code == code1){x1=x; y1=y; code1=encode(x,y,XL,XR,YB,YT);}else{x2=x; y2=y; code2=encode(x,y,XL,XR,YB,YT);}}midpointLine(x1,y1,x2,y2,RGB(255,0,0));//将裁减的直线⽤红⾊标注return;}int main(int argc, char* argv[]){int gdriver=DETECT,gmode;int x1=20,y1=30,x2=250,y2=300,XL=10,XR=200,YT=400,YB=30;initgraph(&gdriver,&gmode,"c:\\tc");//setbkcolor(WHITE);cleardevice();midpointLine(x1,y1,x2,y2,RGB(0,255,0));//将被裁剪直线⽤绿⾊画出rectangle(10,400,200,30);//rectangle(int left,int top,int right,int bottom);//裁剪窗⼝ C_SLineClip(x1,y1,x2,y2,XL,XR,YB,YT);// cohen sutherland算法getch();closegraph();return0;}显⽰效果:将在窗⼝内的线段设为红⾊,窗⼝外的线段设为绿⾊。
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裁剪算法例题
Cohen-Sutherland裁剪算法例题Cohen-Sutherland裁剪算法是一种用于线段裁剪的算法,用于确定线段是否完全位于视窗内部,或者是否与视窗有部分或完全重合。
以下是一个例题来说明Cohen-Sutherland算法的使用:假设有一个视窗,左上角坐标为(20, 20),右下角坐标为(60, 60)。
现有一条线段,起点坐标为(10, 40),终点坐标为(70, 30)。
使用Cohen-Sutherland算法对该线段进行裁剪。
步骤1: 定义裁剪区域的编码使用二进制编码来定义裁剪区域,对于视窗的四个边界线段,可以使用以下编码:●左侧编码: 0001●右侧编码: 0010●下方编码: 0100●上方编码: 1000步骤2: 计算线段的编码对于线段的起点和终点坐标,根据其相对于视窗的位置,计算其编码。
假设线段起点的编码为C1,终点的编码为C2。
起点(10, 40)编码计算:●位于视窗左侧,所以C1 = 0001终点(70, 30)编码计算:●位于视窗右侧,所以C2 = 0010步骤3: 判断是否完全落在视窗内部如果起点和终点的编码C1和C2都为0,则表示线段完全位于视窗内部,无需裁剪。
在这个例子中,C1 = 0001,C2 = 0010,都不等于0,因此线段不完全位于视窗内部,需要进行裁剪。
步骤4: 判断是否完全在视窗之外如果起点和终点的编码C1和C2的逻辑与操作(AND)结果为非零,表示线段完全在视窗之外,可以完全丢弃不进行裁剪。
在这个例子中,C1 = 0001,C2 = 0010,它们的逻辑与操作结果为0,因此线段不完全在视窗之外,需要进行裁剪。
步骤5: 通过裁剪区域裁剪线段通过逐步调整线段的起点和终点坐标,根据它们的编码,使得线段落在视窗内部或与视窗边界相交。
在这个例子中,我们将线段向视窗内进行裁剪:●根据起点编码C1 = 0001,在视窗左边界裁剪:将起点的x坐标调整为视窗左边界的x坐标,即20,计算新的起点编码C1 =0000。
直线裁剪算法研究(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种情况处理。
cohen-sutherland 直线段裁剪算法
Cohen-Sutherland 直线段裁剪算法是一种计算机图形学中的算法,用于裁剪二维图形中超出指定矩形区域的线段。
算法步骤如下:
定义四个常量,分别表示矩形区域的四个边界:TOP, BOTTOM, LEFT, RIGHT。
对于每条待裁剪的线段,计算其与矩形区域的交集情况,可以使用一个 4 位的二进制数表示,其中每一位分别表示线段与矩形上、下、左、右边界的交集情况。
例如,如果线段与矩形上边界有交集,则二进制数的第 0 位为 1,否则为 0。
根据线段的端点坐标和矩形区域的边界坐标,判断线段与矩形区域的相对位置关系,可以分为以下三种情况:
a. 线段完全在矩形区域内,不需要裁剪,直接保留。
b. 线段完全在矩形区域外,不需要裁剪,直接舍弃。
c. 线段部分在矩形区域内,部分在矩形区域外,需要进行裁剪。
4. 对于需要裁剪的线段,根据其与矩形边界的交点坐标,将线段裁剪成两部分,分别计算每部分与矩形区域的交集情况,并递归进行裁剪,直到所有线段都被处理完毕。
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(即都在可视范围内),则可以直接输出该线段;否则,执行下一步。
简述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直线段裁剪算法的实现。
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裁剪算法是一种简单且高效的线段裁剪算法,适用于二维和三维空间中的线段裁剪。
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页。
CohenSutherland
(b)直线段与窗口边界 (直线H, wyb和wyt平行的情况
( p k ≠ 0, k = 1,2)
类似地再分别计算umax和umin:
u max = max( 0, u k u min = min( u k
pk > 0 pk < 0
)
, 1)
若umax>umin,则直线段在窗口外,删除该直线。 若umax≤umin,将umax和umin代回直线参数方程,即求 出直线与窗口的两实交点坐标。
0101 1000 0000 1010 0010 0110
窗口
0100 D3D2D1D0
窗口及区域编码
(2)若code1&code2≠0,对 直线段可简弃之。
这是因为若code1和code2经按位与运算后的结果不 为0,说明两个端点同在窗口的上方、下方、左方或 右方。
(3)若上述两条件均不成立。则需求出直线段与窗 口边界的交点。在交点处把线段一分为二,其中必有 一段完全在窗口外,可以弃之。再对另一段重复进行 上述处理,直到该线段完全被舍弃或者找到位于窗口 内的一段线段为止。 实现时,一般按固定顺序检查直线段端点的编码位 是否为0。这里按左、右、下、上的顺序。与窗口边 界求交的顺序也可以任意选择,这里也按左(x=wxl )、右(x=wxr)、下(y=wyb)、上(y=wyt)的顺 序进行。 对于端点坐标为(x1,y1)和(x2,y2)的直线, 与左、右边界交点的y坐标可以这样计算:
于是有: u ⋅ p k ≤ q k 其中,k = 1,2,3,4。
首先分析pk=0的情况,若p1=p2=0,则直线与窗口边 界wxl和wxr平行。其中k对应于该裁剪边界(k=1,2 ,3,4对应于左、右、下、上边界)。 从右图中可以看出,若 满足 q1<0(直线A)或 q2<0 (直线F),则相应 的有x1<wxl或wxr<x1,这 样可以判断直线段在窗口 外,可删除。 若q1≥0 且q2≥0 (直线B ,C,D和E),则还需进一步 才能确定直线是否在窗口内 、外或相交。计算式如下:
计算机图形学Cohen-Sutherland直线裁剪算法源码c++
continue;
}
if(code1 & RIGHT)
{
//
ptset[i].y=int(k*(XR-ptset[i].x)+ptset[i].y+0.5);
ptset[i].x=XR;
continue;
}
if(code1 & TOP)///////特别注意if语句中的表达式越简单越好,否则很容易出现误差
{
// TODO: Add your command handler code here
CDC* pDC=GetDC();
CPen newpen(PS_SOLID,1,RGB(255,255,0));
CPen *old=pDC->SelectObject(&newpen);
//RedrawWindow();
//绘制N条直线段;
//pDC->MoveTo(ptset[i]);
//pDC->LineTo(ptset[i+1]);
int i=0;
while(i<N)
{
int code1=encode(ptset[i].x,ptset[i].y);
int code2=encode(ptset[i+1].x,ptset[i+1].y);
//pDC->MoveTo(ptset[i]);
// pDC->LineTo(ptset[i+1]);
}
float k=float(ptset[i+1].y-ptset[i].y)/float(ptset[i+1].x-ptset[i].x);
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验三图形裁剪算法1.实验目的:理解区域编码(Region Code,RC)设计Cohen-Sutherland直线裁剪算法编程实现Cohen-Sutherland直线裁剪算法2.实验描述:设置裁剪窗口坐标为:wxl=250;wxr=850;wyb=250;wyt=450;裁剪前如下图所示:裁剪后结果为:3.算法设计:Cohen-Sutherland 直线裁剪算法:假设裁剪窗口是标准矩形,由上(y=wyt)、下(y=wyb)、左(x=wxl)、右(x=wxr)四条边组成,如下图所示。
延长窗口四条边形成9个区域。
根据被裁剪直线的任一端点P(x,y)所处的窗口区域位置,可以赋予一组4位二进制区域码C4C3C2C1。
为了保证窗口内直线端点的编码为零,编码规则定义如下:第一位:若端点位于窗口之左侧,即x<wxl ,则C1=1,否则C1=0。
第二位:若端点位于窗口之右侧,即x>wxr,则C2=1,否则C2=0。
第三位:若端点位于窗口之下侧,即y<wyb,则C3=1,否则C3=0。
第四位:若端点位于窗口之上侧,即y>wyt,则C4=1,否则C4=0。
裁剪步骤:1. 若直线的两个端点的区域编码都为零,即RC1|RC2=0(二者按位相或的结果为零,即RC1=0 且RC2=0),说明直线两端点都在窗口内,应“简取”之。
2. 若直线的两个端点的区域编码都不为零,即RC1&RC2≠0(二者按位相与的结果不为零,即RC1≠0且RC2≠0,即直线位于窗外的同一侧,说明直线的两个端点都在窗口外,应“简弃”之。
3. 若直线既不满足“简取”也不满足“简弃”的条件,直线必然与窗口相交,需要计算直线与窗口边界的交点。
交点将直线分为两段,其中一段完全位于窗口外,可“简弃”之。
对另一段赋予交点处的区域编码,再次测试,再次求交,直至确定完全位于窗口内的直线段为止。
4. 实现时,一般按固定顺序左(x=wxl)、右(x=wxr)、下(y=wyb)、上(y=wyt)求解窗口与直线的交点。
4.源程序:1)//TestView.hclass CTestView : public CView{…….protected:double Pointx[2],Pointy[2];//用户绘制的直线int wxl,wxr,wyb,wyt;//左上与右下CDC Picture;//内存(预存)DC,防止屏幕闪烁char m_i; //第一个点还是第二个点BOOL m_Attatch;BOOL m_Draw;unsigned int RC,RC0,RC1;……..}2) //TestView.cpp#define ROUND(a) int(a+0.5)#define LEFT 1#define RIGHT 2#define BOTTOM 4#define TOP 8CTestView::CTestView(){//窗口位置坐标wxl=250;wxr=850;wyb=250;wyt=450;m_Attatch=FALSE;m_i=0;m_Draw=FALSE;RC0=0;RC1=0;}void CTestView::OnDraw(CDC* pDC){CTestDoc* pDoc = GetDocument();ASSERT_V ALID(pDoc);// TODO: add draw code for native data hereCRect Rect;GetClientRect(&Rect);//获得客户区的大小CBitmap Bitmap,*pBitmap;Bitmap.LoadBitmap(IDB_BITMAP1);CDC MemDC;MemDC.CreateCompatibleDC(GetDC());pBitmap=MemDC.SelectObject(&Bitmap);MemDC.BitBlt(0,0,Rect.Width(),Rect.Height(),&Picture,0,0,SRCCOPY);MemDC.TextOut((wxl+wxr)/2,wyb-20,"窗口");//窗口标题//绘制窗口和直线CPen Pen3,*pOldPen3;//定义3个像素宽度的画笔Pen3.CreatePen(PS_SOLID,3,RGB(0,0,0));pOldPen3=MemDC.SelectObject(&Pen3);MemDC.MoveTo(wxl,wyt);MemDC.LineTo(wxr,wyt);MemDC.LineTo(wxr,wyb);MemDC.LineTo(wxl,wyb);MemDC.LineTo(wxl,wyt);MemDC.SelectObject(pOldPen3);Pen3.DeleteObject();CPen Pen1,*pOldPen1;//定义1个像素宽度的画笔Pen1.CreatePen(PS_SOLID,1,RGB(0,255,255));pOldPen1=MemDC.SelectObject(&Pen1);if(m_i>=1){MemDC.MoveTo(ROUND(Pointx[0]),ROUND(Pointy[0]));MemDC.LineTo(ROUND(Pointx[1]),ROUND(Pointy[1]));}MemDC.SelectObject(pOldPen1);Pen1.DeleteObject();CDC *dc=GetDC();dc->BitBlt(0,0,Rect.Width(),Rect.Height(),&MemDC,0,0,SRCCOPY);MemDC.SelectObject(pBitmap);}void CTestView::OnMENUClip()//裁剪菜单函数{Cohen();Invalidate(FALSE);}unsigned int CTestView::EnCode(double LinePx,double LinePy)//端点编码函数{//顺序左右下上RC=0;if(LinePx<wxl){RC=RC | LEFT;}if(LinePx>wxr){RC=RC | RIGHT;}if(LinePy<wyb){RC=RC | BOTTOM;}if(LinePy>wyt){RC=RC | TOP;}return RC;}void CTestView::Cohen()//Cohen-Sutherland算法{BOOL Change;double x,y;RC0=EnCode(Pointx[0],Pointy[0]);RC1=EnCode(Pointx[1],Pointy[1]);while(TRUE){Change=FALSE;if(0 == (RC0|RC1)){//简取之return;}else if(0!=(RC0 & RC1)){//简弃之return;}else{if(0==RC0)//如果P0点在窗口内,交换P0和P1,保证p0点在窗口外{//交换点的坐标值double TPointx,TPointy;TPointx=Pointx[0];TPointy=Pointy[0];Pointx[0]=Pointx[1];Pointy[0]=Pointy[1];Pointx[1]=TPointx;Pointy[1]=TPointy;//交换点的编码值unsigned int TRC;TRC=RC0;RC0=RC1;RC1=TRC;}//按左、右、下、上的顺序裁剪if(RC0 & LEFT )//P0点位于窗口的左侧{x=wxl;//求交点yy=Pointy[0]+(Pointy[1]-Pointy[0])*(x-Pointx[0])/(Pointx[1]-Pointx[0]);Pointx[0]=x;Pointy[0]=y;Change=TRUE;RC0=EnCode(Pointx[0],Pointy[0]);RC1=EnCode(Pointx[1],Pointy[1]);}if(RC0 & RIGHT )//P0点位于窗口的右侧{x=wxr;//求交点yy=Pointy[0]+(Pointy[1]-Pointy[0])*(x-Pointx[0])/(Pointx[1]-Pointx[0]);Pointx[0]=x;Pointy[0]=y;Change=TRUE;RC0=EnCode(Pointx[0],Pointy[0]);RC1=EnCode(Pointx[1],Pointy[1]);}if(RC0 & BOTTOM )//P0点位于窗口的下侧{y=wyb;//求交点xx=Pointx[0]+(Pointx[1]-Pointx[0])*(y-Pointy[0])/(Pointy[1]-Pointy[0]);Pointx[0]=x;Pointy[0]=y;Change=TRUE;RC0=EnCode(Pointx[0],Pointy[0]);RC1=EnCode(Pointx[1],Pointy[1]);}if(RC0 & TOP )//P0点位于窗口的上侧{y=wyt;//求交点xx=Pointx[0]+(Pointx[1]-Pointx[0])*(y-Pointy[0])/(Pointy[1]-Pointy[0]);Pointx[0]=x;Pointy[0]=y;Change=TRUE;RC0=EnCode(Pointx[0],Pointy[0]);RC1=EnCode(Pointx[1],Pointy[1]);}if(FALSE==Change){return;}}}}void CTestView::OnMENUDrawLine()//绘制直线菜单函数{// TODO: Add your command handler code hereif(FALSE==m_Attatch){Picture.CreateCompatibleDC(GetDC());CBitmap *Bitmap,*pBitmap;Bitmap=new CBitmap;Bitmap->LoadBitmap(IDB_BITMAP1);pBitmap=Picture.SelectObject(Bitmap);m_Attatch=TRUE;}m_Draw=TRUE;m_i=0;Invalidate(FALSE);AfxGetMainWnd()->SetWindowText("Cohen-Sutherland直线裁剪算法");//显示标题MessageBox("请使用鼠标在屏幕上绘制直线,然后点击裁剪按钮进行裁剪","提示",MB_OKCANCEL);}void CTestView::OnLButtonDown(UINT nFlags, CPoint point) //单击鼠标左键函数{// TODO: Add your message handler code here and/or call defaultif(TRUE==m_Draw){if(m_i<2){Pointx[m_i]=point.x;Pointy[m_i]=point.y;m_i++;}}CView::OnLButtonDown(nFlags, point);}void CTestView::OnMouseMove(UINT nFlags, CPoint point) //鼠标移动函数{// TODO: Add your message handler code here and/or call defaultif(TRUE==m_Draw){if(m_i<2){Pointx[m_i]=point.x;Pointy[m_i]=point.y;Invalidate(FALSE);}}CView::OnMouseMove(nFlags, point);}5.运行结果:(屏幕截图)序号检查项目分值提交时间得分1 算法设计(40%)0-402 算法的程序实现(40%)0-403 运行结果(10%)0-104 实验报告规范性 (10%) 0-10成绩。