zoukankan      html  css  js  c++  java
  • 计算机图形学 实验四 AET算法

    实验四:多边形的扫描转换与填充(实在是懒得贴SCAN了,SCAN不但没技术含量而且还死麻烦。代码太长了。所以就只贴AET了。)

    实验目的: 了解多边形的表示方式,区域填充基本原理,掌握多边形的扫描转换算法

    基本要求:

     给定有序点对表示的多边形

     实现 x 扫描线填充

     实现改进的 x 扫描线填充(使用活性边表结构)

    实现:

    使用方法:右键开启菜单,点击AET,鼠标左键点击开始描点。完成后按回车键。如果想重新画可重复此步骤。

    #define EXIT_SUCCESS 0
    #include<stdio.h>
    #include <stdlib.h>
    #include<GL/glut.h>
    #include<math.h>
    #include<queue>
    #include<vector>
    #include<algorithm>
    #include "cross.h"
    #include<iostream>
    using  namespace std;
    // later Edition
    int MODE = 0;           // 模式代码:0-DAA算法,1-Bresenham算法,2-中点圆算法
    bool mouseLeftDown;     // 实时记录鼠标左键状态
    bool mouseRightDown;    // 实时记录鼠标左键状态
    float mouseX, mouseY;   // 实时记录鼠标位置,与下一次鼠标位置之间形成微分
    bool status = false;    // 标记当前是否为规划状态
    int startX=0, startY=0, endX=0, endY=0;
    int start[2] = { 0 };
    int end[2] = { 0 };
    float red=1.0,green=1.0, blue=0.0;
    float PI = 3.415926535;
    
    Point sp, previous, now;
    bool start_pass = false;
    // 纯粹的交点模式,简单的交点判别法
    vector<pair<Point,Point> > q;// 存储边集,在编辑中存储需要的数据
    vector<vector<edge> > NET(501);
    vector<vector<edge> > AET(501);// 活性边 
    // 数据结构上,对于求交,需要以下几个数据结构
    // 1.存储所有边,然后存储边的所有交集。对于边的所有交集,目前可以按照一个简单的有序队列的方式进行。
    vector<vector<int> > t(501);// 存储所有扫描线与各个边的交点。
    
    ostream& operator<<(ostream& output,const Point& p) {
        cout <<"("<< p.x << "," << p.y << ")";
        return output;
    }
    
    void polygon() {
        for (int i = 1;i <= 500;i++) {
            AET[i].clear();
            NET[i].clear();
        }
        // now intialize the NET
        for (int i = 0;i < q.size();i++) {                    // NNNNNNNNNNEEEEEEEEEEEETTTTTTTTTTTT
            //cout<<q[i].first<<q[i].second<<endl;
            edge v((q[i].first.y > q[i].second.y) ? q[i].second.x : q[i].first.x,
                1.0 * (q[i].first.x - q[i].second.x) / (q[i].first.y - q[i].second.y),
                max(q[i].first.y, q[i].second.y));
            //cout<<v;
             // 然后将边插入到第一次出现的扫描线处,也就是说第一次的ymin的扫描线处。 
            NET[min(q[i].first.y, q[i].second.y)].push_back(v);
        }// 循环结束后,所有的边都已经进入了NET
        // 接下来将会进行正式的作画
        
        for (int i = 1;i <= 500;i++) {                        // AAAAAAAAAAAEEEEEEEEEEEETTTTTTTTTT
            vector<int> temp;
            for (int a = 1;a <= 500;a++) {
                for (int b = 0;b < AET[a].size();b++) {
                    temp.push_back(AET[a][b].start);
                }
            }
            sort(temp.begin(), temp.begin() + temp.size());
            sort(NET[i].begin(), NET[i].end());// 提前排序不需要再进行插入排序 
            for (int j = 0;j < NET[i].size();j++) {
                AET[i].push_back(NET[i][j]);// 插入排序法将节点插入AET完成
            }
            glColor3d(red, green, blue);
            glPointSize(1.0);
            glBegin(GL_POINTS);
            for (int l = 0;l < temp.size();l += 2) {
                for (int o = temp[l];o <= temp[l + 1];o++) {
                    //cout << "draw(" << i << "," << o << ")、";
                    glVertex2d(o, i);
                }
            }
            //if (temp.size())cout << endl;
            glEnd();
    
            for (int a = 1;a <= 500;a++) {
                for (int b = 0;b < AET[a].size();b++) {
                    if (AET[a][b].ymax == i) {
                        AET[a].erase(AET[a].begin() + b);
                    }
                    else
                        if (AET[a][b].ymax > i) {
                            AET[a][b].start += AET[a][b].dx;
                        }
                }
            }
        }
    }
    
    int arr[500][500];
    
    void init(void)
    {
        //glClearColor(0.0, 0.0, 0.0, 0.0);/* select clearing color  */   // 设置背景颜色为黑色
        //glMatrixMode(GL_MODELVIEW);                   
        glClearColor(0.0, 0.0, 0.0, 0.0); /* white background */
        glColor3f(1.0, 0.0, 0.0); /* draw in red */
    
        /* set up viewing: */
        /* 500 x 500 window with origin lower left */
    
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluOrtho2D(0.0, 500.0, 0.0, 500.0);
        glMatrixMode(GL_MODELVIEW);
    }
    
    
    
    
    #define RED 1233
    #define BLUE 1234
    #define GREEN 1235
    #define WHITE 12366
    #define YELLOW 12367
    #define SCAN_LINE 12368
    #define AET 12369
    void processMenuEvents(int option) {
        //option,就是传递过来的value的值。
        switch (option) {
        case RED:
            red = 1.0;
            green = 0.0;
            blue = 0.0; break;
        case GREEN:
            red = 0.0;
            green = 1.0;
            blue = 0.0; break;
        case BLUE:
            red = 0.0;
            green = 0.0;
            blue = 1.0; break;
        case WHITE:
            red = 1.0;
            green = 1.0;
            blue = 1.0; break;
        case YELLOW:
            red = 1.0;
            green = 1.0;
            blue = 0.0;break;
        case SCAN_LINE:
            for (int i = 1;i <= 500;i++)t[i].clear();
            q.clear(); 
            sp.x = 0;
            glutPostRedisplay();
            status = true;
            MODE = 0;break;
        case AET:
            MODE = 1;break;
        }
    }
    void createGLUTMenus() {
    
        int menu;
    
        // 创建菜单并告诉GLUT,processMenuEvents处理菜单事件。
        menu = glutCreateMenu(processMenuEvents);
    
        //给菜单增加条目
        glutAddMenuEntry("红色", RED);
        glutAddMenuEntry("蓝色", BLUE);
        glutAddMenuEntry("绿色", GREEN);
        glutAddMenuEntry("白色", WHITE);
        glutAddMenuEntry("黄色", YELLOW);
        glutAddMenuEntry("AET", SCAN_LINE);
    
        // 把菜单和鼠标右键关联起来。
        glutAttachMenu(GLUT_RIGHT_BUTTON);
    }
    
    
    void display(void)
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glColor3f(1-red, 1-green,1- blue);
        glLoadIdentity();
    
        
        glPointSize(5.0);
        glBegin(GL_POINTS);
    
        if (status == true) {
    
            if(sp.x)glVertex2i(sp.x, sp.y);
            for (int i = 0;i < q.size();i++) {
                glVertex2i(q[i].second.x, q[i].second.y);
            }
        }
            
        glEnd();
    
        glColor3f(red, green, blue);
        if(!status)polygon();
        // Draw here
        
        
        glutSwapBuffers();
    }
    int saveStack = 0;
    void keyboard(unsigned char key, int x, int y)
    
    {
        switch (key) {
            case 'q':case 'Q':
                exit(EXIT_SUCCESS);
                break;
            case 13:
                //for (int i = 1;i <= 500;i++)t[i].clear();
                //q.clear();
                
                if (start_pass == true&&status==true) {
                    pair<Point, Point> v(now, sp);
                    q.push_back(v);
                    cout << "??" << now << sp << "?" << endl;
                    // just initiate the graphic or just simply put the graphic drawing operation into the display function
                    start_pass = false;
                }
    
                status = false;
                
                cout << "should display" << endl;
                glutPostRedisplay();
                break;
            case 'r':case 'R':
                for (int i = 1;i <= 500;i++)t[i].clear();
                q.clear();
                glutPostRedisplay();
                break;
        }
    }
    int ww, hh;
    
    void mouse_process(int button, int state, int x, int y)
    {
        mouseX = x;
        mouseY = y;
        printf("<%d,%d>
    ", x, y);
        cout << "===============" << endl;
        for (int i = 0;i < q.size();i++) {
            cout << q[i].first <<"-"<< q[i].second << endl;
        }
    
    
        hh = glutGet(GLUT_WINDOW_HEIGHT);
        if (button == GLUT_LEFT_BUTTON)
        {
            if (state == GLUT_DOWN)
            {
                
                if (!mouseLeftDown) {
                    startX = x;startY = hh-y;
                } 
                now = Point(x, hh-y);
                if(status)
                if (previous == now);
                else {
                    if (start_pass == false) {
                        start_pass = true;
                        sp = now;
                        previous = now;
                    }
                    else {
                        pair<Point, Point> v(previous, now);
                        previous = now;
                        q.push_back(v);
                    }
                }
                glutPostRedisplay();
               
                
                mouseLeftDown = true;
            }
            else if (state == GLUT_UP) {
                mouseLeftDown = false;
       
            }
                
        }
    
        else if (button == GLUT_RIGHT_BUTTON)
        {
            if (state == GLUT_DOWN)
            {
                mouseRightDown = true;
            }
            else if (state == GLUT_UP)
                mouseRightDown = false;
        }
    
    
        
    }
    
    void mouse_process_active(int x, int y)
    {
        if (mouseLeftDown){
            endX = x;endY = hh - y;
            glutPostRedisplay();
        }
        if(mouseRightDown)
        {
    
        }
        glutPostRedisplay();
    
    }
    void mouse_process_passtive(int x, int y) {}
    
    
    int main(int argc, char** argv)
    {
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
        glutInitWindowSize(500, 500);
        glutCreateWindow(" 右键开启菜单");
    
        init();
    
        Point a(40, 40), b(150, 60), c(100, 100), d(10, 70);
        pair<Point, Point> v1(a, b), v2(b, c), v3(c, d), v4(d, a);
        q.push_back(v1);q.push_back(v2);q.push_back(v3);q.push_back(v4);
     
        glutDisplayFunc(display);
        
        // later Edition
        glutMouseFunc(mouse_process);
        glutMotionFunc(mouse_process_active);
        glutPassiveMotionFunc(mouse_process_passtive);
        createGLUTMenus();
        glutKeyboardFunc(keyboard);
        glutMainLoop();
    
        return 0;
    }
  • 相关阅读:
    领会一些比较巧妙的算法
    操作系统os常识
    C++中的继承与虚函数各种概念
    我学shell程序的记录
    matlab:linux环境中将m文件编译成动态链接库
    struct内存对齐:gcc与VC的差别
    fedora中丢失或损坏fstab,无法启动,如何补救
    判断一个字符串中的字符是否都在另一个中出现
    linux下的不错的小软件:apvlv,zathura和vifm
    C语言中将结构体写入文件
  • 原文地址:https://www.cnblogs.com/PRCdefender/p/14606422.html
Copyright © 2011-2022 走看看