• Welcome to Dark Bit Factory & Gravity.
 

Plotting A Circle.

Started by Clyde, July 04, 2006

Previous topic - Next topic

0 Members and 0 Guests are viewing this topic.

Clyde

Im using tiny ptc and I wondered if anyone knew how to plot filled circles / ovals, using the FeedPixel(x,y,col) method with different heights and widths. Ive been racking my brain cell all day.

Cheers and many thanks,
Clyde.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.


Challenge Trophies Won:

zawran

There is a piece of code on the BR code archieves which plots a circle/eclipse using integer math. It should be fairly easy to convert to FB, there are both a bmx and bb version on the following link:

http://www.blitzbasic.com/codearcs/codearcs.php?code=1477


Clyde

Hmm seems the site is down. And Thanks man, I'll take a look whens its back online.

Cheers,
Clyde.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.


Challenge Trophies Won:

zawran

The site isn't down, but apparently it doesn't work to link directly to it, so here is the bb version (btw. the code is public domain so free to use/convert)


;Midpoint ellipse algorithm

Graphics 640,480,0,2

Local xCenter% = 320
Local yCenter% = 240
Local Rx%, Ry%
Local p%, px%, py%, x%, y%
Local Rx2%, Ry2%, twoRx2%, twoRy2%
Local pFloat#

Repeat
        Cls
WaitEvent()


        If MouseDown(1)
            xCenter = MouseX()
            yCenter = MouseY()
        EndIf
        Rx = Abs(xCenter - MouseX())
        Ry = Abs(yCenter - MouseY())

        Rx2 = Rx * Rx
        Ry2 = Ry * Ry
        twoRx2 = Rx2 Shl 1
        twoRy2 = Ry2 Shl 1

msStart = MilliSecs()

        ;Region 1
        x = 0
        y = Ry

        Plot xCenter + x, yCenter + y
        Plot xCenter - x, yCenter + y
        Plot xCenter + x, yCenter - y
        Plot xCenter - x, yCenter - y
        pFloat = (Ry2 - (Rx2 * Ry)) + (0.25 * Rx2)
        p = Int(pFloat)
        If pFloat Mod 1.0 >= 0.5 Then p = p + 1

        px = 0
        py = twoRx2 * y

        While px < py
                x = x + 1
                px = px + twoRy2
                If p >= 0
                        y = y - 1
                        py = py - twoRx2
                EndIf
                If p < 0 Then p = p + Ry2 + px Else p = p + Ry2 + px - py
                Plot xCenter + x, yCenter + y
                Plot xCenter - x, yCenter + y
                Plot xCenter + x, yCenter - y
                Plot xCenter - x, yCenter - y
        Wend

        ;Region 2
        pFloat = (Ry2 * (x + 0.5) * (x + 0.5)) + (Rx2 * (y - 1.0) * (y - 1.0)) - (Rx2 * (Float(Ry2)))
        p = Int(pFloat)
        If pFloat Mod 1.0 >= 0.5 Then p = p + 1
        While y > 0
                y = y - 1
                py = py - twoRx2
                If p <= 0
                        x = x +1
                        px = px + twoRy2
                EndIf
                If p > 0 Then p = p + Rx2 - py Else p = p + Rx2 - py + px
                Plot xCenter + x, yCenter + y
                Plot xCenter - x, yCenter + y
                Plot xCenter + x, yCenter - y
                Plot xCenter - x, yCenter - y
        Wend

timeToDraw = MilliSecs() - msStart
Text 20, 20, Rx + " x " + Ry
Text 20, 30, "Draw time " + timeToDraw + " ms"

        Flip(False)
Until KeyHit(1)


Shockwave

Filled circles are a bit harder, this does the trick and would probably be ok for you, it's basically my metaball generation code but I'm sure you can pull out the bits you need.


        #Include Once "tinyptc.bi"
        option dynamic
        If( ptc_open( "METABLOBS", 640, 480 ) = 0 ) Then
        End -1
        End If
   
        Dim Shared As Integer Buffer( 640 * 480 )
       
            dim as double angle,bangle
DO
radius=99
for z=1 to 99
        bangle=360
        clv=z
        if clv>255 then clv=255
        clv=rgb(clv,clv,clv)
        for a=1 to 360
           
            x1=(100+(radius*sin(angle*3.1415926535897932/180)))
            y1=(100+(radius*cos(angle*3.1415926535897932/180)))           
            x2=(100+(radius*sin(bangle*3.1415926535897932/180)))           
           
            angle=angle+.5
            bangle=bangle-.5
                               
            for l=x2 to x1
                buffer((640*y1)+l)=clv
            next
           
        next
        radius=radius-1
next

ptc_update @buffer(0)
LOOP UNTIL INKEY$<>""


Basically the Y sinus sorts out the Y co-ordinate
The two X sinus create the points to loop between to fill the circle.
Shockwave ^ Codigos
Challenge Trophies Won:

Shockwave

I was feeling mean just posting that snippet...
Here.. I converted it for you..

Slow code; :P


        #Include Once "tinyptc.bi"
        option dynamic
        option explicit
       
        If( ptc_open( "METABLOBS", 640, 480 ) = 0 ) Then
        End -1
        End If
        declare sub dcircle(BYVAL CX AS INTEGER , BYVAL CY AS INTEGER , BYVAL R AS INTEGER, BYVAL CLR AS INTEGER)
        Dim Shared As Integer Buffer( 640 * 480 )
       
           
DO
dcircle (320,240,239,&hffffff)
ptc_update @buffer(0)
LOOP UNTIL INKEY$<>""

SUB dCIRCLE(BYVAL CX AS INTEGER , BYVAL CY AS INTEGER , BYVAL R AS INTEGER, BYVAL CLR AS INTEGER)
DIM  as integer a,z,x1,y1,x2,l
dim as double angle,bangle

        bangle=360

       
       
        for a=1 to 1440
           
            x1=(cx+(r*sin(angle*3.1415926535897932/180)))
            y1=(cy+(r*cos(angle*3.1415926535897932/180)))           
            x2=(cx+(r*sin(bangle*3.1415926535897932/180)))           
           
            angle=angle+.125
            bangle=bangle-.125
                               
            for l=x2 to x1
                buffer((640*y1)+l)=CLR
            next
           
        next



END SUB
Shockwave ^ Codigos
Challenge Trophies Won:

Clyde

Thanks kindly to both of you.

Cheers,
Clyde.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.


Challenge Trophies Won:

Jim

A nice simple Blitz filled circle.

Graphics 640,480,0,2

Repeat
Color Rand(255),Rand(255),Rand(255)
fillcircle(Rand(640),Rand(480),Rand(100))
Until KeyDown(1)
End

Function fillcircle(x%,y%,r%)
r2%=r*r
For h% = -r To r
w% = Sqr(r2-h*h)
Line x-w,y+h , x+w,y+h
Next
End Function


Jim
Challenge Trophies Won:

Clyde

Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.


Challenge Trophies Won:

Shockwave

It would be easy to generate a much faster circle algo than mine in freebasic using Jims code :)
Shockwave ^ Codigos
Challenge Trophies Won:

Shockwave

Here, I did it.
All it needs now is a little asm to flat fill the scan lines :)


' Coded By Jim Shaw and Shockwave.
'
' Usage..

' DCIRCLE ( XP , YP , RADIUS , COLOUR )


        #Include Once "tinyptc.bi"
        option dynamic
        option explicit
       
        If( ptc_open( "CIRCLES", 640, 480 ) = 0 ) Then
        End -1
        End If
        declare sub dcircle(BYVAL CX AS INTEGER , BYVAL CY AS INTEGER , BYVAL R AS INTEGER, BYVAL CLR AS INTEGER)
        Dim Shared As Integer Buffer( 640 * 480 )
       
  dim rrx,rry,rrr,rrc         
DO
    rrx=rnd*(640)
    rry=rnd*(480)
    rrr=rnd*(250)
    rrc=rnd*(255)
dcircle (rrx,rry,rrr,rgb(rrc,rrc,rrc))
ptc_update @buffer(0)
LOOP UNTIL INKEY$<>""

SUB dCIRCLE(BYVAL CX AS INTEGER , BYVAL CY AS INTEGER , BYVAL R AS INTEGER, BYVAL CLR AS INTEGER)
DIM  as integer r2,cc,loopy,ww,l
r2=r*r
cc=-r
for loopy = cc to r       
        ww = Sqr(r2-loopy*loopy)
        for l = CX-ww to CX+ww
                   if l>0 and l<640 and loopy+CY>0 and loopy+CY<480 then
                       buffer((640*(loopy+CY))+l)=CLR
                   end if
        next   
next
END SUB
Shockwave ^ Codigos
Challenge Trophies Won:

Shockwave

Here's a quick hack to show how easy it would be to use this for generating your own bobs :)


' Fast Filled Circle Algo Using Tinyptc.
' Coded By Jim Shaw and Shockwave.
'
' Usage..

' DCIRCLE ( XP , YP , RADIUS , COLOUR )
'
' All it needs now is a little asm tweak to flat shade the scanline for
' ultimate speed.
'
' www.dbfinteractive.com
'
' A Quick hack to show shaded circles..

#define ptc_win
        #Include Once "tinyptc.bi"
       
        option static
        option explicit
       
        If( ptc_open( "CIRCLES", 640, 480 ) = 0 ) Then
        End -1
        End If
        declare sub dcircle(BYVAL CX AS INTEGER , BYVAL CY AS INTEGER , BYVAL R AS INTEGER, BYVAL CLR AS INTEGER)
        Dim Shared As Integer Buffer( 640 * 480 )
       
  dim rrx,rry,rrr,rrrc,rrgc,rrbc ,zz,rrt,rgt,rbt
DO
    rrx=rnd*(640)
    rry=rnd*(480)
    rrr=20+rnd*(50)
    rrrc=rnd*(255)
    rrgc=rnd*(255)
    rrbc=rnd*(255)
    rrt=0
    rgt=0
    rbt=0
for zz= rrr to 1 step -1
dcircle (rrx,rry,zz,rgb(rrt ,rgt ,rbt))
if rrt<rrrc then rrt=rrt+1
if rgt<rrgc then rgt=rgt+1
if rbt<rrbc then rbt=rbt+1
next

ptc_update @buffer(0)
LOOP UNTIL INKEY$<>""

SUB dCIRCLE(BYVAL CX AS INTEGER , BYVAL CY AS INTEGER , BYVAL R AS INTEGER, BYVAL CLR AS INTEGER)
DIM  as integer r2,cc,loopy,ww,l
r2=r*r
cc=-r
for loopy = cc to r       
        ww = Sqr(r2-loopy*loopy)
        for l = CX-ww to CX+ww
                   if l>0 and l<640 and loopy+CY>0 and loopy+CY<480 then
                       buffer((640*(loopy+CY))+l)=CLR
                   end if
        next   
next
END SUB
Shockwave ^ Codigos
Challenge Trophies Won:

Stonemonkey

Nice stuff Shockwave, if speed is a concern (particularly if you're considering using asm) then it'd be an idea to take the screen bounds checking outside the loops instead of for every pixel.

Clyde

Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.


Challenge Trophies Won:

thrawn89

Quote from: Stonemonkey on July 05, 2006
Nice stuff Shockwave, if speed is a concern (particularly if you're considering using asm) then it'd be an idea to take the screen bounds checking outside the loops instead of for every pixel.

And if in that row, not all the pixels are on the screen, then what?  ???

You'd have to calculate how many pixels you're going be drawing in the row, see if it goes out of bounds, if so, at what pixel, then use the for loop below to draw to that last pixel, but I agree, it cuts down the amount of IFs from a couple hundred per line to 1 per line

Thrawn

Stonemonkey

Hmmmm sorry, I didn't word that quite right. Take the x clipping out of the x loop and take the y clipping out of the y loop.

something like:

y=cy-radius
y_end=cy+radius
if y<0 then y=0
if y_end>screenheight then y_end=screenheight
while y<y_end
Ã,  Ã,  halfwidth=sqr(radius^2-(cy-y)^2)
Ã,  Ã,  x=cx-halfwidth
Ã,  Ã,  x_end=cx+halfwidth
Ã,  Ã,  if x<0 then x=0
Ã,  Ã,  if x_end>screenwidth then x_end=screenwidth
Ã,  Ã,  while x<x_end
Ã,  Ã,  Ã,  Ã,  plot(x,y,colour)
Ã,  Ã,  Ã,  Ã,  x+=1
Ã,  Ã,  wend
Ã,  Ã,  y+=1
wend

although I'd take it a bit further and use pointers to write into memory instead of using plot.

Shockwave

Cool :) I've had some common sense whacked into me! :)

Stonemonkey >  :whack: < Shocky
Shockwave ^ Codigos
Challenge Trophies Won:

thrawn89

Why stop there and write the whole thing in ASM, you? lol just kidding ;-)

Common sense whacked into you? Hmm looks like it was more like a long, rather deformed, green,...stick that was wacked into you to me....;-)

EDIT:
In hindsight, that should have probally have been left unsaid  :o

Shockwave

All I can say is lol. :)
Shockwave ^ Codigos
Challenge Trophies Won:

Shockwave

Anyway, what did you want this for Clyde? :) Anything interesting brewing mate?
Shockwave ^ Codigos
Challenge Trophies Won: