圆形厚度绘图算法

目前我正在使用Bresenham的圆绘制算法,它可以精确地绘制圆圈,但是我想要一种相对快速有效的方法来绘制具有指定厚度的圆(因为Bresenham的方法只绘制单个像素厚度)。 我意识到我可以简单地绘制具有不同半径的多个圆圈,但我相信这将是非常低效的(并且效率很重要因为这将在Arduino上运行,其中每微秒都是珍贵的)。 我目前正在使用以下代码:

void circle(byte xc, byte yc, int radius, Colour colour) { int x = -radius, y = 0, err = 2 - 2 * radius; while(x < 0) { setPixel(xc - x, yc + y, colour); setPixel(xc - y, yc - x, colour); setPixel(xc + x, yc - y, colour); setPixel(xc + y, yc + x, colour); radius = err; if(radius  x || err > y) { err += ++x * 2 + 1; } } } 

我怎么能修改它以允许指定圆的厚度? PS我不想使用任何外部库,请!

如果按照中点圆算法的说明扫描八分圆 ,则主坐标y将始终增加1。 然后,您可以一次绘制两个圆,因为它们的主坐标是同步的。

您可以在内圈和外圈的点之间绘制水平(和垂直)线,而不是放置像素,这些线具有相同的y (或x )坐标。 这样做直到外圆到达对角线。

你保持状态为xerr两个圆,内圈i和外圈o 。 在内圆到达对角线后,内点位于该对角线上。 这意味着您要绘制八个相邻的八分圆扇区。

这个想法与@oakad在评论中提出的非常类似,但不需要保留列表。 中点圆算法可能比Bresenham算法慢,因此可能还有改进的余地,但内存占用率低是一个优势。

下面的代码将绘制一个具有给定内半径和外半径的空心圆。 线宽为ro - ri + 1 ,因此即使相等的半径也会打印一个像素宽的圆。 如果内半径小于外半径,则不会打印任何内容。

 void xLine(int x1, int x2, int y, int colour) { while (x1 <= x2) setPixel(x1++, y, colour); } void yLine(int x, int y1, int y2, int colour) { while (y1 <= y2) setPixel(x, y1++, colour); } void circle2(int xc, int yc, int inner, int outer, int colour) { int xo = outer; int xi = inner; int y = 0; int erro = 1 - xo; int erri = 1 - xi; while(xo >= y) { xLine(xc + xi, xc + xo, yc + y, colour); yLine(xc + y, yc + xi, yc + xo, colour); xLine(xc - xo, xc - xi, yc + y, colour); yLine(xc - y, yc + xi, yc + xo, colour); xLine(xc - xo, xc - xi, yc - y, colour); yLine(xc - y, yc - xo, yc - xi, colour); xLine(xc + xi, xc + xo, yc - y, colour); yLine(xc + y, yc - xo, yc - xi, colour); y++; if (erro < 0) { erro += 2 * y + 1; } else { xo--; erro += 2 * (y - xo + 1); } if (y > inner) { xi = y; } else { if (erri < 0) { erri += 2 * y + 1; } else { xi--; erri += 2 * (y - xi + 1); } } } } 

下面的解决方案可能很慢,但是非常简单。

首先,使用Bresenham算法绘制内圈和外圈。 然后,检查条件:

 if (pow(i - centre, 2) + pow(j - centre, 2) <= pow(outern_radius,2) && pow(i - centre, 2) + pow(j - centre, 2) >= pow(inner_radius,2)) 

如果满足,则setPixel(i,j)。

Interesting Posts