Cohen-Sutherland裁剪算法

来源:互联网 发布:js 弹幕特效 编辑:程序博客网 时间:2024/05/17 13:43

最近几天由于项目关系,接触到裁剪算法,今天算是真正把它其中一种最简单的Cohen-Sutherland实现了一下,算法原理很简单,我不想多讲,任何一本计算机图形学的书应该都会有涉及到该裁剪算法,我的参考书是《计算机图形学》(OpenGL版,第3版,清华大学出版社)下面直接把代码贴出来吧。

#define LEFT_EDGE 1  #define RIGHT_EDGE 2  #define BOTTOM_EDGE 4  #define TOP_EDGE 8   struct vertex {     float x;     float y; };vertex CP;float wxmax = 1.0, wxmin = -1.0, wymax = 1.0, wymin = -1.0;void MoveTo(GLfloat x, GLfloat y){    CP.x = x; CP.y = y;}void LineTo(GLfloat x, GLfloat y){    glBegin(GL_LINES);      glVertex2f(CP.x, CP.y);      glVertex2f(x, y);    glEnd();    glFlush();}int CompCode(GLfloat x, GLfloat y)//位置编码,原理上有9个位置,其实只要5个就可以了{    int code = 0x00;  //此处是二进制      if (y<wymin)        code = code | 4;    if (y>wymax)        code = code | 8;    if (x>wxmax)        code = code | 2;    if (x<wxmin)        code = code | 1;    return code;}void cohensutherlandlineclip(){    vertex p1,p2;    int accept = 0;    float x = 0.0, y = 0.0;    int code0, code1, codeout;    for (int i = 0; i < v.nedge; i++)//输入要裁剪的边    {        p1 = v.edge[0][i];        p2 = v.edge[1][i];        code0 = CompCode(p1.x, p1.y);        code1 = CompCode(p2.x, p2.y);        do{            if (!(code0 | code1))//全部显示(平凡接受)              {                accept = 1;                break;            }            if (code0 & code1)//完全不可见(平凡拒绝)            {                accept = 0;                break;            }            if (code0 != 0)//p1在窗口外面            {                codeout = code0;                if (codeout&LEFT_EDGE)//p1在窗口左边                {                    p1.y += (p2.y - p1.y)*(wxmin - p1.x) / (p2.x - p1.x);//左边界截断                    p1.x = wxmin;                }                else if (codeout&RIGHT_EDGE)                {                    p1.y += (p2.y - p1.y)*(wxmax - p1.x) / (p2.x - p1.x);                    p1.x = wxmax;                }                else if (codeout&BOTTOM_EDGE)                {                    p1.x += (p2.x - p1.x)*(wymin - p1.y) / (p2.y - p1.y);                    p1.y = wymin;                }                else if (codeout&TOP_EDGE)                {                    p1.x += (p2.x - p1.x)*(wymax - p1.y) / (p2.y - p1.y);                    p1.y = wymax;                }                code0 = CompCode(p1.x, p1.y);            }            else//p2在窗口外                {                codeout = code1;                if (codeout&LEFT_EDGE)                {                    p2.y += (p2.y - p1.y)*(wxmin-p2.x) / (p2.x - p1.x);                    p2.x = wxmin;                }                else if (codeout&RIGHT_EDGE)                {                    p2.y += (p2.y - p1.y)*(wxmax - p2.x) / (p2.x - p1.x);                    p2.x = wxmax;                }                else if (codeout&BOTTOM_EDGE)                {                    p2.x += (p2.x - p1.x)*(wymin - p2.y) / (p2.y - p1.y);                    p2.y = wymin;                }                else if (codeout&TOP_EDGE)                {                    p2.x += (p2.x - p1.x)*(wymax - p2.y) / (p2.y - p1.y);                    p2.y = wymax;                }                code1 = CompCode(p2.x, p2.y);            }        } while (1);//并非死循环,最多四次裁剪就可以跳出循环        if (accept)      //画出所有被平凡接受的线段          {            MoveTo(p1.x, p1.y);            LineTo(p2.x, p2.y);        }        else//舍弃所有被平凡拒绝的边        {            p1.x = 0.0; p1.y = 0.0; p2.x = 0.0; p2.y = 0.0;            MoveTo(p1.x, p1.y);            LineTo(p2.x, p2.y);        }    }}

裁剪效果
裁之前:
这里写图片描述

裁之后:
这里写图片描述

原创粉丝点击