1. 程式人生 > >OPENGL—編碼裁剪(Cohen-Sutherland)法裁剪圖

OPENGL—編碼裁剪(Cohen-Sutherland)法裁剪圖

//編碼裁剪(Cohen-Sutherland)法裁剪圖
#include"stdafx.h"
#include<Gl/glut.h>
#include <process.h>

class wcPt2D {
public:
    float x, y;
};

const int winLeftBitCode = 0x1;
const int winRightBitCode = 0x2;
const int winBottomBitCode = 0x4;
const int winTopBitCode = 0x8;

GLubyte encode(wcPt2D pt, wcPt2D winMin, wcPt2D winMax) {    //進行編碼
    GLubyte code = 0x00;
    if (pt.x < winMin.x)        //D0=1,否則為0
		code = code | winLeftBitCode;
    if (pt.x > winMax.x)        //D1=1,否則為0
		code = code | winRightBitCode;
    if (pt.y < winMin.y)        //D2=1,否則為0
		code = code | winBottomBitCode;
    if (pt.y > winMax.y)        //D3=1,否則為0
		code = code | winTopBitCode;
    return (code);
}

inline int inside(int code) {               //在內部,inside=1
    return int(!code);
}

inline int reject(int code1, int code2) {   //code1&code2不等於0,“簡棄”,reject=true
    return int(code1 & code2);
}

inline int accept(int code1, int code2) {   //code1|code2等於0,“簡取”,accept=true
    return int(!(code1 | code2));
}

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 lineClip(wcPt2D winMin, wcPt2D winMax, wcPt2D p1, wcPt2D p2)    //裁剪
{
    GLubyte code1, code2;
    int done = false, plotLine = false;
    float m;
    while (!done)                       //保證用新的P1P2重新進行計算
	{
        code1 = encode(p1, winMin, winMax);   //對p1、p2進行編碼,分別為code1、code2
        code2 = encode(p2, winMin, winMax);
        if (accept(code1, code2))		//對直線P1P2“簡取”之
		{
            done = true;
            plotLine = true;
        } 
		else if (reject(code1, code2)) //對直線P1P2“簡棄”之
		{
            done = true;
        } 
		else                           //否則
		{
            if (inside(code1))         //若P1在視窗內,則交換P1和P2的座標值和編碼
			{
                swapPts(&p1, &p2);
                swapCodes(&code1, &code2);
            }

			//判斷P1在視窗外哪一側,然後求出兩者的交點,並用交點的值替代P1的座標值,以達到去掉P1S線段的目的
            if (p2.x != p1.x) 
				m = (p2.y - p1.y) / (p2.x - p1.x);
            if (code1 & winLeftBitCode) 
			{
                p1.y += (winMin.x - p1.x) * m;
                p1.x = winMin.x;
            }
			else if (code1 & winRightBitCode) 
			{
                p1.y += (winMax.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;
            }
        }
    }
	//重新繪製當前的直線段P1P2
    if (plotLine)
        glBegin(GL_LINES);
    glColor3f(1, 0, 0);
    glVertex2f(p1.x, p1.y);
    glVertex2f(p2.x, p2.y);
    glEnd();
}

void drawpolygon(double cd[]) 
{
    glBegin(GL_LINE_LOOP);    //繪製直線
    glLineWidth(10);
    for (int i = 0; i < 8; i = i + 2) {
        glVertex2f(cd[i], cd[i + 1]);
    }
    glEnd();
}

void drawline(double cd[]) 
{
    glBegin(GL_LINES);      //繪製點
    glLineWidth(10);
    for (int i = 0; i < 8; i = i + 2) {
        glVertex2f(cd[i], cd[i + 1]);
    }
    glEnd();
}

void myKeyBoard(unsigned char key, int x, int y) //處理按鍵資訊
{   
    wcPt2D winMin = {200, 200};
    wcPt2D winMax = {400, 400};
    wcPt2D p1 = {100, 0};
    wcPt2D p2 = {500, 500};

    if (key == 13)   //按下Enter鍵
        lineClip(winMin, winMax, p1, p2);

    glFlush();
    if (key == 27)   //按下ESC鍵
        exit(0);
}

void display(void) 
{
    double re[8] = {200, 200, 400, 200, 400, 400, 200, 400};   //按照比例輸出
    double line[4] = {100,0 , 500, 500};
 
    glClear(GL_COLOR_BUFFER_BIT);
	glViewport(0, 0, 600, 600);
    glColor3f(0, 0, 0);
	//繪製
    drawpolygon(re);
    drawline(line);
 
    glFlush();
}

int main(int argc, char **argv) 
{
	//初始化
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RED);
    glutInitWindowSize(600, 600);
    glutInitWindowPosition(100, 100);
    glutCreateWindow("Cohen-Sutherland演算法");
    glClearColor(1, 1, 1, 0.0);
    glMatrixMode(GL_PROJECTION);
    gluOrtho2D(0.0, 600.0, 0.0, 600.0);

    glutKeyboardFunc(myKeyBoard);   //鍵盤輸入控制
    glutDisplayFunc(display);

    glutMainLoop();
    return 0;

}

執行結果: