Tech Note 25a: Drawing Circles

May 01, 2008

© NSB Corporation. All rights reserved.

NS Basic doesn't have a command to draw circles. The DrawRectangle command can specify round corners, but it is not designed to draw various circles. If you need a circle in your application, preparing the bitmap of the circle is one method to do it. However, if you want circles of arbitrary sizes, the bitmap will not satisfy you. In this article, I will explain how to draw circles using trigonometric functions: SIN and COS.

A circle of radius 1 is called the unit circle, and any point on the circumference of this circle is expressed as (cosø sinø). This may be high school Math... but a diagram tells more clearly:
      

The length of circumference of a circle is 2 PI, where r is radius. In the unit circle, the circumference is 2 PIsince r equals 1. This is the definition of radian. In expression in degree, which is more familiar to most of us, 1 circumference is 360 degrees. Let's stop talking Math and draw a circle.

Assign the following code to a button:

    Dim Pi as Single
    Dim i as Single
    Dim X as Single
    Dim Y as Single

    Pi=3.14159265

    For i=0 to 2*Pi Step Pi/20
        X=50 * cos(i)
        Y=50 * sin(i)

        DrawLine 80,80,80+X,80+Y
    Next

It draws a fireworks-like shape of a radius 50 centering on the position of (80, 80):

      

The coordinates of the point which is on the circumference of the circle of radius r, whose center is located at (x0, y0), are expressed as (x0+r*cosø, y0+r*sinø) To make up one circle, the sample uses the For...Next statement that repeats this formula. Since sin() and cos() functions in MathLib use radian, you have to assign arguments in radian.

In order to make this into a circle, it is necessary to connect two points. Although it was slightly forcing, I use the following method:

    
    Dim Pi as Single
    Dim i as Single
    Dim X1 as Single
    Dim Y1 as Single
    Dim X2 as Single
    Dim Y2 as Single

    Pi=3.14159265

    For i=0 to 2*Pi STEP Pi/20
        
        X1=50 * cos(i)
        Y1=50 * sin(i)
        X2=50 * cos(i+Pi/20)
        Y2=50 * sin(i+Pi/20)

        DrawLine 80+X1,80+Y1,80+X2,80+Y2        
        
    Next
      

Mmm... it draws a circle! Although it is slow, you can draw arbitrary circles now. Again, it is not easy to use radian, so taking the fact

      360 degrees = 2 PI radian

we can find this constant:

      1 degree = PI/ 180

By multiplying any angle by this constant, it converts degree into radian.

    Dim Pi as Single
    Dim i as Single
    Dim X1 as Single
    Dim Y1 as Single
    Dim X2 as Single
    Dim Y2 as Single

    Pi=3.14159265/180

    For i=0 to 360 STEP 5
        
        X1=50 * cos(i*Pi)
        Y1=50 * sin(i*Pi)
        X2=50 * cos((i+5)*Pi)
        Y2=50 * sin((i+5)*Pi)

        DrawLine 80+X1,80+Y1,80+X2,80+Y2        
        
    Next

It should give you the same result.
If you use the following code, you can draw arbitrary ovals:

    Dim Pi as Single
    Dim i as Single
    Dim X1 as Single
    Dim Y1 as Single
    Dim X2 as Single
    Dim Y2 as Single

    Pi=3.14159265/180

    For i=0 to 270 STEP 5
        
        X1=70 * cos(i*Pi)
        Y1=50 * sin(i*Pi)
        X2=70 * cos((i+5)*Pi)
        Y2=50 * sin((i+5)*Pi)

        DrawLine 80+X1,80+Y1,80+X2,80+Y2        
        
    Next

      

So far what I introduced is relatively old fashioned, and it used to be used commonly when circle-drawing commands were not available. This isn't new to many people. But there is another method that can be used.

It's simple. The values of SIN and COS for every degree are stored in a database. Integer doesn't work in this case, so I use the Single data type. The values are stored in the array that contains 720 (360 x 2) elements. You can download the database here:

      amisclib.zip

The Creator ID is "Test" but you can change it using A.N.L.
Here is how to use it:
Add downloaded AmiSCLib.prc as resource in the IDE. Assume the ID is "1005" here. Add the following code in the Startup code:

    Dim Db as Database
    Dim Res as Integer
    
    Global ss(360) as Single
    Global cs(360) as Single

    res=dbOpen(Db,"AmiSCLib",0)
    If res<>0 Or res<>3 Then
        res = DbCreateDatabaseFromResource("DBIM",1005)
        res=dbOpen(Db,"AmiSCLib",0)
    End If
    
    res=dbread(Db,"sin",ss)
    res=dbread(Db,"cos",cs)

    res=dbClose(Db)

This assigns SIN values to SS() and COS values to CS(). If you set the AmiSCLib's creator ID the same as that of your application, the resource will be deleted when the application is uninstalled.

Each array contains 360 values corresponding to degrees 0-359. To get values of SIN and COS, directly look at array elements of SS() and CS() you need. You have to remember two things:

  1. NS Basic's array start at index 1, not index 0. Thus, the elements of SS are referred to by indexes 1-360. If the degree you want is 'X', SS(X+1) will read the value corresponding to the degree.
  2. The array consists of SS(1), SS(2), SS(3), ..., SS(359) and SS(360), so index values you specify have to be between 1 and 360 inclusive.

    Dim i as Single
    Dim X1 as Single
    Dim Y1 as Single
    Dim X2 as Single
    Dim Y2 as Single

    For i=0 to 355 STEP 5
        
        X1=50 * cs(i+1)
        Y1=50 * ss(i+1)
        X2=50 * cs(i+5)
        Y2=50 * ss(i+5)

        DrawLine 80+X1,80+Y1,80+X2,80+Y2        
        
    Next

The code gets simpler and the process speed isn't reduced much. You can use this library freely. It contains just the values of SIN and COS... AmiSCLib will be copied into the Backup folder on the desktop. Copy this to NS Basic's Lib folder.