Dark Bit Factory & Gravity
PROGRAMMING => Other languages => Blitz => Topic started by: Paul on December 28, 2006
-
I've been trying to make a circle function that draws a circle but it leaves out some pixels. can anyone tell me why?
Graphics 800,600
SetBuffer BackBuffer()
LockBuffer BackBuffer()
circle1(300,255 Shl 16)
UnlockBuffer BackBuffer()
Flip
WaitKey()
Function circle1(radius,col)
d=(Sqr((radius^2)*2))/2
For x=-d To d
For y=-d To d
WritePixelFast(x+400,y+300,col)
Next
Next
For dist=d To radius
Steps#=180/(dist*Pi*2);Lower number = highr quality
a#=0
Repeat
a#=a#+steps#
WritePixelFast(Sin(a#)*dist+400,Cos(a#)*dist+300,col)
;x=Sin(a#)*dist+400
;y=Cos(a#)*dist+300
Until a#=>360
Next
End Function
Function circle2(radius,col)
For dist=0 To radius
Steps#=180/(dist*Pi*2);change 180 for diffren speed and quality... in my theory it should be perfect at 360 buy it isnt
a#=0
Repeat
a#=a#+steps#
WritePixelFast(Sin(a#)*dist+400,Cos(a#)*dist+300,col)
;x=Sin(a#)*dist+400
;y=Cos(a#)*dist+300
Until a#=>360
Next
End Function
-
Sorry, I don't have blitz installed but I take it you're referring to strange patterns of unfilled pixels appearing towards the outside of your circles which become just radiating lines of pixels the larger you make your circles. You could make the angle step smaller the larger you make your circle to fix this but that would mean a lot of unnecessary re-filling of pixels towards the middle of the circe. Another method of filling circles is to use a bit of pythagroras in something like:
/top row to bottom row of circle
for y=-radius to radius
/use pythagoras right angle triangle to find half the width of the current row
half_row_width=sqr(radius^2-y^2)
/add centre coords and fill row
for x=-half_row_width to half_row_width
fill_pixel centre_x+x,centre_y+y,color
next
next
I'm not sure what the blitz commands are for this but it should be something like that.
-
I think thats what i'm doing but i get this effect
http://www.yourfilehost.com/media.php?cat=other&file=1534test.zip
Graphics 800,600
SetBuffer BackBuffer()
While Not KeyHit(1)
ac=Input$("this should be 360")
if ac=<0 then ac=360
Cls
LockBuffer BackBuffer()
circle2(300,255,ac)
UnlockBuffer BackBuffer()
Flip
Wend
Function circle2(radius,col,ac=360)
For dist=0 To radius
Steps#=ac/(dist*Pi*2);change 180 for diffren speed and quality... in my theory it should be perfect at 360 buy it isnt
a#=0
Repeat
a#=a#+steps#
WritePixelFast(Sin(a#)*dist+400,Cos(a#)*dist+300,col)
;x=Sin(a#)*dist+400
;y=Cos(a#)*dist+300
Until a#=>360
Next
End Function
-
I think that there is also a command called oval that lets you draw them?
-
Yep paul, that was the effect I was meaning and it's caused by a large circle needing many more pixels filled at the edges than are needed at the middle. The little bit of code I posted (with some modification for it to work in blitz) will fill it completely and only fill each pixel once.
EDIT: I get a memory access violation with the exe, writepixelfast in blitz doesn't do any bounds checking for any offscreen coords so you need to test for that in your code else you might find some strange things happening to windows icons or pointers as you overwrite bits of memory you're not supposed to.
-
http://www.yourfilehost.com/media.php?cat=other&file=4405test.zip new .exe
I then im doing what you say
I start with the radius 0 and go out to the circle size.
For dist=o To radius
next
and each time i calculate the circumference and divide by 360 to get each step. but it still jumps sometimes. and probably does some double instead.
-
If you compare the code you'll see that I'm doing something different, instead of filling lines radiating from the centre this fills each horizontal line starting from the top:
Function fill_circle(radius,col)
centre_x=400
centre_y=300
for y=-radius to radius
half_row_width=sqr(radius^2-y^2)
for x=-half_row_width to half_row_width
writepixelfast(centre_x+x,centre_y+y,color)
next
next
end function
you should still put in some bounds checking though, or just use writepixel instead of writepixelfast.
-
THX this works perfectly:)
Sry that i diddnt get it first time
thx again
oval wouldnt work because im doing something different
-
Just a different version that I came up with that checks the screen bounds:
Function F_CIRCLE(cx, cy, rad)
LockBuffer
inc# = Float(360/(rad*Pi*2))
steps = 90/inc#
For i = 0 To steps
x1 = (cx - rad * Cos(deg#))
y1 = (cy - rad * Sin(deg#))
x2 = (cx*2)-x1
y2 = (cy*2)-y1
If x1 < 0 Then x1 = 0
If x2 >= GraphicsWidth() Then x2 =GraphicsWidth()-1
If y1 < 0 Then y1 = 0
If y2 >= GraphicsHeight() Then y2 = GraphicsHeight()-1
For x = x1 To x2
WritePixelFast x, y1, $ffffff
Next
For x = x1 To x2
WritePixelFast x, y2, $ffffff
Next
deg# = deg# + inc#
Next
UnlockBuffer
End Function