Re: semicircle [OFFTOPIC]

Search this archive.

From: Jay Link (jlink@interlink-bbs.com)
Date: Wed 01 Dec 1999 - 21:01:13 IST


> Maybe I'm missing something here, so just ignore me in that case, but
> wouldnt the best solution be the Bresenham circle algorithm?  It's
> fast, elegant, and takes aspect ratio into account.

Hey Chris,

That worked out very well! Thanks for posting it. There were two problems,
however:

1) The circle, whether filled or not, had a single blank line in the
center. But, that can be fixed by making y >= 0, not just > 0.

Here's how that would look, then, using gl_hline():

#define SCREEN_WIDTH  320
#define SCREEN_HEIGTH 200

void bresenham_circle(int xc, int yc, int r, char c)
{
      int x = 0, y = r, d = 2 * (1 - r);

      while (y >= 0)
      {
            gl_hline(xc + x, yc + y, xc - x, c);
            gl_hline(xc + x, yc - y, xc - x, c);
            if(d + y > 0)
            {
                  y--;
                  d -= (2 * y * SCREEN_WIDTH / SCREEN_HEIGTH) - 1;
            }
            if(x > d)
            {
                  x++;
                  d += (2 * x) + 1;
            }
      }
}


2) Now, the second problem is that your (or, Bresenham's) circle looks
good in 320 x 200 modes, but in a more modern 4/3 mode (i.e. 640 x 480),
it looks a little skewed. Contrast this with gl_circle(), which looks ok
in 4/3 modes, but looks bad in 320 x 200.

Using your post as an inspiration, though, I learned how ridiculously easy
it is to change the gl_circle() algorithm to make a filled circle instead.
Like I said, though, it looks good in high res, but skewed in 320 x 200.

void gl_filled_circle(int xc, int yc, int r, char c)
{
      int x = 0,
          y = r,
          d = 1 - r;

      gl_line(xc + x, yc + y, xc - x, yc + y, c);
      gl_line(xc + x, yc - y, xc - x, yc - y, c);
      gl_line(xc + y, yc + x, xc - y, yc + x, c);
      gl_line(xc + y, yc - x, xc - y, yc - x, c);
      while (x < y)
      {
            if (d < 0)
            {
                  d += x * 2 + 3;
            } else {
                  d += x * 2 - y * 2 + 5;
                  y--;
            }
            x++;
            gl_line(xc + x, yc + y, xc - x, yc + y, c);
            gl_line(xc + x, yc - y, xc - x, yc - y, c);
            gl_line(xc + y, yc + x, xc - y, yc + x, c);
            gl_line(xc + y, yc - x, xc - y, yc - x, c);
      }
}


Perhaps there is a way to iron out either one of these to look good in all
resolutions, perhaps by using vga_getxdim()? Or, they could be combined
into one super-function, where if vga_getxdim() = 320 then do Bresenham's,
otherwise do the modified gl_circle().

Anyway, Matan, I think this definitely needs to be in 1.4.1, however it's
coded, and I like the idea of fixing gl_circle() so that it looks good in
320 x 200, as well.

Thanks, everyone, for your suggestions!

-Jay Link


This archive was generated by hypermail 2.1.4 : Wed 21 Jan 2004 - 22:10:22 IST