SDL2高效画实心圆的算法(一)

文章目录

一、数学基础

  1. 圆的公式: x 2 + y 2 = r 2 x^2+y^2=r^2 x2+y2=r2

  2. 设原点是圆心, ( x 0 , y 0 ) (x_0,y_0) (x0,y0)是圆上的点,则其关于圆心中心对称的点为 ( − x 0 , − y 0 ) (-x_0,-y_0) (−x0,−y0)同样也是圆上的点,同样点 ( x 0 , − y 0 ) (x_0,-y_0) (x0,−y0)、 ( − x 0 , y 0 ) (-x_0,y_0) (−x0,y0),点 ( y 0 , x 0 ) (y_0,x_0) (y0,x0)、 ( − y 0 , − x 0 ) (-y_0,-x_0) (−y0,−x0),点 ( y 0 , − x 0 ) (y_0,-x_0) (y0,−x0)、 ( − y 0 , x 0 ) (-y_0,x_0) (−y0,x0),也是圆上中心对称的点。通过中心对称的点两两连线,我们能够得到4条直径,且它们是轴对称的。

  3. 微分和无穷小思想,考虑0~ π / 4 \pi/4 π/4角度范围内,在此范围圆上的点满足 y ≤ x y\le x y≤x

    • 角度0附近 :在圆上的点 ( x 0 , y 0 ) (x_0,y_0) (x0,y0)基础上考虑下一点 ( x 1 , y 1 ) (x_1,y_1) (x1,y1),让 y 1 = y 0 + d x y_1=y_0+dx y1=y0+dx,假设 r > > 1 r>>1 r>>1,则可以规定 d x = 1 dx=1 dx=1,即 y 1 = y 0 + 1 y_1=y_0+1 y1=y0+1,如果x值不变,即现在看点 ( x 0 , y 1 ) (x_0,y_1) (x0,y1)在哪?我们代入圆公式看一下:
      x 0 2 + y 1 2 = x 0 2 + y 0 2 + 2 y 0 + 1 x_0^2+y_1^2=x_0^2+y_0^2+2y_0+1 x02+y12=x02+y02+2y0+1
      ∵ y 0 → 0 ,且 r > > 1 \because y_0\to 0,且r>>1 ∵y0→0,且r>>1
      ∴ x 0 2 + y 1 2 → r 2 \therefore x_0^2+y_1^2 \to r^2 ∴x02+y12→r2
      即在X轴附近, ( x 0 , y 0 + 1 ) . . . ( x 0 , y 0 + n ) (x_0,y_0+1)...(x_0,y_0+n) (x0,y0+1)...(x0,y0+n)可以近似看成圆上的点。
    • 角度 π / 4 \pi/4 π/4附近 :设点 ( x n , y n ) (x_n,y_n) (xn,yn)在圆上,仍让 y n + 1 y_n+1 yn+1,代入圆公式:
      x n 2 + ( y n + 1 ) 2 = x n 2 + y n 2 + 2 y n + 1 x_n^2+(y_n+1)^2=x_n^2+y_n^2+2y_n+1 xn2+(yn+1)2=xn2+yn2+2yn+1
      此时 y n y_n yn相对于r已不是无穷小,不能忽略了,这说明点 ( x n , y n + 1 ) (x_n,y_n+1) (xn,yn+1)在圆外。
      现在我们看一下点 ( x n − 1 , y n + 1 ) (x_n-1,y_n+1) (xn−1,yn+1),代入,
      ( x n − 1 ) 2 + ( y n + 1 ) 2 = x n 2 + y n 2 + 2 ( y n − x n ) + 2 = x n 2 + y n 2 + ( 2 y n + 1 ) − ( 2 x n − 1 ) (x_n-1)^2+(y_n+1)^2=x_n^2+y_n^2+2(y_n-x_n)+2=x_n^2+y_n^2+(2y_n+1)-(2x_n-1) (xn−1)2+(yn+1)2=xn2+yn2+2(yn−xn)+2=xn2+yn2+(2yn+1)−(2xn−1)
      ∵ π / 4 附近 x n ≈ y n \because \pi/4附近x_n \approx y_n ∵π/4附近xn≈yn
      ∴ ( x n − 1 ) 2 + ( y n + 1 ) 2 → r 2 \therefore (x_n-1)^2+(y_n+1)^2 \to r^2 ∴(xn−1)2+(yn+1)2→r2
      即在 π / 4 \pi/4 π/4轴附近, ( x n − 1 , y n + 1 ) . . ( x n − 1 , y n + m ) (x_n-1,y_n+1)..(x_n-1,y_n+m) (xn−1,yn+1)..(xn−1,yn+m)可以近似看成圆上的点,且有的在圆内部。

二、编程设计

