计算机图形学 实验四 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;
}
原文地址:https://www.cnblogs.com/PRCdefender/p/14606422.html