Circles

General FreeBASIC programming questions.
Locked
albert
Posts: 6000
Joined: Sep 28, 2006 2:41
Location: California, USA

Circles

Post by albert »

Can someone give me a sample program to a circle, looping through radians and using sin() and cos() to solve x and y.

I forgot how to get a circle.
Richard
Posts: 3096
Joined: Jan 15, 2007 20:44
Location: Australia

Post by Richard »

Code: Select all

Screen 19
Window (-12, 8)-(12,-8)
Dim As Double Pi, twoPi, theta, radius, xctr, yctr, x, y
Pi = 4 * Atn(1)
TwoPi = 2 * Pi
radius = 2      ' radius of circle
xctr = 1        ' position of centre
yctr = 2
Pset(radius + xctr, yctr), 14   ' start circle
For theta = 0 To TwoPi Step .05     ' theta in radians
    x = xctr + radius * Cos(theta)
    y = yctr + radius * Sin(theta)
    Line -(x,y), 14    ' sector
Next theta
Line -(radius + xctr, yctr), 14 ' close circle

Sleep
Steve
Posts: 16
Joined: Feb 26, 2006 23:33
Location: Atlanta, GA

Re: Circles

Post by Steve »

albert wrote:Can someone give me a sample program to a circle, looping through radians and using sin() and cos() to solve x and y.

I forgot how to get a circle.
In FB, the easiest way is to look up the CIRCLE statement in the wiki. In general, if you have a radius r and an angle a (which you will vary from 0 to 2 * Pi):

FOR a = 0 to 2 * Pi STEP stepsize
x = r * COS(a)
y = r * SIN(a)
PSet(x, y)
a += stepsize
NEXT

This assumes that the stepsize is small enough that the result looks like a smooth circle instead of an array of isolated points.

There are faster ways, such as using the relatively slow trig functions to plot only 1/8 of the circle and using the 2D symmetry of the circle to get the rest. For example, once you have a point (x, y), then (x, -y), (-x, y), (-x, -y), (y, x), (y, -x), (-y, x) and (-y, -x) are all on the circle.
voodooattack
Posts: 605
Joined: Feb 18, 2006 13:30
Location: Alexandria / Egypt
Contact:

Post by voodooattack »

Code: Select all

Const PI As Double = 3.1415926535897932

sub drawmeacircle(byval x as integer, byval y as integer, byval radius as integer) 
    for i as double = 0 to PI * 2 step 0.005
        var x2 = cos(i), y2 = sin(i)
        
        pset ((x2 * radius) + x, (y2 * radius) + y)
         
    next
end sub


screen 13

drawmeacircle(10,10, 3)
drawmeacircle(100,100, 30)

sleep
edit: you guys beat me to it.. oh well =P
albert
Posts: 6000
Joined: Sep 28, 2006 2:41
Location: California, USA

Thanks!

Post by albert »

Thanks you guys. I had forgotten how to make a circle.


I'm testing the sin() and cos() function by:
creating a circle 90 degrees using just sines.
creating a circle 90 degrees using just cosines.

incrementing and decrementing through 1/2 pi.

I want to see the accuracy of the two functions.

I remember playing around with the formula and plugging in the log() somehow and remember that it smoothes out the rough edges on large circles. (corrects sin(),cos())

i think it was:
Y = Y * sin(log(r))
X = x * cos(log(r))

it might have been sin(?) * log(?)

I'll try to recreate the formula.
albert
Posts: 6000
Joined: Sep 28, 2006 2:41
Location: California, USA

Circles

Post by albert »

Here is my test on sin() circles and cos() circles
They both make perfect circles.

Code: Select all


dim x1 as double
dim y1 as double
dim x2 as double
dim y2 as double

dim r1 as double
dim r2 as double

dim a1 as double
dim a2 as double

dim stepsize as double
dim pi as double
pi = 3.14159

screen 12

stepsize = .00001
r1 = 100
r2 = 105
a1 = 0
a2 = pi /2
do 
    ' fOR a1 = 0 to Pi/2 STEP stepsize 
    'x1 = -500 + (r1 * COS(log(a1))) 
    'y1 = 0     + (r1 * SIN(log(a1))) 

    x1 = 200  + (r1 * COS(a2)) 
    y1 = 200  + (r1 * cos(a1)) 
    
    x2 = 200 + (r2 * sin(a2))
    y2 = 200 + (r2 * sin(a1))
    
    PSet(x1, y1),13
    pset(x2, y2),14
    circle(200,200),95,2
    a1 = a1 + stepsize
    a2 = a2 - stepsize
    
