C++ 如何使用中点圆算法删除SDL中绘制的圆中的这些间隙?

C++ 如何使用中点圆算法删除SDL中绘制的圆中的这些间隙?,c++,graphics,geometry,sdl,sdl-2,C++,Graphics,Geometry,Sdl,Sdl 2,我正在尝试创建一个相当简单的游戏,主要涉及使用SDL2绘制圆圈。我发现SDL缺少一个内置的方法来为SDL_渲染器绘制圆,但是在搜索一个方法后,我发现了有用的答案,其中的细节是使用中点圆算法来完成的。因为我想要一个填充圆,所以我编写了一个相当简单的函数,它只需要画很多稍微小一些的圆,就可以得到一个填充圆的外观。不幸的是,这导致绘制带有间隙的圆,这些间隙在圆上形成一种“X”图案,如图所示: 这是我的绘制空心圆功能: void-draw\u-hollow\u-circle(SDL\u渲染器*渲染器,i

我正在尝试创建一个相当简单的游戏,主要涉及使用SDL2绘制圆圈。我发现SDL缺少一个内置的方法来为SDL_渲染器绘制圆,但是在搜索一个方法后,我发现了有用的答案,其中的细节是使用中点圆算法来完成的。因为我想要一个填充圆,所以我编写了一个相当简单的函数,它只需要画很多稍微小一些的圆,就可以得到一个填充圆的外观。不幸的是,这导致绘制带有间隙的圆,这些间隙在圆上形成一种“X”图案,如图所示: 这是我的
绘制空心圆
功能:

void-draw\u-hollow\u-circle(SDL\u渲染器*渲染器,int-centerx,int-centery,int-radius)
{
//用给定的位置和半径绘制一个空心圆
常数int直径=(半径*2);
int x=半径-1;
int y=0;
int-tx=1;
int-ty=1;
int error=tx-直径;
而(x>=y)
{
//每个渲染一个圆的八分之一
SDL_渲染绘制点(渲染器,centerx+x,centery+y);
SDL_渲染绘制点(渲染器,centerx+x,centery-y);
SDL_渲染绘制点(渲染器,centerx-x,centery+y);
SDL_渲染绘制点(渲染器,centerx-x,centery-y);
SDL_渲染绘制点(渲染器,centerx+y,centery-x);
SDL_渲染绘制点(渲染器,centerx+y,centery+x);
SDL_渲染绘制点(渲染器,centerx-y,centery-x);
SDL_渲染绘制点(渲染器,centerx-y,centery+x);
如果(错误0)
{
--x;
tx+=2;
误差+=(tx-直径);
}
}
}
这是我的
画圈
功能:

void draw_circle(SDL_渲染器*渲染器,int x,int y,int radius,int r,int g,int b)
{
//使用给定的位置、半径和颜色绘制填充圆
SDL_SetRenderDrawColor(渲染器、r、g、b、SDL_ALPHA_不透明);
//画许多稍小的空心圆,给人一个填充圆的印象
而(半径>=0)
{
绘制空心圆(渲染器,x,y,半径);
--半径;
}
}

现在,这很烦人,我想要一种方法来避免这种差距,只得到一个纯红色的圆圈,但不幸的是,我没有找到任何方法来这样做。我尝试了一种不同的方法,包括绘制从圆心到边缘的许多半径,但这导致了类似的问题,尽管间隙的位置略有不同。任何类型的答案都可以,无论是更适合填充圆的算法,还是代码数学中的错误等等。

这些漏洞都是舍入错误的产物。精确定位每个点将使用实数(比如浮点),但像素坐标必须是整数,因此舍入。是的,由于类似的原因绘制对角线时会出现类似的瑕疵。只有水平线、垂直线、坡度为+1的线和坡度为+1的线可以在不进行某种舍入的情况下绘制−一,

填充圆的一个简单方法是绘制矩形而不是点。
draw\u hollow\u circle
中循环的每次迭代都会绘制八个点。前四个是一个矩形的角,而后四个形成另一个矩形。试着画这两个矩形而不是八个点。(不再需要在半径上迭代。)


(由于许多点会被多次绘制,因此请坚持使用完全不透明的颜色。这会影响部分透明度。)

您可以使用水平线或垂直线连接圆周长上的点,以实现填充圆。这不会像@JaMit所描述的方法那样产生重叠,因此应该可以进行混合:

void fill_circle(SDL_Renderer *renderer, int centerX, int centerY, int radius) {
    const int diameter = (radius * 2);

    int x = (radius - 1);
    int y = 0;
    int tx = 1;
    int ty = 1;
    int error = (tx - diameter);

    while (x >= y)
    {

        // top
        SDL_RenderDrawLine(renderer, centerX - y, centerY - x, centerX + y, centerY - x);

        // top-center piece
        SDL_RenderDrawLine(renderer, centerX - x, centerY - y, centerX + x, centerY - y);

        // lower-center piece
        SDL_RenderDrawLine(renderer, centerX - x, centerY + y, centerX + x, centerY + y);

        // lower piece
        SDL_RenderDrawLine(renderer, centerX - y, centerY + x, centerX + y, centerY + x);

        if (error <= 0)
        {
            ++y;
            error += ty;
            ty += 2;
        }

        if (error > 0)
        {
            --x;
            tx += 2;
            error += (tx - diameter);
        }
    }
}
void fill_圆(SDL_渲染器*渲染器,int centerX,int centerY,int radius){
常数int直径=(半径*2);
int x=(半径-1);
int y=0;
int-tx=1;
int-ty=1;
int误差=(tx-直径);
而(x>=y)
{
//顶
SDL_渲染绘制线(渲染器,centerX-y,centerY-x,centerX+y,centerY-x);
//顶部中心件
SDL_渲染绘制线(渲染器,centerX-x,centerY-y,centerX+x,centerY-y);
//下中心件
SDL_渲染绘制线(渲染器,centerX-x,centerY+y,centerX+x,centerY+y);
//下片
SDL_渲染绘制线(渲染器,centerX-y、centerY+x、centerX+y、centerY+x);
如果(错误0)
{
--x;
tx+=2;
误差+=(tx-直径);
}
}
}
可以逐个注释绘制线语句以查看效果