Board index » delphi » Drawing a circle, pixel by pixel

Drawing a circle, pixel by pixel

Search Google for Bresenham's circle algorithm.
It's very fast and doesn't have that problem.
--
Finn Tolderlund

"Jon Lennart Berg" <jon...@c2i.net> wrote in message
news:3dae89b1$1@newsgroups.borland.com...

Quote
> For some time now i have been using the following routine to calculate a
> circle pixel by pixel. It works great except that when the circle has a
> radius span of more than 360, the pixels start to move away from each

other.
 

Re:Drawing a circle, pixel by pixel


By the way:
The problem with your old procedure is that you always draw 360 pixels (for
x:=0 to 359 do) nomatter how big or small the circle is.
This means that for small circles you draw too many pixels and for large
circles you draw too few pixels.
--
Finn Tolderlund

"Jon Lennart Berg" <jon...@c2i.net> wrote in message
news:3daec4cf$1@newsgroups.borland.com...

Quote
> Thanks!
> Works like a charm... :)
> Lennart Berg

Re:Drawing a circle, pixel by pixel


Since the formula for a circle's circumference is 2*Radius*Pi you have draw
2*Radius*Pi pixels.
This means that your old procedure should be changed to something like this:
procedure Circle(xStart, yStart, Radius: Integer;
  Canvas: TCanvas; Color: TColor);
var
  {x,}xpos,ypos: Integer;
  Pix, Pixels: Integer;
  x: Real;
begin
  Pixels := Round(2* Radius * Pi);
  //for x:=0 to 359 do
  for pix := 0 to Pixels-1 do
  begin
    x := 360 * pix / Pixels; {calculate a value of 0-359}
    xpos:=(round(xStart + sin(x*pi/180)*radius));
    ypos:=(round(yStart + cos(x*pi/180)*radius));
    Canvas.Pixels[xpos,ypos] := Color;
  end;
end;
--
Finn Tolderlund

"Jon Lennart Berg" <jon...@c2i.net> skrev i en meddelelse
news:3db00f6f@newsgroups.borland.com...

Quote
> I figured that, but i was unsure about what values i should place there.
> I guess (X * Y * X) would give correct results??

> Lennart Berg

> "Finn Tolderlund" <f...@nospam.com> skrev i melding
> news:3dafb1bb$1@newsgroups.borland.com...
> > By the way:
> > The problem with your old procedure is that you always draw 360 pixels
> (for
> > x:=0 to 359 do) nomatter how big or small the circle is.
> > This means that for small circles you draw too many pixels and for large
> > circles you draw too few pixels.
> > --
> > Finn Tolderlund

Re:Drawing a circle, pixel by pixel


Quote
Finn Tolderlund wrote:

> Since the formula for a circle's circumference is 2*Radius*Pi you have draw
> 2*Radius*Pi pixels.
> This means that your old procedure should be changed to something like this:
> procedure Circle(xStart, yStart, Radius: Integer;
>   Canvas: TCanvas; Color: TColor);
> var
>   {x,}xpos,ypos: Integer;
>   Pix, Pixels: Integer;
>   x: Real;
> begin
>   Pixels := Round(2* Radius * Pi);
>   //for x:=0 to 359 do
>   for pix := 0 to Pixels-1 do
>   begin
>     x := 360 * pix / Pixels; {calculate a value of 0-359}
>     xpos:=(round(xStart + sin(x*pi/180)*radius));
>     ypos:=(round(yStart + cos(x*pi/180)*radius));
>     Canvas.Pixels[xpos,ypos] := Color;
>   end;
> end;
> --
> Finn Tolderlund

You might also check if this renders faster:

   Canvas: TCanvas; Color: TColor);
 var
   xpos,ypos: Integer;
   Pix, Pixels: Integer;
   x: Real;
 begin
   Pixels := Round(2*Radius * Pi);
   //for x:=0 to 359 do
   x:=pi*2/pixels;
   with canvas do
   for pix := 0 to Pixels do
   begin
     x := 360 * pix / Pixels; {calculate a value of 0-359}
     xpos:=(round(xStart + sin(pix*x)*radius));
     ypos:=(round(yStart + cos(pix*x)*radius));
     if  pix=0 then moveto(x,y) else lineto(x,y);
   end;
 end;

