Pie and Piefilled drawing is distorted

From Liberty BASIC Family
Jump to navigation Jump to search

Description

Pie and Piefilled drawing is distorted in two ways. Firstly the angles are not drawn precisely and are skewed. Secondly when the diameter of the Pie is greater than or equal to 656 then the graphics will not flush and redraw correctly. Running this code the red Pie segments are drawn by Piefilled and the black lines by formula. The black lines are in the correct positions for the angles requested, you will note that the pie segments are all skewed by a varying amount depending on the angle drawn.

Also if you set the radius variable to 656, let the graphics draw then minimize and restore the window you will see the graphics are completely destroyed.

Example code to demonstrate the bug.

nomainwin
open "test" for graphics_nsb_fs as #gr
#gr "trapclose [quit]"
#gr "home"
#gr "posxy x y"
#gr "down"
radius = 600
'radius = 656
#gr "color red"
#gr "line ";x+radius/2;" ";y;" ";x;" ";y
for angle = 0 to 360 step 30
  #gr "backcolor red ; color yellow"
  #gr "piefilled ";radius;" ";radius;" ";angle;" ";15
next
for angle = 0 to 360 step 15
  r=radius/2
  fi=angle/180*acs(-1)
  xx=x+r*cos(fi)
  yy=y+r*sin(fi)
  #gr "color black"
  #gr "line ";xx;" ";yy;" ";x;" ";y
next
#gr "flush"
wait
[quit]
close #gr

Example code to work around the bug.

    'By tsh73
    nomainwin
    WindowWidth  = 630
    WindowHeight = 640
    UpperLeftX   = (DisplayWidth-WindowWidth)/2
    UpperLeftY   = (DisplayHeight-WindowHeight)/2
    graphicbox #1.g, 10,10,600,600
    open "Graph" for graphics_nf_nsb as #1
    print #1,   "trapclose [quit]"
    global graphicboxDC
    graphicboxDC=GetDC(hwnd(#1.g))

    print #1.g, "home ; down ; fill white"

    #1.g "posxy x y"
    h = 600
    #1.g "color red"
    #1.g "backcolor yellow"
    #1.g "line ";x+h/2;" ";y;" ";x;" ";y
    for t = 0 to 360 step 5
        #1.g "color black"
    '    #gr "pie ";h;" ";h;" ";t;" ";1
        ret=piefilled("#1.g",h,h,t,1)
        '1 degree pie sector
        'line should run along starting side of sector.
        r=h/2
        fi=t/180*acs(-1)
        xx=x+r*cos(fi)
        yy=y+r*sin(fi)
        #1.g "color red"
        #1.g "line ";xx;" ";yy;" ";x;" ";y
        call pause
    next

    'and one example of non-filled pie
    #1.g "color blue; size 2"
    ret=pie("#1.g",600,600,n,10)

wait

[quit]
    close #1
end

sub pause
    timer 100, [up]
    wait
[up]
    timer 0
end sub
'=============================Window and DC functions=================================
Function GetDC(hWnd)
    CallDLL #user32, "GetDC",_
        hWnd As Ulong,_  'window or control handle
        GetDC As Ulong   'returns device context
End Function

Function piefilled(h$,w,h,ang1,ang2)
    #h$ "posxy x y"
    ulX=int(x-w/2)
    ulY=int(y-h/2)
    lrX=int(ulX+w)
    lrY=int(ulY+h)

'in LB, ang2 is delta. Goes clockwise if >0, backwards if <
    ang2 = ang1+ang2
    'it looks it works only if ang1>ang2 (GDI draw counterclockwise)?: hence hack:
    if ang1<ang2 then tmp = ang1:ang1=ang2:ang2=tmp
    w2=w/2
    h2=h/2

    a1=ang1/180*acs(-1)
    xxS=int(x+w2*cos(a1))
    yyS=int(y+h2*sin(a1))
    a2=ang2/180*acs(-1)
    xxE=int(x+w2*cos(a2))
    yyE=int(y+h2*sin(a2))
    CallDll #gdi32, "Pie",_
        graphicboxDC as ulong,_ 'device context
        ulX as long,_ 'upper left x origin
        ulY as long,_ 'upper left y origin
        lrX as long,_ 'lower right x extent point
        lrY as long,_ 'lower right y extent point
        xxS as long,_ 'start arc here X
        yyS as long,_ 'start arc here Y
        xxE as long,_ 'end arc here X
        yyE as long,_ 'end arc here Y
        result as boolean 'nonzero if successful
end function

Function pie(h$,w,h,ang1,ang2)
    #h$ "posxy x y"
    ulX=int(x-w/2)
    ulY=int(y-h/2)
    lrX=int(ulX+w)
    lrY=int(ulY+h)

'in LB, ang2 is delta. Goes clockwise if >0, backwards if <
    ang2 = ang1+ang2
    'it looks it works only if ang1>ang2 (GDI draw counterclockwise)?: hence hack:
    if ang1<ang2 then tmp = ang1:ang1=ang2:ang2=tmp
    w2=w/2
    h2=h/2

    a1=ang1/180*acs(-1)
    xxS=int(x+w2*cos(a1))
    yyS=int(y+h2*sin(a1))
    a2=ang2/180*acs(-1)
    xxE=int(x+w2*cos(a2))
    yyE=int(y+h2*sin(a2))
    #h$ "line ";xxS;" ";yyS;" ";x;" ";y
    #h$ "line ";xxE;" ";yyE;" ";x;" ";y
    CallDll #gdi32, "Arc",_
        graphicboxDC as ulong,_ 'device context
        ulX as long,_ 'upper left x origin
        ulY as long,_ 'upper left y origin
        lrX as long,_ 'lower right x extent point
        lrY as long,_ 'lower right y extent point
        xxS as long,_ 'start arc here X
        yyS as long,_ 'start arc here Y
        xxE as long,_ 'end arc here X
        yyE as long,_ 'end arc here Y
        result as boolean 'nonzero if successful
end function