zoukankan      html  css  js  c++  java
  • 实验4 编码裁剪算法

     

    1.实验目的:

    了解二维图形裁剪的原理(点的裁剪、直线的裁剪、多边形的裁剪),利用VC+OpenGL实现直线的裁剪算法。

    2.实验内容:

    (1) 理解直线裁剪的原理(Cohen-Surtherland算法、梁友栋算法)

    (2) 利用VC+OpenGL实现直线的编码裁剪算法,在屏幕上用一个封闭矩形裁剪任意一条直线。

    (3) 调试、编译、修改程序。

    (4) 尝试实现梁友栋裁剪算法。

    3.实验原理:

    编码裁剪算法中,为了快速判断一条直线段与矩形窗口的位置关系,采用了如图A.4所示的空间划分和编码方案。

    clip_image002

    图A.4 裁剪编码

    裁剪一条线段时,先求出两端点所在的区号code1和code2,若code1 = 0且code2 = 0,则说明线段的两个端点均在窗口内,那么整条线段必在窗口内,应取之;若code1和code2经按位与运算的结果不为0,则说明两个端点同在窗口的上方、下方、左方或右方。这种情况下,对线段的处理是弃之。如果上述两种条件都不成立,则按第三种情况处理。求出线段与窗口某边的交点,在交点处把线段一分为二,其中必有一段完全在窗口外,可弃之,对另一段则重复上述处理。

    4.实验代码:

    #include <GL/glut.h>
    
    #include <stdio.h>
    
    #include <stdlib.h>
    
    #define LEFT_EDGE 1
    
    #define RIGHT_EDGE 2
    
    #define BOTTOM_EDGE 4
    
    #define TOP_EDGE 8
    
    void LineGL(int x0,int y0,int x1,int y1)
    
    {
    
    glBegin (GL_LINES);
    
    glColor3f (1.0f, 0.0f, 0.0f); glVertex2f (x0,y0);
    
    glColor3f (0.0f, 1.0f, 0.0f); glVertex2f (x1,y1);
    
    glEnd ();
    
    }
    
    struct Rectangle
    
    {
    
    float xmin,xmax,ymin,ymax;
    
    };
    
    Rectangle rect;
    
    int x0,y0,x1,y1;
    
    int CompCode(int x,int y,Rectangle rect)
    
    {
    
    int code=0x00;
    
    if(y<rect.ymin)
    
    code=code|4;
    
    if(y>rect.ymax)
    
    code=code|8;
    
    if(x>rect.xmax)
    
    code=code|2;
    
    if(x<rect.xmin)
    
    code=code|1;
    
    return code;
    
    }
    
    int cohensutherlandlineclip(Rectangle rect, int &x0,int & y0,int &x1,int &y1)
    
    {
    
    int accept,done;
    
    float x,y;
    
    accept=0;
    
    done=0;
    
    int code0,code1, codeout;
    
    code0 = CompCode(x0,y0,rect);
    
    code1 = CompCode(x1,y1,rect);
    
    do{
    
    if(!(code0 | code1))
    
    {
    
    accept=1;
    
    done=1;
    
    }
    
    else if(code0 & code1)
    
    done=1;
    
    else
    
    {
    
    if(code0!=0)
    
    codeout = code0;
    
    else
    
    codeout = code1;
    
    if(codeout&LEFT_EDGE){
    
    y=y0+(y1-y0)*(rect.xmin-x0)/(x1-x0);
    
    x=(float)rect.xmin;
    
    }
    
    else if(codeout&RIGHT_EDGE){
    
    y=y0+(y1-y0)*(rect.xmax-x0)/(x1-x0);
    
    x=(float)rect.xmax;
    
    }
    
    else if(codeout&BOTTOM_EDGE){
    
    x=x0+(x1-x0)*(rect.ymin-y0)/(y1-y0);
    
    y=(float)rect.ymin;
    
    }
    
    else if(codeout&TOP_EDGE){
    
    x=x0+(x1-x0)*(rect.ymax-y0)/(y1-y0);
    
    y=(float)rect.ymax;
    
    }
    
    if(codeout == code0)
    
    {
    
    x0=x;y0=y;
    
    code0 = CompCode(x0,y0,rect);
    
    }
    
    else
    
    {
    
    x1=x;y1=y;
    
    code1 = CompCode(x1,y1,rect);
    
    }
    
    }
    
    }while(!done);
    
    if(accept)
    
    LineGL(x0,y0,x1,y1);
    
    return accept;
    
    }
    
    void myDisplay()
    
    {
    
    glClear(GL_COLOR_BUFFER_BIT);
    
    glColor3f (1.0f, 0.0f, 0.0f);
    
    glRectf(rect.xmin,rect.ymin,rect.xmax,rect.ymax);
    
    LineGL(x0,y0,x1,y1);
    
    glFlush();
    
    }
    
    void Init()
    
    {
    
    glClearColor(0.0, 0.0, 0.0, 0.0);
    
    glShadeModel(GL_FLAT);
    
    rect.xmin=100;
    
    rect.xmax=300;
    
    rect.ymin=100;
    
    rect.ymax=300;
    
    x0 = 450,y0 = 0, x1 = 0, y1 = 450;
    
    printf("Press key 'c' to Clip!
    Press key 'r' to Restore!
    ");
    
    }
    
    void Reshape(int w, int h)
    
    {
    
    glViewport(0, 0, (GLsizei) w, (GLsizei) h);
    
    glMatrixMode(GL_PROJECTION);
    
    glLoadIdentity();
    
    gluOrtho2D(0.0, (GLdouble) w, 0.0, (GLdouble) h);
    
    }
    
    void keyboard(unsigned char key, int x, int y)
    
    {
    
    switch (key)
    
    {
    
    case 'c':
    
    cohensutherlandlineclip(rect, x0,y0,x1,y1);
    
    glutPostRedisplay();
    
    break;
    
    case 'r':
    
    Init();
    
    glutPostRedisplay();
    
    break;
    
    case 'x':
    
    exit(0);
    
    break;
    
    default:
    
    break;
    
    }
    
    }
    
    int main(int argc, char *argv[])
    
    {
    
    glutInit(&argc, argv);
    
    glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
    
    glutInitWindowPosition(100, 100);
    
    glutInitWindowSize(640, 480);
    
    glutCreateWindow("Hello World!");
    
    Init();
    
    glutDisplayFunc(myDisplay);
    
    glutReshapeFunc(Reshape);
    
    glutKeyboardFunc(keyboard);
    
    glutMainLoop();
    
    return 0;
    
    }
    

      附上本实验的VC++工程代码(VC++2008)

    5.实验提高

    请分别给出直线的三种不同位置情况,测试实验代码是否存在问题,有的话请调试改正。可能的话,可以尝试实现梁友栋裁剪算法。

  • 相关阅读:
    POJ3345 Bribing FIPA(树形DP)
    POJ3294 Life Forms(二分+后缀数组)
    ZOJ1027 Travelling Fee(DP+SPFA)
    POJ2955 Brackets(区间DP)
    POJ1655 Balancing Act(树的重心)
    POJ2774 Long Long Message(后缀数组)
    URAL1297 Palindrome(后缀数组)
    SPOJ705 SUBST1
    POJ3261 Milk Patterns(二分+后缀数组)
    POJ1743 Musical Theme(二分+后缀数组)
  • 原文地址:https://www.cnblogs.com/opengl/p/3789239.html
Copyright © 2011-2022 走看看