Need code to fill a pie slice?
#1
For your graphics tool chest, here is some code to draw a filled pie slice. QB64 circle method leaks when try PAINT to fill in slice.

We have to start at the beginning and just draw an arc, then give it sides (that actually meet the ends of the arc) then fill with PAINT, the routine filledPieSliceHandle& draws the pie slice in a separate location so there is no interference with PAINT fills PLUS you can then use the image multiple times at different locations.

Code:
_TITLE "arc drawing testing"
RANDOMIZE TIMER

CONST xmax = 800
CONST ymax = 600


SCREEN _NEWIMAGE(xmax, ymax, 32)
_SCREENMOVE 360, 60

DIM SHARED rad AS _FLOAT
rad = _PI(1 / 180)

DIM r AS _FLOAT
DIM e AS _FLOAT
DIM s AS _FLOAT
DIM cc AS _UNSIGNED LONG
r = 100
WHILE 1
    CLS
    cc = _RGB32(RND * 255, RND * 255, RND * 255)
    s = RND * 360: e = RND * 360
    arc 400, 200, 100, e, s, cc
    pieSlice 200, 400, 100, e, s, cc
    fillPieSlice 600, 400, 100, e, s, cc
    mySlice = filledPieSliceHandle&(r * .5 - 2, e, s, cc) 'test muliplicity
    FOR i = 0 TO xmax STEP 100
        FOR j = 0 TO ymax STEP 100
            IF i = 0 OR i = 700 THEN
                _PUTIMAGE (i + 2, j + 2), mySlice
            ELSEIF j = 0 OR j = 500 THEN
                _PUTIMAGE (i + 2, j + 2), mySlice
            END IF
        NEXT
    NEXT
    _FREEIMAGE mySlice
    _LIMIT 1
WEND
_FREEIMAGE mySlice


'note: degrees start due East = 0 and go clockwise: South = 90, West = 180, North = 270
SUB arc (x, y, r, degStart, degStop, c&)
    'x, y origin, r = radius, c = color

    'degStart is first angle clockwise from due East = 0 degrees
    ' arc will start drawing there and clockwise until degStop angle reached

    IF degStop < degStart THEN
        arc x, y, r, degStart, 360, c&
        arc x, y, r, 0, degStop, c&
    ELSE
        'rad = _PI(1 / 180)
        rs = degStart * rad: re = degStop * rad
        FOR yr = -r TO r
            y2 = yr * yr
            FOR xr = -r TO r
                IF ABS(SQR(xr * xr + y2) - r) <= .5 THEN
                    IF atan360(yr, xr) >= rs AND atan360(yr, xr) <= re THEN PSET (x + xr, y + yr), c&
                END IF
            NEXT
        NEXT
    END IF
END SUB

'draw lines from origin to arc on sides
SUB pieSlice (x, y, r, degStart, degStop, c&)
    arc x, y, r, degStart, degStop, c&
    'rad = _PI(1 / 180)
    px = x + r * COS(rad * degStart): py = y + r * SIN(rad * degStart)
    LINE (x, y)-(px, py), c&
    px = x + r * COS(rad * degStop): py = y + r * SIN(rad * degStop)
    LINE (x, y)-(px, py), c&
END SUB

'test fillPieSlice code
SUB fillPieSlice (x, y, r, degStart, degStop, c&)
    pieSlice x, y, r, degStart, degStop, c&
    'rad = _PI(1 / 180)
    IF degStart <= degStop THEN
        midA = (degStop - degStart) / 2 + degStart
    ELSE
        midA = (360 - degStop + degStart) / 2 + degStop
    END IF
    px = x + .5 * r * COS(rad * midA): py = y + .5 * r * SIN(rad * midA)
    'CIRCLE (px, py), 4, c& 'debug before use paint
    PAINT (px, py), c&, c&
END SUB

'need to match degrees going around clockwise up to full circle
FUNCTION atan360 (y, x)
    test = _ATAN2(y, x)
    IF test < 0 THEN atan360 = _PI(2) + test ELSE atan360 = test
END FUNCTION

