基于 Bresenham 算法画填充圆

五子棋里那个画圆的函数一直欠缺没有完成。

最开始的想法是根据 x * x + y * y = r *r 

由三角函数计算各点的坐标,然后依次点出所有点:

// 画空心圆弧(效率很低)
// 参数:x,y = 圆心坐标;r = 内圆半径;R = 外圆半径;a = 起始弧度;A = 终止弧度(弧度为逆时针方向)
void FillCircle(SDL_Renderer *pRen, int x, int y, int r, int R, int a, int A)
{
    const int FINE = 10;        // 精细程度
    double f;
    int i, j;
    _Bool point[2 * R][2 * R];  // 包含圆的最大正方形的所有点

    memset(point, 0, sizeof(point));

    // 计算点
    for(i = r; i <= R; i++)
    {
        for(j = FINE*a; j <= FINE*A; j++)
        {
            f = 3.14159265359 * j / (FINE * 180);
            point[(int)(R + i * cosf(f))][(int)(R - i * sinf(f))] = 1;
        }
    }

    // 画点
    for(i = 0; i < 2 * R; i++)
    {
        for(j = 0; j < 2 * R; j++)
        {
            if(point[i][j])
            {
                SDL_RenderDrawPoint(pRen, x - R + i, y - R + j);
            }
        }
    }
}

 但是由于用到了两次双层循环,循环里还涉及 sin 和 cos 运算,效率非常低!FINE 取值 5 的时候只能画小圆,大了就好多空白。FINE 取 10 的时候,我的电脑配置 E3v3 + 12G 内存都感觉到卡了,FINE 取 100 的时候,直接卡到渣!


上网搜索了下,发现有高效的 Bresenham 算法,可是看不懂!!

只能照葫芦画瓢,抄过来了!

// 基于 Bresenham 算法画填充圆
// 参数:x,y = 圆心坐标;r = 半径
// 备注:如果没有画线函数,就直接用 for 循环画点线
void FillCircle_Bresenham(SDL_Renderer *pRen, int x, int y, int r)
{
    int tx = 0, ty = r, d = 3 - 2 * r;

    while(tx < ty)
    {
        // 小于 45 度横线
        SDL_RenderDrawLine(pRen, x - ty, y - tx, x + ty, y - tx);
        if(tx != 0) // 防止水平线重复绘制
        {
            SDL_RenderDrawLine(pRen, x - ty, y + tx, x + ty, y + tx);
        }

        if(d < 0)   // 取上面的点
        {
            d += 4 * tx + 6;
        }
        else        // 取下面的点
        {
            // 大于 45 度横线
            SDL_RenderDrawLine(pRen, x - tx, y - ty, x + tx, y - ty);
            SDL_RenderDrawLine(pRen, x - tx, y + ty, x + tx, y + ty);
            d += 4 * (tx - ty) + 10;
            ty--;
        }
        tx++;
    }

    if(tx == ty)    // 45 度横线
    {
        SDL_RenderDrawLine(pRen, x - ty, y - tx, x + ty, y - tx);
        SDL_RenderDrawLine(pRen, x - ty, y + tx, x + ty, y + tx);
    }
}

效率倒是高了好多,可是这段代码我看不懂!数学没学好啊!

用的 SDL 的画线函数,实际上用任何能画线的 API 都行。甚至没有画线的 API,有画点的 API 也一样实现。——自己用点画线就行。

转载于:https://my.oschina.net/u/580100/blog/617398

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值