文章目录
一、数学基础
-
圆的公式: x 2 + y 2 = r 2 x^2+y^2=r^2 x2+y2=r2
-
设原点是圆心, ( 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条直径,且它们是轴对称的。

-
微分和无穷小思想,考虑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)可以近似看成圆上的点,且有的在圆内部。
- 角度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)在哪?我们代入圆公式看一下:
二、编程设计
设 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;
}
结果如图:

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