loop until a1 >= pi*2

'a1 += stepsize 
'NEXT 


sleep

Richard
Posts: 3096
Joined: Jan 15, 2007 20:44
Location: Australia

Post by Richard »

The double precision Sin and Cos functions in FB are correct to 16 digits. When Pset(x,y) sets a pixel on the screen it's position is quantised to the resolution of the screen. For 1000 pixels that is at best 3 digits.
There is a rule of thumb that says, when a human sees a circle drawn with 60 straight lines it looks smooth. For circles on the screen I use steps of .05 radians which gives 125 segments. That makes sure the polygon that approximates the circle will not have visible corners, the resolution of the screen is the limiting factor.
1000101
Posts: 2556
Joined: Jun 13, 2005 23:14
Location: SK, Canada

Post by 1000101 »

Ideally stepsize should be 2*PI/circumference as to only draw the exact number of points on the edge of circle. Using an arbitrary number is nonsense since you are either doing too much work or not enough. A stepsize of 0.05 would be a circle with a circumference of ~125 which would be a radius of 20. Since the circumference of a circle is defined as 2*PI*r you can reduce the whole stepsize from 2 * PI / 2 * PI * r to simply 1 / r.

Code: Select all

Const As Single PI      = 4 * Atn( 1 )

Dim As Single   radius
Dim As Single   circumference
Dim As Single   stepsize

ScreenRes 640, 480
Window Screen (-320, 240)-(319,-239)
Print "Enter a negative value to exit."

Do
        Line( -320, -232 )-( 319, -224 ), 0, bf
        Locate 2, 1
        Input "Radius"; radius
        If( radius < 0 )Then Exit Do
        
        circumference   = 2 * PI * radius
        Print "Circumference:"; circumference
        
        'stepsize        = 2 * PI / circumference
        stepsize        = 1 / radius
        
        Circle ( 0, 0 ), radius, 14
        For theta As Single = 0 To 2 * PI Step stepsize
                PSet( radius * Cos( theta ), radius * Sin( theta ) ), 7
        Next
        
Loop
Note, I have fbgfx circle in yellow then manually draw the circle in grey so you can see it's the same approximate shape and size. The differences come from fbgfx using a different circle drawing algorithm which does not use floats.
h4tt3n
Posts: 698
Joined: Oct 22, 2005 21:12
Location: Denmark

Post by h4tt3n »

Here is a fast circle & ellipse drawing function I made a little while back:

http://www.freebasic.net/forum/viewtopi ... ht=ellipse

It only uses roughly 1/8 as many calls to sin() or cos() as the simpler brute-force methods and therefore takes up much less system ressources.

Cheers,
Mike
Richard
Posts: 3096
Joined: Jan 15, 2007 20:44
Location: Australia

Post by Richard »

There is no need to ever use sine or cosine to draw a circle on the screen.

Code: Select all

Screen 19
Window (-12, 8)-(12,-8)
Const As Double s = .05             ' unity vector ( c + j s )
Const As Double c = Sqr(1 - s * s)  ' evaluated at compile time only

'-----------------------------------------------------------
Sub Circ(Byval xc As Double, Byval yc As Double, Byval radius As Double)
    Dim As Double x = radius, y = 0, t 
    Pset(x + xc, yc), 14   ' start circle
    For seg As Integer = 1 To 126         ' segments
        t = x
        x = c * x - s * y
        y = s * t + c * y
        Line -(x + xc, y + yc), 14
    Next seg
End Sub

'-----------------------------------------------------------
' test circ routine
Dim As Double ctrx = 2  ' position of centre
Dim As Double ctry = 1    
Dim As Double rad = 6   ' radius of circle
Circ( ctrx, ctry, rad)

'-----------------------------------------------------------
Sleep
'-----------------------------------------------------------
albert
Posts: 6000
Joined: Sep 28, 2006 2:41
Location: California, USA

Post by albert »

I wrote a huge number calculator, (its on the projects page under "I got my calculator working finally!")

