openGL - flood fill algorithm

illustrate

In fact, it can be BFS or DFS.

code

#include <GLUT/GLUT.h>
#include <iostream>
#include<iostream>
#include<cstdlib>
#include <queue>
using namespace std;
float wid = 400;         //设置窗口的大小,约定窗口必须为正方形
float height = wid;      //设置窗口的大小
int numbers = 20;       //设置划分的网格的个数
float t = wid/numbers; //模拟像素下的单位1
int con [41][41];
/*
 参数设置说明:
 输入直线的两点A(x1,y1);B(x2,y2)
 您应当确保参数范围在-400~400.且为20的倍数。
 这是因为我们的单位步长为20.
 *支持不同斜率
 *支持两点位置颠倒
 */
struct V {
    int x,y;
};
int x1 = 120,y1=80,x2 =300,y2 = 200;
int xx1 = 20,yy1=180,xx2 =300,yy2 = 200;
int xxx1 = 20,yyy1=180,xxx2 =120,yyy2 = 80;
void draw_point(float x, float y,int k_kind,int d_kind);
float translater(int x);
void swap(int &a, int &b)
{   int tmp = 0;
    tmp = b;
    b = a;
    a = tmp;  }
void bresenham(int x1, int y1,int x2, int y2){
    /*
     函数说明:bresenham算法部分
     参数说明:与openGL已有的划线函数一样,要求用户提供的是点的起点(x1,y1)和终点(x2,y2)
     为了便于观察,我们会绘制原像素下的直线。
     这里的坐标要求是-1 ~ 1
     */
    int k_kind = 0; //k_kind用来表示斜率的类型。0是0~1;1是1~无穷;2是0~-1;3是负无穷~-1
    int d_kind =0; //d_kind用来表示dy正负的类型。
    if (x1 > x2) {
        swap(x1,x2);
        swap(y1,y2);
    }
    int dx = abs(x2-x1), dy = abs(y2-y1);
    if (y1 > y2) {//如果是向下的
        y1 = -y1;
        y2 = -y2;
        d_kind = 1;
    }
    if (dy > dx) { //斜率介于1~无穷的,将看作坐标系变换(这里将坐标变换)。
        swap(x1, y1);
        swap(x2,y2);
        swap(dx,dy);
        k_kind = 1;
    }
    float d  = (dy +dy -dx)*t;     //令d为决策量(这里利用d = dx*w*2避免浮点运算)
    float x = x1+0.0,y = y1+0.0;
    draw_point(translater(x),translater(y),k_kind,d_kind); //绘制下一个点
    while( x < x2){             //以x为步长
        if (d < 0){
            d += 2*dy*t;
        }
        else{
            d += 2*(dy-dx)*t;
            y += t;    //说明应该画在上面那个位置
        }
        x= x  +  t;
        cout << "saa "<< (int)x/20 <<"-- " <<(int)y/20 <<endl;
        draw_point(translater(x),translater(y),k_kind,d_kind); //绘制下一个点
    }
}
float translater(int x){
    /*
     函数说明:将像素坐标下的坐标转化为openGL坐标
     参数说明:传入点像素坐标-wid-wid,返回-1~1坐标
     */
    return  x/wid;
}

void BFS_filling(){
    queue<V> vcon;
    V a;
    a.x =60;
    a.y = 160;
    vcon.push(a);
    while(!vcon.empty()){
        V temp  = vcon.front();
        vcon.pop();
        if (!con[temp.x/20][temp.y/20]) {
            con[temp.x/20][temp.y/20] =1;
            glPointSize(14);
            glColor3f(0.0,1.0,0.0);
            glBegin(GL_POINTS);
            glVertex3f(translater(temp.x),translater(temp.y),0.0);
            glEnd();
            glFlush();
            if (con[temp.x/20+1][temp.y/20]==0) {
                V a;
                a.x =temp.x+20;
                a.y = temp.y;
                vcon.push(a);
            }
            cout << temp.x/20 - 1<<"   " << temp.y/20<<endl;
            cout << con[temp.x/20-1][temp.y/20]<<endl;
            if ((temp.x/20-1 )>=0&&con[temp.x/20-1][temp.y/20]==0) {
                V a;
                a.x =temp.x-20;
                a.y = temp.y;
                vcon.push(a);
            }
            if (con[temp.x/20][temp.y/20+1]==0) {
                V a;
                a.x =temp.x;
                a.y = temp.y+20;
                vcon.push(a);
            }
            if (temp.y/20-1 >=0 &&con[temp.x/20][temp.y/20-1]==0) {
                V a;
                a.x =temp.x;
                a.y = temp.y-20;
                vcon.push(a);
            }
        }}}