设 e r r = 0 err = 0 err=0,在 0 ∼ π / 4 范围内 0\sim \pi/4范围内 0∼π/4范围内,当我们画完圆上的点 ( x , y ) (x,y) (x,y)后,令 e r r = e r r + 2 y + 1 err=err+2y+1 err=err+2y+1,此时 e r r > 0 err>0 err>0. 再令 x = x − 1 , e r r = e r r − ( 2 x − 1 ) x=x-1, err=err-(2x-1) x=x−1,err=err−(2x−1),此时 e r r < 0 err \lt 0 err<0,我们再依次画出 ( x − 1 , y + 1 ) 、 ( x − 1 , y + 2 ) . . . ( x − 1 , y + m ) (x-1,y+1)、(x-1,y+2)...(x-1,y+m) (x−1,y+1)、(x−1,y+2)...(x−1,y+m),同时不断做 e r r = e r r + 2 y + 1 err=err+2y+1 err=err+2y+1,直到 e r r < 0 err \lt 0 err<0,于是我们就可以得到一系列圆内附近的点。通过过圆心画直径,就可以画出实心圆来。

c 复制代码
void SDL_RenderFillCircle( SDL_Renderer* render, int x0, int y0, int radius, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
    SDL_SetRenderDrawColor(render, r, g, b, a);
    int x = radius;
    int y = 0;
    int err = 0;
    while (x >= y)
    {
        SDL_RenderDrawLine(render, x0 + x, y0 + y, x0 - x, y0 - y);
        SDL_RenderDrawLine(render, x0 + y, y0 + x, x0 - y, y0 - x);
        SDL_RenderDrawLine(render, x0 + x, y0 - y, x0 - x, y0 + y);
        SDL_RenderDrawLine(render, x0 + y, y0 - x, x0 - y, y0 + x);
        y += 1;
        err += (y << 1) + 1;
        if (err > 0)
        {
            x -= 1;
            err -= (x << 1) + 1;
        }
    }
}
c 复制代码
int main(int, char**){
    // 初始化SDL显示图像功能
    if (SDL_Init(SDL_INIT_VIDEO)) {
        cerr << "SDL could not initialize! SDL_Error:" << SDL_GetError() << endl;
        return 1;
    }
    // 初始化图片加载功能
    if (!IMG_Init(IMG_INIT_PNG)) { //初始化IMG组件失败
        cerr << "SDL_image could not initialize! SDL_image Error:" << IMG_GetError() << endl;
        IMG_Quit();
        return 1;
    }
    // 初始化窗口
    SDL_Window* window = SDL_CreateWindow("蚁群模拟", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 600, 600, SDL_WINDOW_SHOWN);
    if (window == NULL) { //初始化窗口失败
        cerr << "Window could not be created! SDL_Error:" << SDL_GetError() << endl;
        IMG_Quit();
        SDL_Quit();
        return 1;
    }
    // 构建窗口渲染容器
    SDL_Renderer* rend = SDL_CreateRenderer(window, -1, 0);
    if (!rend) {
        cerr << "Unable to render! SDL_Render Error:" << SDL_GetError() << endl;
        SDL_DestroyWindow(window);
        IMG_Quit();
        SDL_Quit();
        return 1;
    }
    //初始化渲染器
    SDL_SetRenderDrawColor(rend, 255, 255, 255, 255); //白色
    SDL_RenderClear(rend);
    
    SDL_RenderFillCircle(rend, 300, 300, 250, 0, 0, 0, 255); //黑色圆
    SDL_RenderPresent(rend);
    system("pause");

    SDL_DestroyRenderer(rend);
    SDL_DestroyWindow(window);
    IMG_Quit();
    SDL_Quit();
    return 0;
}

结果如图:

三、算法优缺点

优点 :没有平方、开根等计算,计算机运算代价小。
缺点:仅仅是近似圆,且在轴的附近线更密,不能做到均匀绘制。

相关推荐
cheems95272 小时前
[算法手记] 动态规划,二叉树计数问题
算法·动态规划
贫民窟的勇敢爷们2 小时前
Scikit-learn算法:从入门到精通的机器学习工具箱
算法·机器学习·scikit-learn
Liangwei Lin3 小时前
LeetCode 155. 最小栈
java·javascript·算法
~|Bernard|3 小时前
二.go语言中map的底层原理(2026-5-8)
算法·golang·哈希算法
AbandonForce3 小时前
哈希表(HashTable,散列表)个人理解
开发语言·数据结构·c++·散列表
mask哥3 小时前
力扣算法java实现汇总整理(下)
java·算法·leetcode
样例过了就是过了4 小时前
LeetCode热题100 编辑距离
数据结构·c++·算法·leetcode·动态规划
z200509304 小时前
C++中位图和布隆过滤器的一些面试题
开发语言·c++
wearegogog1234 小时前
MATLAB椭圆参数检测算法实现
数据库·算法·matlab