I want to add sin() cos() and tan() functions to it and was testing a therory, that sines and cosines return the same values 90 degrees out of phase with each other, and i was right they do.


What i need is a faster method of figuring the functions other than rasing the number to powers and dividing by the factorial.
h4tt3n
Posts: 698
Joined: Oct 22, 2005 21:12
Location: Denmark

Post by h4tt3n »

@Richard

Cool enough, even though it has its issues. Do you know if this can be expanded to drawing ellipses?
albert
Posts: 6000
Joined: Sep 28, 2006 2:41
Location: California, USA

I modified the no sin(),cos() circle a little

Post by albert »

Hi everyone i modified richards circle program.

Code: Select all


Screen 19
'Window (-12, 8)-(12,-8)
Const As Double s = .001             ' unity vector ( c + j s )
Const As Double c = Sqr(1 - s * s)  ' evaluated at compile time only

'-----------------------------------------------------------
Sub Circ(Byval xc As Double, Byval yc As Double, Byval radius As Double)
    Dim As Double x = radius, y = 0, t 
    dim seg as integer
    
    Pset(x + xc, y + yc), 14   ' start circle
    For seg = 0 To 6.28 / s   '125         ' segments
        t = x
        x = c * x - s * y
        y = s * t + c * y
        'Line -(x + xc, y + yc), 14
        pset(x+xc,y+yc),14
    Next seg

End Sub

'-----------------------------------------------------------
' test circ routine
Dim As Double ctrx = 250  ' position of centre
Dim As Double ctry = 250    
Dim As Double rad = 200   ' radius of circle
Circ( ctrx, ctry, rad)

'-----------------------------------------------------------
Sleep
'----------------------------------------------------------- 
 
Richard
Posts: 3096
Joined: Jan 15, 2007 20:44
Location: Australia

Post by Richard »

@h4tt3n; Here is an expanded version to do aspect with one extra multiply.
Color now included. Implementation of aspect depends on how you define aspect.

Code: Select all

'-----------------------------------------------------------------------
' Circle or ellipse
'-----------------------------------------------------------------------
Screen 19
Window (-12, 8)-(12, -8)
Const As Double s = .05             ' unity vector ( c + j s )
Const As Double c = Sqr(1 - s * s)  ' evaluated at compile time only

'-----------------------------------------------------------------------
Sub Circ(_                  ' circle
    Byval cx As Double,_    ' centre x
    Byval cy As Double,_    ' centre y
    Byval r As Double,_     ' x radius
    Byval e As Double,_     ' y eccentricity
    Byval k As Integer)     ' colour
    Dim As Double t, x = r, y = 0
    Pset(x + cx, cy), 0     ' start circle
    For seg As Integer = 1 To 126   ' segments
        t = x
        x = t * c - y * s
        y = t * s + y * c
        Line -(x + cx, y * e + cy), k
    Next seg
End Sub

'-----------------------------------------------------------------------
' test circ routine
Dim As Double Xctr = 0  ' x position of centre
Dim As Double Yctr = 0  ' y
Dim As Double rad = 3   ' radius of circle
Dim As Double ecc = 2   ' y eccentricity
Dim As Double col = 14  ' colour

Circ( Xctr, Yctr, rad, ecc, col)
Circ( Xctr, Yctr, rad, .5, 12)

Line (-10,  rad) -(10,  rad),7
Line (-10, -rad) -(10, -rad),7

Line (rad,  -16) -(rad, 16),7
Line (-rad, -16) -(-rad, 16),7

'-----------------------------------------------------------------------
Sleep
'-----------------------------------------------------------------------
albert
Posts: 6000
Joined: Sep 28, 2006 2:41
Location: California, USA

Post by albert »

Thanks Richard your a god!

I decided instead of adding sin(), cos() and tan() functions to the calculator, I'll put and X and Y button to return the x and y locations, given an input of radians and radius.


Thankyou!

I wrote a program for QBasic back in 1995 that let the user rotate a line with the arrow keys, and did it without sin(),cos() or tan() but for the life of me i couldn't remember how i did it, your example brings back some memories. (I still can't remember exactly how i did it. but your program works.)

I'll go ahead and add the "X" and "Y" buttons to the calculator.
at a thousand precision it should only take a 1/2 minut or so to come up with a X or Y coordinate.
Locked