This way you can use the canvas pen width in your drawing
procedure as well.
Since this connects all the points you can reduce the number of
steps if you like and still get a closed circle.

Remco

Re:Drawing a circle, pixel by pixel


Okay, a bit late, but:

procedure MidPointCircle(iBitmap: TBitmap; iX, iY, iRadius: integer; iValue:
TColor);

  procedure CirclePoints(iOriginX,iOriginY,iX, iY: integer; iValue: TColor);
  begin
    iBitmap.Canvas.Pixel [iOriginX + iX, iOriginY + iY]  :=  iValue;
    iBitmap.Canvas.Pixel [iOriginX + iY, iOriginY + iX]  :=  iValue;
    iBitmap.Canvas.Pixel [iOriginX + iY, iOriginY - iX]  :=  iValue;
    iBitmap.Canvas.Pixel [iOriginX + iX, iOriginY - iY]  :=  iValue;
    iBitmap.Canvas.Pixel [iOriginX - iX, iOriginY - iY]  :=  iValue;
    iBitmap.Canvas.Pixel [iOriginX - iY, iOriginY - iX]  :=  iValue;
    iBitmap.Canvas.Pixel [iOriginX - iY, iOriginY + iX]  :=   iValue;
    iBitmap.Canvas.Pixel [iOriginX - iX, iOriginY + iY]  :=   iValue;
  end;

var  { Introduction to computer graphics (Foley, van Dam, Feiner, Hughes,
Philips),
       isbn 0-201-60921-5. }
  x,y,d: integer;
  deltaE,deltaSE: integer;
begin
  (* This function uses second-order partial differences to compute
increments *)
  (* in the decision variable. Assumes center of circle is at origin. *)
  x := 0;
  y := iRadius;
  d := 1 - iRadius;
  deltaE := 3;
  deltaSE := 5 - iRadius*2;

  CirclePoints (iX,iY, x,y, iValue);

  while (y > x) do
  begin
    if (d < 0) then
    begin
      inc (d, deltaE);
      inc (deltaE, 2);
      inc (deltaSE, 2);
      inc (x);
    end else begin
      inc (d, deltaSE);
      inc (deltaE, 2);
      inc (deltaSE, 4);
      inc (x);
      dec (y);
    end;
    CirclePoints (iX,iY, x,y, iValue);
  end;
end;

"Remco de Korte" <re...@onwijs.com> wrote in message
news:3DB13B82.DF9D713A@onwijs.com...

Quote
> Finn Tolderlund wrote:

> > Since the formula for a circle's circumference is 2*Radius*Pi you have
draw
> > 2*Radius*Pi pixels.
> > This means that your old procedure should be changed to something like
this:
> > procedure Circle(xStart, yStart, Radius: Integer;
> >   Canvas: TCanvas; Color: TColor);
> > var
> >   {x,}xpos,ypos: Integer;
> >   Pix, Pixels: Integer;
> >   x: Real;
> > begin
> >   Pixels := Round(2* Radius * Pi);
> >   //for x:=0 to 359 do
> >   for pix := 0 to Pixels-1 do
> >   begin
> >     x := 360 * pix / Pixels; {calculate a value of 0-359}
> >     xpos:=(round(xStart + sin(x*pi/180)*radius));
> >     ypos:=(round(yStart + cos(x*pi/180)*radius));
> >     Canvas.Pixels[xpos,ypos] := Color;
> >   end;
> > end;
> > --
> > Finn Tolderlund

> You might also check if this renders faster:

>    Canvas: TCanvas; Color: TColor);
>  var
>    xpos,ypos: Integer;
>    Pix, Pixels: Integer;
>    x: Real;
>  begin
>    Pixels := Round(2*Radius * Pi);
>    //for x:=0 to 359 do
>    x:=pi*2/pixels;
>    with canvas do
>    for pix := 0 to Pixels do
>    begin
>      x := 360 * pix / Pixels; {calculate a value of 0-359}
>      xpos:=(round(xStart + sin(pix*x)*radius));
>      ypos:=(round(yStart + cos(pix*x)*radius));
>      if  pix=0 then moveto(x,y) else lineto(x,y);
>    end;
>  end;

> This way you can use the canvas pen width in your drawing
> procedure as well.
> Since this connects all the points you can reduce the number of
> steps if you like and still get a closed circle.

> Remco

Other Threads