OpenGL Cohen-Sutherland端点编码算法实现线段的裁剪

OpenGL Cohen-Sutherland端点编码算法实现线段的裁剪

题目描述

利用Cohen-Sutherland端点编码算法编程实现任意线段的裁剪,用不同颜色表示

问题分析

首先明确一下什么是Cohen-Sutherland端点编码算法
之后把区域画清楚,算法实现就完事了

Cohen-Sutherland端点编码算法

OpenGL Cohen-Sutherland端点编码算法实现线段的裁剪
根据编码判断点的位置,进而实现裁剪。
从线段两端逐步收缩,以编码边界为判断的节点,直到收缩到中心的裁剪区域。
这里给个参考博客,可以认真学一学原理和思想:

http://supportopensource.iteye.com/blog/678480

编程实现

环境

  • Win10
  • Clion
  • freeglut

代码

#include <GL/glut.h>
#include <math.h>
#define PI 3.14159
#define XL 200
#define XR 400
#define YU 400
#define YD 200

void init()
{
    // 设置背景色为白色 不透明度为0
    glClearColor(1.0, 1.0, 1.0, 0.0);
    // 初始化
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    // 设定投射画图的空间范围gluOrtho2D()以及glOrtho()等等
    // 这里决定后边用比例值画图还是整数值画图
    gluOrtho2D(0.0, 600, 0.0, 600);
    glClear(GL_COLOR_BUFFER_BIT);
}

void gl_Point(int x,int  y){
    glPointSize(5);
    glBegin(GL_POINTS);
    glVertex2i(x,y);
    glEnd();
    glFlush();
}

void circle(double x, double y)
{
    int n =150;
    double R = 15;
    glColor3i(1,1,1);
    for(int i=0;i<150;i++)
    {
        gl_Point(x+R*cos(2*PI*i/n),y+R*sin(2*PI*i/n));
    }
}

// DDA算法画直线
void DDA(int x1,int y1,int x2,int y2){
    int k,i;
    float x,y,dx,dy;
    k = abs(x2-x1);
    if(abs(y2-y1)>k)
        k = abs(y2-y1);
    //直线被划分为每一小段的长度
    dx = float(x2-x1)/k;
    dy = float(y2-y1)/k;
    x = float(x1);
    y = float(y1);
    for(i = 0;i<k;i++){
        gl_Point(int(x+0.5),int(y+0.5));
        x = x+dx;
        y = y+dy;
    }
}

// 编码
int makecode(double x,double y)
{
    int c = 0;
    if (x<XL) c = 1;
    else if (x>XR) c = 2;
    if (y<YD) c = c + 4;
    else if (y>YU) c = c + 8;
    return c;
}

// 裁剪
void Cohen_Sutherland(double x0, double y0, double x2, double y2)
{
    int c, c0, c1;
    double x, y;
    c0 = makecode(x0,y0);
    c1 = makecode(x2,y2);
    while(c0 != 0 || c1 != 0)
    {
        if ((c0 & c1) != 0 ) break ;
        c = c0;
        if (c == 0) c = c1;
        if ((c & 1) == 1){
            y = y0 + (y2 - y0) * (XL - x0) / (x2 - x0);
            x= XL;
        }
        else if ((c & 2) == 2) {
            y = y0 + (y2 - y0) * (XR - x0) / (x2 - x0);
            x = XR;
        }
        else if ((c & 4) == 4) {
            x = x0 + (x2 - x0) * (YD - y0) / (y2 - y0);
            y = YD;
        }
        else if ((c & 8) == 8) {
            x = x0 + (x2 - x0) * (YU - y0) / (y2 - y0);
            y = YU;
        }
        circle(x,y);
        if(c==c0){
            x0 = x;
            y0 = y;
            c0 = makecode(x, y);
        }
        else {
            x2 = x;
            y2 = y;
            c1 = makecode(x, y);
        }

    }
    glColor3f(0.0, 1.0, 0.0);
    DDA(x0, y0, x2, y2);
}

void display()
{
    int x0=50, y0=110, x1=500, y1=560;
    glColor3f(1.0, 0.0, 0.0);
    DDA(x0,y0,x1,y1);

    glColor3f(0.0, 0.0, 0.0);
    DDA(XL,0,XL,600);
    DDA(XR,0,XR,600);
    DDA(0,YD,600,YD);
    DDA(0,YU,600,YU);

    Cohen_Sutherland(x0,y0,x1,y1);

}

int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
    glutInitWindowPosition(0, 0);
    glutInitWindowSize(600, 600);
    glutCreateWindow("2");
    init();
    glutDisplayFunc(display);
    glutMainLoop();
    return 0;
}

编程中间的坑

看好上述代码中的Cohen_Sutherland函数

void Cohen_Sutherland(double x0, double y0, double x2, double y2)
{
int c, c0, c1;
    double x, y;
    c0 = makecode(x0,y0);
    c1 = makecode(x2,y2);
    while(c0 != 0 || c1 != 0)
    {
        if ((c0 & c1) != 0 ) break ;
...
}

最后一行的AND运算,加好里面的括号,不开玩笑,鄙人被按住摩擦了1个小时。

实现效果

OpenGL Cohen-Sutherland端点编码算法实现线段的裁剪