Circle with thickness drawing algorithm

I am currently using Bresenham's circle drawing algorithm which draws circles perfectly, however I would like a relatively fast and efficient way to draw a circle with a given thickness (since Bresenham's method only draws the width of one pixel). I understand that I could just draw several circles with different radii, but I find that it would be very inefficient (and efficiency is important because it will work on Arduino, where every microsecond is precious). I am currently using the following code:

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 <= y) {
      err += ++y * 2 + 1;
    }
    if(radius > x || err > y) {
      err += ++x * 2 + 1;
    }
  }
}

      

How can I change this to clarify the thickness of the circle? PS I don't want to use any external libraries please!

+3


source to share


2 answers


If you scan along octants as described for the Midpoint Circle Algorithm , your main coordinate y

will always increase by one. Then you can draw two circles at the same time because their main coordinates are synchronized.

Instead of placing pixels, you draw horizontal (and vertical) lines between points of the inner and outer surroundings, which have the same coordinate y

(or x

). You do this until the outer circle reaches the diagonal.

You save state with x

and err

for two circles, the inner circle i

and the outer circle o

. After the inner circle reaches the diagonal, the inner point lies on that diagonal. This means that you are drawing eight adjacent octane sectors.



This idea is very similar to what @oakad suggested in the comments, but without having to keep a list. The Midpoint circle algorithm may be slower than Bresenham's algorithm, so there may be room for improvement, but lack of memory is an advantage.

The code below will show a hollow circle with given inside and outside radii. Line width ro - ri + 1

, so even equal radii will print a circle one pixel wide. It will not print anything if the inner radius is less than the outer radius.

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);
            }
        }
    }
}

      

+2


source


The solution below may be slow, however it is very simple.

First draw the inner and outer circles using Bresenham's algorithm. Then check the condition:



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))

      

If so, setPixel (i, j).

-1


source







All Articles