边界填充错误地停止了递归吗?

ejk8hzay  于 2022-10-18  发布在  其他
关注(0)|答案(1)|浏览(162)

我一直试图在我的M1Mac上执行一个简单的边界填充程序,使用的是我安装的Visual Studio代码,包括所有配置默认构建任务的库,构建工作完成得很好。
但问题是,当窗口可见时,程序有一个鼠标单击事件侦听器,单击它应该会开始使用所需的颜色填充区域,但似乎在只绘制了一条线后停止。
这是我的节目,


# include<stdio.h>

# include <GLUT/glut.h>

int xmin, ymin, xmax, ymax; //Polygon boundaries

float FillColor[3] = {1.0, 0.0, 0.0};  //Color to be filled - red
float BorderColor[3] = {0.0, 0.0, 0.0};  // Border color of polygon - black

void setPixel(int x, int y)
{
    glBegin(GL_POINTS);
        glColor3fv(FillColor);
        glVertex2i(x, y);
    glEnd();
    glFlush();
}
void display()
{
    glClear(GL_COLOR_BUFFER_BIT);

    //Drawing polygon
    glColor3fv(BorderColor);
    glLineWidth(6);
    glBegin(GL_LINES);
        glVertex2i(xmin, ymin);
        glVertex2i(xmin, ymax);
    glEnd();
    glBegin(GL_LINES);
        glVertex2i(xmax, ymin);
        glVertex2i(xmax, ymax);
    glEnd();
    glBegin(GL_LINES);
        glVertex2i(xmin, ymin);
        glVertex2i(xmax, ymin);
    glEnd();
    glBegin(GL_LINES);
        glVertex2i(xmin, ymax);
        glVertex2i(xmax, ymax);
    glEnd();
    glFlush();
}
void BoundaryFill(int x,int y)
{
    float CurrentColor[3];
    glReadPixels(x, y, 1.0, 1.0, GL_RGB, GL_FLOAT, CurrentColor);

    // if CurrentColor != BorderColor and CurrentColor != FillColor
    if((CurrentColor[0] != BorderColor[0] && (CurrentColor[1]) != BorderColor[1] &&
       (CurrentColor[2])!= BorderColor[2]) && (CurrentColor[0] != FillColor[0] &&
       (CurrentColor[1]) != FillColor[1] && (CurrentColor[2]) != FillColor[2]))
    {
        setPixel(x, y);
        BoundaryFill(x+1, y);
        BoundaryFill(x-1, y);
        BoundaryFill(x, y+1);
        BoundaryFill(x, y-1);
        //Using 4-connected approach, remove comment from below lines to make it 8-connected approach
        BoundaryFill(x+1, y+1);
        BoundaryFill(x+1, y-1);
        BoundaryFill(x-1, y+1);
        BoundaryFill(x-1, y-1);
    }
}
void mouse(int btn, int state, int x, int y)
{
    if(btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
    {
        printf("%d, %d\n", x, y);
        BoundaryFill(x, 500-y);
    }
}

void init()
{
    glClearColor(0.101, 1.0, 0.980, 1.0); //Background color - cyan
    glMatrixMode(GL_PROJECTION);
    gluOrtho2D(0, 500, 0, 500);
}
int main(int argc, char**argv)
{
    printf("Window size - 500x500 i.e. range of x and y is 0 -> 500\n");
    printf("\nEnter polygon boundaries:-\n");
    printf("Enter xmin: ");
    scanf("%d", &xmin);
    printf("Enter ymin: ");
    scanf("%d", &ymin);
    printf("Enter xmax: ");
    scanf("%d", &xmax);
    printf("Enter ymax: ");
    scanf("%d", &ymax);

    glutInit(&argc, argv);
    glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(500, 500);
    glutCreateWindow("Boundary-Fill Algorithm");

    init();
    glutDisplayFunc(display);
    glutMouseFunc(mouse);
    glutMainLoop();
    return 0;
}

Please check the image -- where after this stage, the recursion stops which meant to be filling more pixels in 8 connected approach.

pgky5nke

pgky5nke1#

正交投影覆盖的面积为[0,500]^2像素,而算法假设的面积为[0,500)^2像素。请注意包含范围和排除范围之间的差异。这可能会导致glReadPixels读取其预期读取位置左侧(和/或下方)的像素值,从而破坏算法。要解决此问题,请为glOrtho2D使用不同的尺寸:

gluOrtho2D(0, 499, 0, 499);

另外,glReadPixels的宽度和高度参数应该是整数,即:

glReadPixels(x, y, 1, 1, GL_RGB, GL_FLOAT, CurrentColor);

而且直接比较浮点值并不是一个好主意(参见StackOverflow的其他部分)。取而代之的是使用如下内容:


# include <math.h>

int isEqualFloat(float x, float y)
{
    return fabs(x - y) < 0.001F;
}

我假设glReadPixels在这里的用法是为了教育目的。一种更好的方法是存储“已访问”像素的布尔矩阵,这样就不需要比较浮点值中的颜色和从GPU内存中检索数据。
最后,使用最新的Mac电脑可能会产生影响。对于一些低分辨率的程序,操作系统决定重复每个像素,以避免窗口太小。然而,这实际上会在OpenGL不知情的情况下将分辨率提高一倍。

相关问题