LoginLogin

Perfectly Filled Circles

Root / Submissions / [.]

SimeonCreated:
It can be difficult to draw a perfectly filled circle. Once the center of the circle goes off the screen, GPAINT can no longer be used. When other objects are inside the circle's border, GPAINT does not fill the entire circle. With this function, we can guarantee that the circle will get completely filled every time it is drawn.
'DRAWS A PERFECTLY FILLED CIRCLE
'C IS FILL COLOR AND B IS BORDER COLOR
DEF FCIRCLE X,Y,R,C,B
 GCIRCLE X,Y,R,8
 'IF CIRCLE IS ALREADY WITHIN BOUNDS
 IF X>=0&&Y>=0&&X<400&&Y<240 THEN
  GPAINT X,Y,C,8
  GCIRCLE X,Y,R,B
  RETURN
 ENDIF
 VAR DX=MAX(0,MIN(X,399))-X
 VAR DY=MAX(0,MIN(Y,239))-Y
 VAR DT=MAX(1,SQR(DX*DX+DY*DY))
 DX=X+DX/DT*(R-2)
 DY=Y+DY/DT*(R-2)
 GPAINT DX,DY,C,8
 GCIRCLE X,Y,R,B
END


FCIRCLE -100,-100,300,#RED,#WHITE

So, if the center of the circle is within bounds, then it just GPAINTs? I'm confused, because that still doesn't solve the problem with overlapping shapes.

Replying to:chicken
So, if the center of the circle is within bounds, then it just GPAINTs? I'm confused, because that still doesn't solve the problem with overlapping shapes.
GPAINT border mode solves this. If you include a "border color" as the last argument to the GPAINT call, the paint continues over every color until it reaches the border color, instead of constraining to a contiguous area of color. You can see he draws the circle with a color value of 8, and then specifies that as the paint border.

Graphics pages are actually 512x512 (bigger than the screen) and the entire area is drawable, so you should be using that as your bounds check. Otherwise, pretty good. I had used a similar method before but hadn't bothered to do any bounds checking.

Be careful with bounds checking. When you are near the edge, make sure that it's not off by a pixel or 2, which would cause the whole screen to be filled.

The pic makes it look anti - aliased, which is misleading

In most cases, this works just fine, but GPAINT has its issues. If you wanted to draw a circle with your method after having drawn lines or some other graphics on the screen, you might not fill the whole circle. I propose a method that is slower, but fills an entire circle manually and without issues from other graphics already present.
'X, Y, Radius, and color
DEF FILLCIRCLE X,Y,R,COLOR_
 FOR I=0 TO R*2-1
  FOR J=0 TO R*2-1
   'Finds distance(hypotenuse) from the center
   HYP=SQR(POW(ABS(I-X),2)+POW(ABS(J-Y),2))
   IF HYP<=R THEN GPSET I,J,COLOR_
  NEXT
 NEXT
END
Edit: To make it more efficient, you could make it check if it's drawing off-screen, saving some time while drawing.

Replying to:Guzzler
In most cases, this works just fine, but GPAINT has its issues. If you wanted to draw a circle with your method after having drawn lines or some other graphics on the screen, you might not fill the whole circle. I propose a method that is slower, but fills an entire circle manually and without issues from other graphics already present.
'X, Y, Radius, and color
DEF FILLCIRCLE X,Y,R,COLOR_
 FOR I=0 TO R*2-1
  FOR J=0 TO R*2-1
   'Finds distance(hypotenuse) from the center
   HYP=SQR(POW(ABS(I-X),2)+POW(ABS(J-Y),2))
   IF HYP<=R THEN GPSET I,J,COLOR_
  NEXT
 NEXT
END
Edit: To make it more efficient, you could make it check if it's drawing off-screen, saving some time while drawing.