基於 Bresenham 算法畫填充圓

五子棋裏那個畫圓的函數一直欠缺沒有完成。算法

最開始的想法是根據 x * x + y * y = r *r 函數

由三角函數計算各點的座標,而後依次點出全部點:code

// 畫空心圓弧(效率很低)
// 參數: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 算法,但是看不懂!!數學

只能照葫蘆畫瓢,抄過來了!class

// 基於 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 也同樣實現。——本身用點畫線就行。配置

相關文章
相關標籤/搜索