2017-02-19 613 views
1

我想逐行画出圆圈(例如顺时针方向),从圆圈中心逐个像素地画圆圈。但避免重新绘制像素(这很慢)。在C++中从中心绘制实心圆圈?

想象一下,这就像每个回合只更新一次的“雷达”。

没有内存可容纳所有填充像素的阵列(以前的最大线条点),也不需要GPU或高层库(通过函数DrawPoint(x,y)绘制)。

我具备的功能画线和点:

void DrawLineFromCenterXYToAngle(int centerX, int centerY, float angle) 
{ 
.... instead of angle it is possible to find points of the circle and iterate it 
.... find line points by Bresenham's line algorithm 
{ 
    DrawPoint(int x, int y); 
} 
} 

void DrawPoint(int x, int y) 
{ 
    PixelDraw_Slow(x,y)=GetColor_VerySlow(x,y); 
} 

现在我重复的角度和速度很慢了,因为在中心的像素重绘多次的循环。并需要优化。

如果这使得它更快,形状可能不是完美的圆形。

+0

你必须使用一些库,因为标准'C++'没有GUI的概念。由于我们不知道您使用的是什么库,因此我们很难提供帮助。 – drescherjm

+1

也许你应该展示你如何迭代,这样我们可以帮助你实现。 – drescherjm

+0

这是单片机rutine它没有帮助。例如空隙Adafruit_GFX_AS ::的drawLine(int16_t X0,Y0 int16_t, \t \t \t int16_t X1,Y1 int16_t, \t \t \t uint16_t颜色){ int16_t陡= ABS(Y1 - Y0)> ABS(X1 - X0); (陡峭)交换(x0,y0);交换(x0,y0);交换(x0,y0);交换(x0,y0) swap(x1,y1); } if(x0> x1)swap(x0,x1); swap(y0,y1); } int16_t dx,dy; dx = x1-x0; dy = abs(y1-y0); int16_t err = dx/2; int16_t ystep; if(y0 user1329019

回答

0

有Bresenham绘图算法的圆圈。

Example with code

int r = 200, ymax, x, y, yp, xp, d; 
ymax = r/sqrt(2); 
x = r; /* start at the bottom of the first octant */ 
/* d measures whether the midpoint of two pixel locations 
is inside or outside the ideal circle. positive means outside */ 
d = -1*r; /* to be precise, this should be r^2 - (r - 0.5)^2 */ 
xp = r; yp = -1; /* these hold the old values across iterations */ 
for(y=0; y<=ymax; y++) { 
    plot_8_ways(x,y); 
    if (d > 0) { /* midpoint is outside circle, go NW */ 
    x--; 
    d += (2*yp - 2*xp + 3); 
    } 
    else { /* midpoint is inside circle, go N */ 
    d += (2*yp + 1); 
    } 
    yp = y; 
    xp = x; 
} 
0

没有RAM来容纳所有填充的像素(最大前一行点)和无GPU或高电平库阵列(由函数DrawPoint(X,Y)绘图) 。

如果你可以存储一行点,那么你有足够的内存来跟踪所有填充像素,如果你有效地表示它。

假设您的雷达扫描从12点钟或6点钟位置开始(顺时针或逆时针扫描无关紧要),则在渲染圆圈的任何时候,垂直线只会与填充像素块相交一次(即输入一次并退出一次)。因此,只需通过为每列像素存储垂直最小和最大填充像素y坐标,就可以跟踪它们。如果您从3点或9点位置开始,那么您可以存储每行的最小和最大x。

你可以只用一对数组做到这一点:

int minY[X_RANGE]; 
int maxY[X_RANGE]; 

X_RANGE是像素的列的最大数量。这只需要和你的圆圈一样大,而不是整个屏幕,因为你可以根据圆边界框左边的X来抵消它。同样,Y_RANGE是最大行数。

当你开始渲染,初始化数组来表示空列:

void InitColumnArrays() 
{ 
    for(int x = 0; x < X_RANGE; x++) 
    { 
     minY[x] = Y_RANGE - 1; 
     maxY[x] = 0; 
    } 
} 

然后,当你呈现一个像素,只是检查是否已经通过检查阵列呈现:

void DrawPointCheckingRanges(int x, int y) 
{ 
    // TODO: range check values 

    // check if point has already been drawn and draw it and extend ranges if not: 
    if((y < minY[x]) || (y > maxY[x])) 
    { 
     DrawPoint(x + offsetX, y + offsetX); 
     if(y < minY[x]) 
      minY[x] = y; 
     if(y > maxY[x]) 
      maxY[x] = y; 
    } 
} 

offsetX和offsetY是如上所述的可选偏移量。

您可以将其与Bresenham圈绘图算法结合使用,从而有效地为您的线条提供端点。

上面的代码假定DrawPoint比这些边界检查和数组读写操作要慢。