Circle/Arc drawing to pixmap


Tweet blitzmax graphics code-archives algorithms
(Posted 2 years ago) TomToad

This code will draw circles and arcs onto pixmaps. Just use Circle(Pixmap:TPixmap, xoff:int, yoff:int, radius:int, color:int, arcbegin:float = 0, arcend:float = 360, steps:int = 6)
Pixmap is the pixmap in which you will be drawing the circle
xoff, yoff will be the center of the circle
radius is the radius of the circle
color is in the format ARGB
arcbegin, arcend is the beginning angle and ending angle of the arc you wish to draw.
steps is the angle added each step. A higher value will give a more polygon look, a lower value will give a smoother arc look.

The Line function is a modified version of Besenham's LineDraw routine (integer math only) by ImaginaryHuman

'This functiom uses the Bresenham algorithm for drawing a line.  The code below is a
' slightly modified version of [codearc 1465] by ImaginaryHuman
Function line(pixmap:TPixmap,x1:Int,y1:Int,x2:Int,y2:Int,color:Int)
    'Draws a line of individual pixels from X1,Y1 to X2,Y2 at any angle
    Local Steep:Int=Abs(Y2-Y1) > Abs(X2-X1)         'Boolean
    If Steep
        Local Temp:Int=X1; X1=Y1; Y1=Temp       'Swap X1,Y1
        Temp=X2; X2=Y2; Y2=Temp     'Swap X2,Y2
    EndIf
    Local DeltaX:Int=Abs(X2-X1)     'X Difference
    Local DeltaY:Int=Abs(Y2-Y1)     'Y Difference
    Local Error:Int=0       'Overflow counter
    Local DeltaError:Int=DeltaY     'Counter adder
    Local X:Int=X1      'Start at X1,Y1
    Local Y:Int=Y1      
    Local XStep:Int
    Local YStep:Int
    If X1<X2 Then XStep=1 Else XStep=-1 'Direction
    If Y1<Y2 Then YStep=1 Else YStep=-1 'Direction
    If Steep Then WritePixelSafe(pixmap,Y,X,color) Else WritePixelSafe(pixmap,X,Y,color)        'Draw
    While X<>X2
        X:+XStep        'Move in X
        Error:+DeltaError       'Add to counter
        If (Error Shl 1)>DeltaX     'Would it overflow?
            Y:+YStep        'Move in Y
            Error=Error-DeltaX      'Overflow/wrap the counter
        EndIf
        If Steep Then WritePixelSafe(pixmap,Y,X,color) Else WritePixelSafe(pixmap,X,Y,color)        'Draw
    Wend
End Function

'This function writes pixel color to the pixmap while also doing bounds checks
Function WritePixelSafe(pixmap:TPixmap,x:Int,y:Int,color:Int)
    If x < 0 Or x >= pixmap.Width Or y < 0 Or y >= pixmap.Height Then Return
    WritePixel(pixmap,x,y,color)
End Function

'This function will draw a circle or an arc.
'pixmap is the pixmap that you will be drawing to
'xoff, yoff are the offsets for the center of the circle.  to center the circle on the pixmap, you 
'   would use something like xoff = pixmap.width/2 : yoff = pixmap.height/2
'radius is the radius of the circle
'color is the color you wish to plot in the format ARGB
'arcbegin, arcend are the beginning and ending of the arc. 0 is alligned to the positive x axis and
'   angle increases clockwise.
'step is the number of degrees the renderer should advance each step.  The higher the number, the more polygonal 
'   the arc will look.  Using 90 will give you a square, using 120 will give you an equilateral triangle
Function Circle(pixmap:TPixmap,xoff:Int,yoff:Int,radius:Int,color:Int,arcbegin:Float=0,arcend:Float=360,steps:Int = 6)
    Local first:Int = True
    Local ox:Int, oy:Int, x:Int, y:Int
    While arcend < arcbegin
        arcend :+ 360
    Wend
    Local a:Float = arcbegin
    While a < arcend
        x = xoff+radius*Cos(a)
        y = yoff+radius*Sin(a)
        If Not first
            line(pixmap,ox,oy,x,y,color)
        Else
            first = False
        End If
        ox = x
        oy = y
        a :+ steps
    Wend
    x = xoff + radius*Cos(arcend)
    y = yoff + radius*Sin(arcend)
    line(pixmap,ox,oy,x,y,color)
End Function

'example of usage
Graphics 400,400
Local pixmap:TPixmap = CreatePixmap(400,400,PF_RGBA8888)
pixmap.ClearPixels($FFFFFFFF) 'fill the pixmap with white

Circle(pixmap,100,100,100,$FF000000) 'draw a black circle in the upper right corner
Circle(pixmap,200,200,200,$FFFF0000,270,90) 'draw a red arc om the right
circle(pixmap,300,300,50,$FF00FF00,0,360,72) 'draw a green pentagon

Cls
DrawPixmap pixmap,0,0 'render the pixmap to the screen
Flip

WaitKey() 'wait for a key to be pressed

Reply To Topic (minimum 10 characters)

Please log in to reply