• 计算机图形学5——Two-Dimensional Viewing and Clipping(二维线段裁剪算法)


    采用Cohen-Sutherland算法裁剪线段

    核心代码有:

    bool line_clipping(CPoint2D p1, CPoint2D p2, CRect *cw,
    				   CPoint2D *q1, CPoint2D *q2)
    // p1, p2: End points of input line segment
    // cw:	   Clipping rectangle
    // q1, q2: End points of output line segment
    // Return value: true --- accept, false --- reject
    {
    	GLubyte code1,code2;
    	GLint done=false,poltLine=false;
    	GLfloat m;
    	while(!done)
        {
            code1=encode(p1,cw);//起点
            code2=encode(p2,cw);//终点
            if(accept(code1,code2))
            {
                done=true;
                poltLine=true;
            }
            else if(reject(code1,code2))
            {
                done=true;
            }
            else
            {
                if(inside(code1))//return GLint(!code);起点为0000,则交换起点和终点
                {
                    swapPts(&p1,&p2);
                    swapCodes(&code1,&code2);
                }
                if(p2.x!=p1.x)//斜率存在,便求斜率
                    m=(p2.y-p1.y)/(p2.x-p1.x);//这里之前打错字了,导致显示不全
    
                //从右向左检查R1(起点且为外端点)
                if(code1&left){
                    p1.y+=(cw->xmin-p1.x)*m;
                    p1.x=cw->xmin;
                }
                else if(code1&right)
                {
                    p1.y+=(cw->xmax-p1.x)*m;
                    p1.x=cw->xmax;
                }
                else if(code1&bottom)
                {
                    if(p2.x!=p1.x)
                        p1.x+=(cw->ymin-p1.y)/m;
                    p1.y=cw->ymin;
                }
                else if(code1&top)
                {
                    if(p2.x!=p1.x)
                        p1.x+=(cw->ymax-p1.y)/m;
                    p1.y=cw->ymax;
                }
            }
        }
        *q1=p1;
        *q2=p2;
        return poltLine;
    }
    

    完整代码如下:

    // ====== Computer Graphics Experiment #6 ======
    // |   Two-Dimensional Viewing and Clipping    |
    // =============================================
    //
    // Requirement:
    // (1) Implement Cohen-Sutherland line clipping algorithm.
    // (2) Change position and size of window and viewport
    //     and observe the effects.
    
    #include <windows.h>
    #include <GL/glut.h>
    #include <math.h>
    
    // 2D point class
    class CPoint2D
    {
    public:
    	float x, y;
    };
    
    // Rectangle class
    class CRect
    {
    public:
    	float xmin, ymin, xmax, ymax;
    
    	float width(void)  { return xmax-xmin; }
    	float height(void) { return ymax-ymin; }
    
    	// Make (xmin, ymin) the lower left corner
    	void normalize(void);
    
    	// Draw the rectangle
    	void draw(GLenum mode);
    
    };
    
    void CRect::normalize(void)
    {
    	float ftemp;
    	if (xmin > xmax)
    		{ftemp=xmin; xmin=xmax; xmax=ftemp;}
    	if (ymin > ymax)
    		{ftemp=ymin; ymin=ymax; ymax=ftemp;}
    }
    
    void CRect::draw(GLenum mode)
    {
    	glBegin(mode);
    	glVertex2f(xmin, ymin);
    	glVertex2f(xmax, ymin);
    	glVertex2f(xmax, ymax);
    	glVertex2f(xmin, ymax);
    	glEnd();
    }
    
    #define PI 3.14159265359
    
    int running_state=0;
    // 0 --- Normal state.
    // 1 --- Rubber-band state.
    
    // Size of the scene
    float scene_size=1000.0;
    
    CRect clip_rect;	// Clipping rectangle
    CRect window;	// Window
    CRect viewport;		// Viewport
    
    // Program window size
    int pw_width, pw_height;
    
    // Set window
    void set_window(CRect *cw)
    {
    	glMatrixMode(GL_PROJECTION);
    	glLoadIdentity();
    	gluOrtho2D (cw->xmin, cw->xmax, cw->ymin, cw->ymax);
    }
    
    // Set viewport
    void set_viewport(CRect *vp)
    {
    	glViewport(vp->xmin, vp->ymin,
    		vp->width(), vp->height());
    }
    
    const GLint left=0x1;
    const GLint right=0x2;
    const GLint bottom=0x4;
    const GLint top=0x8;
    
    
    GLint inside(GLint code)
    {
        return GLint(!code);
    }
    GLint reject(GLint code1,GLint code2)
    {
        return GLint(code1&code2);
    }
    GLint accept(GLint code1,GLint code2)
    {
        return GLint(!(code1|code2));
    }
    GLubyte encode(CPoint2D pt,CRect *cw1)/////////////////
    {
        GLubyte code=0x00;
        if(pt.x<cw1->xmin)
            code=code|left;
        if(pt.x>cw1->xmax)
            code=code|right;
        if(pt.y<cw1->ymin)
            code=code|bottom;
        if(pt.y>cw1->ymax)
            code=code|top;
        return(code);
    }
    
    void swapPts(CPoint2D *p1,CPoint2D *p2)
    {
        CPoint2D temp;
        temp=*p1;*p1=*p2;*p2=temp;
    }
    
    void swapCodes(GLubyte *p1,GLubyte*p2)
    {
        GLubyte temp;
        temp=*p1;*p1=*p2;*p2=temp;
    }
    // Cohen-Sutherland line clipping algorithm.
    bool line_clipping(CPoint2D p1, CPoint2D p2, CRect *cw,
    				   CPoint2D *q1, CPoint2D *q2)
    // p1, p2: End points of input line segment
    // cw:	   Clipping rectangle
    // q1, q2: End points of output line segment
    // Return value: true --- accept, false --- reject
    {
    	GLubyte code1,code2;
    	GLint done=false,poltLine=false;
    	GLfloat m;
    	while(!done)
        {
            code1=encode(p1,cw);//起点
            code2=encode(p2,cw);//终点
            if(accept(code1,code2))
            {
                done=true;
                poltLine=true;
            }
            else if(reject(code1,code2))
            {
                done=true;
            }
            else
            {
                if(inside(code1))//return GLint(!code);起点为0000,则交换起点和终点
                {
                    swapPts(&p1,&p2);
                    swapCodes(&code1,&code2);
                }
                if(p2.x!=p1.x)//斜率存在,便求斜率
                    m=(p2.y-p1.y)/(p2.x-p1.x);//这里之前打错字了,导致显示不全
    
                //从右向左检查R1(起点且为外端点)
                if(code1&left){
                    p1.y+=(cw->xmin-p1.x)*m;
                    p1.x=cw->xmin;
                }
                else if(code1&right)
                {
                    p1.y+=(cw->xmax-p1.x)*m;
                    p1.x=cw->xmax;
                }
                else if(code1&bottom)
                {
                    if(p2.x!=p1.x)
                        p1.x+=(cw->ymin-p1.y)/m;
                    p1.y=cw->ymin;
                }
                else if(code1&top)
                {
                    if(p2.x!=p1.x)
                        p1.x+=(cw->ymax-p1.y)/m;
                    p1.y=cw->ymax;
                }
            }
        }
        *q1=p1;
        *q2=p2;
        return poltLine;
    }
    
    //Translate the clip rectangle
    void Translaterect(int dx,int dy)
    {
        clip_rect.xmin+=dx;
        clip_rect.xmax+=dx;
        clip_rect.ymin+=dy;
        clip_rect.ymax+=dy;
    }
    
    // Initialization function
    void init(void)
    {
    	glClearColor (0.0, 0.0, 0.0, 0.0);
    	glEnable(GL_LINE_STIPPLE);
    }
    
    // Display callback function
    void display(void)
    {
    	int i;
    	CPoint2D p1, p2, q1, q2;
    	double a, r;
    
    	glClear (GL_COLOR_BUFFER_BIT);
    
    	// Draw blue rectangle to fill the background
    	glColor3f(0.0, 0.0, 0.5);
    	window.draw(GL_POLYGON);
    
    	// Draw unclipped lines in green color
    	p1.x=0.0; p1.y=0.0;
    	r=0.5*scene_size;
    	glLineStipple(1, 0x0f0f);
    	glColor3f(0.0, 1.0, 0.0);
    	glBegin(GL_LINES);
    	for (i=0; i<360; i+=15)
    	{
    		a=(double)i/180.0*PI;
    		p2.x=r*cos(a);
    		p2.y=r*sin(a);
    		if (i==0 || i==180) p2.y=0;
    		if (i==90 || i==270) p2.x=0;
    		p2.x+=p1.x;
    		p2.y+=p1.y;
    		glVertex2f(p1.x, p1.y);
    		glVertex2f(p2.x, p2.y);
    	}
    	glEnd();
    	glLineStipple(1, 0xffff);
    
    	// Draw clipped lines in white color
    	if (running_state == 0) {
    	glColor3f(1.0, 1.0, 1.0);
    	glLineWidth(2.0);
    	glBegin(GL_LINES);
    	for (i=0; i<360; i+=15)
    	{
    		a=(double)i/180.0*PI;
    		p2.x=r*cos(a);
    		p2.y=r*sin(a);
    		if (i==0 || i==180) p2.y=0;
    		if (i==90 || i==270) p2.x=0;
    		p2.x+=p1.x;
    		p2.y+=p1.y;
    		if(line_clipping(p1, p2, &clip_rect, &q1, &q2))
    		{
    			glVertex2f(q1.x, q1.y);
    			glVertex2f(q2.x, q2.y);
    		}
    	}
    	glEnd();
    	glLineWidth(1.0);
    	}
    
    	// Draw clipping rectangle
    	glLineStipple(1, 0x0f0f);
    	glColor3f(1.0, 1.0, 0.0);
    	clip_rect.draw(GL_LINE_LOOP);
    	glLineStipple(1, 0xffff);
    
    	glutSwapBuffers();
    }
    
    // Reshape callback function
    
    void reshape(int w, int h)
    {
    	// Store program window size
    	pw_width=w;
    	pw_height=h;
    
    	// set viewport
    	viewport.xmin=0;
    	viewport.xmax=w;
    	viewport.ymin=0;
    	viewport.ymax=h;
    	set_viewport(&viewport);
    
    	// set clipping window
    	window.xmin=-0.6*scene_size;
    	window.xmax=0.6*scene_size;
    	window.ymin=-0.6*scene_size;
    	window.ymax=0.6*scene_size;
    	set_window(&window);
    
    	// set clipping rectangle
    	clip_rect.xmin=0.5*window.xmin;
        clip_rect.xmax=0.5*window.xmax;
    	clip_rect.ymin=0.5*window.ymin;
        clip_rect.ymax=0.5*window.ymax;
    }
    
    // Keyboard callback function
    void keyboard(unsigned char key, int x, int y)
    {
    	switch (key) {
    		case 27:
    			exit(0);
    	}
    }
    
    // Special keyboard callback function
    void special_key(int key, int x, int y)
    {
    	switch (key) {
          case GLUT_KEY_LEFT:
                Translaterect(-5,0);
                glutPostRedisplay();
                break;
          case GLUT_KEY_RIGHT:
                Translaterect(5.0,0.0);
                glutPostRedisplay();
                break;
          case GLUT_KEY_DOWN:
                Translaterect(0.0,-5.0);
                glutPostRedisplay();
                break;
          case GLUT_KEY_UP:
                Translaterect(0.0,5.0);
                glutPostRedisplay();
                break;
    	}
    }
    
    // Main program entrance
    int main(int argc, char* argv[])
    {
    	glutInit(&argc, argv);
    	glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE);
    	glutInitWindowSize(500, 500);
    	glutCreateWindow("Test 2D Clippig and Viewing");
    	init();
    	glutReshapeFunc(reshape);
    	glutKeyboardFunc(keyboard);
    	glutSpecialFunc(special_key);
    	glutDisplayFunc(display);
    	glutMainLoop();
    	return 0;
    }
    
    

    在这里插入图片描述

    考虑到我修改出这篇文章的代码花了不少时间,
    应该算是原创的一种了
    (っ °Д °;)っ

  • 相关阅读:
    百度地图学习
    JS中call和apply区别有哪些 记录
    初次学习AngularJS
    C#中Abstract和Virtua笔记,知识
    css学习笔记四
    css学习笔记三
    jquery基础 笔记三
    jquery基础 笔记二
    jquery基础 笔记一
    负边距在布局中的应用
  • 原文地址:https://www.cnblogs.com/vivid-victory/p/10090459.html
Copyright © 2020-2023  润新知