void draw_point(float x , float y, int k_kind,int d_kind){
    /*
     函数说明:绘制像素的点,这里将点的大小设置为17
     颜色采用蓝色。
     参数说明:浮点数x,y是openGl坐标系。kind是指明斜率的类型
     */
    glPointSize(17);
    glColor3f(0.0,0.0,1.0);
    glBegin(GL_POINTS);
    cout <<"k:"<<k_kind<<"d:" << d_kind  << endl;
    if(k_kind==0&&d_kind==1){
        y = -y;
    }else if (k_kind ==1 &&d_kind==1){
        x= -x;
        swap(x,y);
    }else if (k_kind==1&&d_kind ==0){
        swap(x,y);
    }
    int xx = x*400/20;
    int yy = y*400/20;
    con[xx][yy]=1;
    glVertex3f(x,y,0.0);
    glEnd();
    glFlush();
}
void draw_line(int x1, int y1 ,int x2 , int y2){
    /*
     函数说明:绘制原直线
     */
    glBegin(GL_LINES);
    glColor3f(1.0,0.0,0.0);
    glVertex2f(translater(x1),translater(y1)); //定点坐标范围
    glVertex2f(translater(x2),translater(y2));
    glEnd();
    glFlush();
}
void grid(){
    /*
     函数说明:绘制网格为了便于将真实的像素pixel转化为我们模拟的像素
     */
    glClearColor(0, 0, 0, 0);//这是设置背景色,必须要在glclear之前调用
    glClear(GL_COLOR_BUFFER_BIT);
    //画直线
    int wid_number = numbers;
    int hei_number = numbers;
    float delta_wid = wid / wid_number;
    float delta_hei = height / hei_number;
    glColor3f(1.0,1.0,0);
    for (int i = 1; i < 40 ; i ++ ) {
        glBegin(GL_LINES);
        glVertex2f(-1+i*delta_hei/height, -1);
        glVertex2f(-1+i*delta_hei/height, 1);
        glVertex2f(-1,-1+i*delta_hei/height);
        glVertex2f(1,-1+i*delta_hei/height);
        glEnd();
        glFlush();
    }
    glColor3f(1.0,0,0);
    glBegin(GL_LINES);   //绘制坐标系,便于观察
    glVertex2f(-1,0);
    glVertex2f(1,0);
    glVertex2f(0,-1);
    glVertex2f(0,1);
    glEnd();
    glFlush();
    draw_line(x1, y1, x2, y2);
    draw_line(xx1, yy1, xx2, yy2);
    draw_line(xxx1, yyy1, xxx2, yyy2);
    //刷新缓冲,保证绘图命令能被执行
    bresenham(x1, y1,x2,y2);
    bresenham(xx1, yy1,xx2,yy2);
    bresenham(xxx1, yyy1,xxx2,yyy2);
    BFS_filling();
}
int main(int argc, char *argv[]) {
    for (int i = 0; i < 41; i++) {
        for (int j = 0; j< 41; j++) {
            con[i][j]  = 0;
        }
    }
    //初始化GLUT library
    glutInit(&argc, argv);
    //对窗口的大小进行初始化
    glutInitWindowSize(700,700);
    glutInitWindowPosition(300,200);
    // 设置窗口出现的位置
    //glutInitWindowPosition(int x, int y);
    glutInitDisplayMode(GLUT_RGBA);
    glutCreateWindow("class16_hw1");
    glutDisplayFunc(&grid);
    glutMainLoop();
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325723958&siteId=291194637