## Circles

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

### Circles

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: 2926
Joined: Jan 15, 2007 20:44
Location: Australia

Code: Select all

`Screen 19Window (-12, 8)-(12,-8)Dim As Double Pi, twoPi, theta, radius, xctr, yctr, x, yPi = 4 * Atn(1)TwoPi = 2 * Piradius = 2      ' radius of circlexctr = 1        ' position of centreyctr = 2Pset(radius + xctr, yctr), 14   ' start circleFor theta = 0 To TwoPi Step .05     ' theta in radians    x = xctr + radius * Cos(theta)    y = yctr + radius * Sin(theta)    Line -(x,y), 14    ' sectorNext thetaLine -(radius + xctr, yctr), 14 ' close circleSleep`
Steve
Posts: 16
Joined: Feb 26, 2006 23:33
Location: Atlanta, GA

### Re: Circles

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:

Code: Select all

`Const PI As Double = 3.1415926535897932sub 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)             nextend subscreen 13drawmeacircle(10,10, 3)drawmeacircle(100,100, 30)sleep`

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

### Thanks!

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: 4737
Joined: Sep 28, 2006 2:41
Location: California, USA

### Circles

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

Code: Select all

`dim x1 as doubledim y1 as doubledim x2 as doubledim y2 as doubledim r1 as doubledim r2 as doubledim a1 as doubledim a2 as doubledim stepsize as doubledim pi as doublepi = 3.14159screen 12stepsize = .00001r1 = 100r2 = 105a1 = 0a2 = pi /2do     ' 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: 2926
Joined: Jan 15, 2007 20:44
Location: Australia
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
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   radiusDim As Single   circumferenceDim As Single   stepsizeScreenRes 640, 480Window 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: 677
Joined: Oct 22, 2005 21:12
Location: Denmark
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: 2926
Joined: Jan 15, 2007 20:44
Location: Australia
There is no need to ever use sine or cosine to draw a circle on the screen.

Code: Select all

`Screen 19Window (-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 segEnd Sub'-----------------------------------------------------------' test circ routineDim As Double ctrx = 2  ' position of centreDim As Double ctry = 1    Dim As Double rad = 6   ' radius of circleCirc( ctrx, ctry, rad)'-----------------------------------------------------------Sleep'-----------------------------------------------------------`
albert
Posts: 4737
Joined: Sep 28, 2006 2:41
Location: California, USA
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: 677
Joined: Oct 22, 2005 21:12
Location: Denmark
@Richard

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

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

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 segEnd Sub'-----------------------------------------------------------' test circ routineDim As Double ctrx = 250  ' position of centreDim As Double ctry = 250    Dim As Double rad = 200   ' radius of circleCirc( ctrx, ctry, rad)'-----------------------------------------------------------Sleep'-----------------------------------------------------------  `
Richard
Posts: 2926
Joined: Jan 15, 2007 20:44
Location: Australia
@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 19Window (-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 segEnd Sub'-----------------------------------------------------------------------' test circ routineDim As Double Xctr = 0  ' x position of centreDim As Double Yctr = 0  ' yDim As Double rad = 3   ' radius of circleDim As Double ecc = 2   ' y eccentricityDim As Double col = 14  ' colourCirc( Xctr, Yctr, rad, ecc, col)Circ( Xctr, Yctr, rad, .5, 12)Line (-10,  rad) -(10,  rad),7Line (-10, -rad) -(10, -rad),7Line (rad,  -16) -(rad, 16),7Line (-rad, -16) -(-rad, 16),7'-----------------------------------------------------------------------Sleep'-----------------------------------------------------------------------`
albert
Posts: 4737
Joined: Sep 28, 2006 2:41
Location: California, USA

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.