' create filled pie slice with no interference for PAINT,
' this function creates the image and returns the handle to call it
FUNCTION filledPieSliceHandle& (r AS _FLOAT, degStart AS _FLOAT, degEnd AS _FLOAT, c AS _UNSIGNED LONG)
    d = _DEST
    filledPieSliceHandle& = _NEWIMAGE(2 * r + 2, 2 * r + 2, 32)
    _DEST filledPieSliceHandle&
    pieSlice r, r, r, degStart, degEnd, c
    'rad = _PI(1 / 180)
    IF degStart <= degEnd THEN
        midA = (degEnd - degStart) / 2 + degStart
    ELSE
        midA = (360 - degEnd + degStart) / 2 + degEnd
    END IF
    px = r + .5 * r * COS(rad * midA): py = r + .5 * r * SIN(rad * midA)
    'CIRCLE (px, py), 4, c& 'debug before use paint
    PAINT (px, py), c, c
    _DEST d
END FUNCTION


Attached Files Thumbnail(s)

B += x
Reply
#2
Nice, bplus, does this work for Tempodibasic’s code example?
I like to program in BASIC
With code that is simple and slick
I learnt it in school
And it is still cool
So it is my number one pick
Reply
#3
Hi Adrian, 

TempodiBasic's post was what got me looking into the PAINT leak problem. But the code TempodiBasic was using was calling for percents of circles which I have no use for.

The angles for starting and stopping an arc were expressed as numbers 0 to 100, so you could illustrate the percent of something to a whole ie pie charts.

My utility is using angles in degree units so to to convert a percent to a degree:

degree = 360 * percentage / 100 

so 10% = 360 * 10/100 = 36 degrees

TempodiBasic can simply use this formula to convert his percents to degree angles to use in utility provided.
B += x
Reply
#4
I have been reminded by Steve that there is much easier way to draw an arc, you just have to be careful about leaving gaps between points, here is modified code testing for leaks from PAINT fills, it seems to work:
Code:
_TITLE "arc drawing #2 testing"
RANDOMIZE TIMER

CONST xmax = 800
CONST ymax = 600


SCREEN _NEWIMAGE(xmax, ymax, 32)
_SCREENMOVE 360, 60

DIM SHARED rad AS _FLOAT
rad = _PI(1 / 180)

DIM r AS _FLOAT
DIM e AS _FLOAT
DIM s AS _FLOAT
DIM cc AS _UNSIGNED LONG
r = 100
WHILE 1
    CLS
    cc = _RGB32(RND * 255, RND * 255, RND * 255)
    s = RND * 360: e = RND * 360
    'arc 400, 200, 100, e, s, cc
    'pieSlice 200, 400, 100, e, s, cc

    fillPieSlice 400, 300, RND * 300, e, s, cc

    'test stoppimg for leak
    'LINE (0, 0)-(2, 2), cc, BF  'ok stops

    'test for leaks from PAINT
    IF POINT(1, 1) = cc THEN
        COLOR _RGB32(255, 255, 255), _RGB32(0, 0, 0)
        LOCATE 1, 1: PRINT "PAINT leaked!!!Press any to end..."
        SLEEP: END
    END IF

    'mySlice = filledPieSliceHandle&(r * .5 - 2, e, s, cc) 'test muliplicity
    'FOR i = 0 TO xmax STEP 100
    '    FOR j = 0 TO ymax STEP 100
    '        IF i = 0 OR i = 700 THEN
    '            _PUTIMAGE (i + 2, j + 2), mySlice
    '        ELSEIF j = 0 OR j = 500 THEN
    '            _PUTIMAGE (i + 2, j + 2), mySlice
    '        END IF
    '    NEXT
    'NEXT
    '_FREEIMAGE mySlice
    _LIMIT 1
WEND
_FREEIMAGE mySlice


'note: degrees start due East = 0 and go clockwise: South = 90, West = 180, North = 270
SUB arc (x, y, r, degStart, degStop, c&)
    'x, y origin, r = radius, c = color

    'degStart is first angle clockwise from due East = 0 degrees
    ' arc will start drawing there and clockwise until degStop angle reached

    IF degStop < degStart THEN
        arc x, y, r, degStart, 360, c&
        arc x, y, r, 0, degStop, c&
    ELSE
        'rad = _PI(1 / 180)

        ' modified to easier way suggested by Steve

        rs = degStart * rad: re = degStop * rad
        al = _PI * r * r * (re - rs) / _PI(2)
        FOR a = rs TO re STEP 1 / al
            PSET (x + r * COS(a), y + r * SIN(a)), c&
        NEXT

        'end of modified code

    END IF
END SUB

'draw lines from origin to arc on sides
SUB pieSlice (x, y, r, degStart, degStop, c&)
    arc x, y, r, degStart, degStop, c&
    'rad = _PI(1 / 180)
    px = x + r * COS(rad * degStart): py = y + r * SIN(rad * degStart)
    LINE (x, y)-(px, py), c&
    px = x + r * COS(rad * degStop): py = y + r * SIN(rad * degStop)
    LINE (x, y)-(px, py), c&
END SUB

'test fillPieSlice code
SUB fillPieSlice (x, y, r, degStart, degStop, c&)
    pieSlice x, y, r, degStart, degStop, c&
    'rad = _PI(1 / 180)
    IF degStart <= degStop THEN
        midA = (degStop - degStart) / 2 + degStart
    ELSE
        midA = (360 - degStop + degStart) / 2 + degStop
    END IF
    px = x + .5 * r * COS(rad * midA): py = y + .5 * r * SIN(rad * midA)
    'CIRCLE (px, py), 4, c& 'debug before use paint
    PAINT (px, py), c&, c&
END SUB

'need to match degrees going around clockwise up to full circle
FUNCTION atan360 (y, x)
    test = _ATAN2(y, x)
    IF test < 0 THEN atan360 = _PI(2) + test ELSE atan360 = test
END FUNCTION

' create filled pie slice with no interference for PAINT,
' this function creates the image and returns the handle to call it
FUNCTION filledPieSliceHandle& (r AS _FLOAT, degStart AS _FLOAT, degEnd AS _FLOAT, c AS _UNSIGNED LONG)
    d = _DEST
    filledPieSliceHandle& = _NEWIMAGE(2 * r + 2, 2 * r + 2, 32)
    _DEST filledPieSliceHandle&
    pieSlice r, r, r, degStart, degEnd, c
    'rad = _PI(1 / 180)
    IF degStart <= degEnd THEN
        midA = (degEnd - degStart) / 2 + degStart
    ELSE
        midA = (360 - degEnd + degStart) / 2 + degEnd
    END IF
    px = r + .5 * r * COS(rad * midA): py = r + .5 * r * SIN(rad * midA)
    'CIRCLE (px, py), 4, c& 'debug before use paint
    PAINT (px, py), c, c
    _DEST d
END FUNCTION
Smile
B += x
Reply
#5
Code to fill a pie slice:
 
SCREEN 1
CIRCLE (200, 100), 60, 1, -.0001, -1.57
PAINT (210, 80), 2, 1
dndbbs project:

Links to my MUD: (strictly 16-bit); AKA XP:

Dndbbs executables
http://www.filegate.net/pdn/pdnbasic/dnd50a1e.zip

Dndbbs source
http://www.filegate.net/pdn/pdnbasic/dnd50a1s.zip

Dndbbs upgrade
http://www.filegate.net/pdn/pdnbasic/dnd50a1u.zip

DNDDOOR - https://bit.ly/EriksDNDDoor DUNGEON - https://bit.ly/EriksDungeon
Interpreter - https://bit.ly/EriksSICK Hex Editor - https://bit.ly/EriksHexEditor Utilities - https://bit.ly/EriksUtils
QB45 files: - https://bit.ly/EriksQB45 QB64shell - https://bit.ly/QB64shell Some old QB64 versions: - https://bit.ly/OldQB64
Reply
#6
(01-12-2018, 02:20 PM)eoredson Wrote: Code to fill a pie slice:
 
SCREEN 1
CIRCLE (200, 100), 60, 1, -.0001, -1.57
PAINT (210, 80), 2, 1

Kids don't try this at home!

In most QB64 graphic screens, this will not only fill your pie slice, it will also flood your screen. Which is the reason I started this thread and a fix for the problem.
B += x
Reply