Drawing Arcs

new BookmarkLockedFalling
Psycho
Full Member
***

Psycho Avatar

Posts: 196

Post by Psycho on Jul 12, 2010 19:58:23 GMT -5

In my quest to create some pie charts in RB, I discovered how much I miss the pie and piefilled commands from LB. To begin this process on my own (which I have not yet done) I had to first know how to create the arcs at the outside of the pie shape. Looking back through the Liberty Basic Newsletters, I found issue #109 had several different examples on how to do this. I modified code from that newsletter, originally written by Tom Nally, to work in Run Basic. The following code will work in IE8 and FF 3.6 but stacks the graphic area in IE6. I think the entire screen would have to be cleared and redrawn in IE6.

The original article can be found here: babek.info/libertybasicfiles/lbnews/nl109/arcs.htm

Anyway, maybe this will help someone else along the way.
The center mark can be removed and outside lines added to this example program to create a single pie piece.

Now, filling in this and other pieces.....certainly a challenge (at least for me).

'Demo program to show how to draw arcs in Run Basic
'Original program written in Liberty Basic by Tom Nally for LB newsletter
'http://babek.info/libertybasicfiles/lbnews/nl109/arcs.htm
'Converted for use in Run Basic by John "Psycho" Siejkowski 2010
'Released as Open Source

'Requires the following 6 arguments passed to the GenArc drawing sub:
'startAngle
'endAngle
'segments
'centerX
'centerY
'radius


'define graphic area handle as global to allow drawing both inside and outside of subs
global #main


'create user input area to test changes and view graphic results
html "<pre>"
print " X Center: ";:textbox #XCenter, "150", 10
print
print " Y Center: ";:textbox #YCenter, "150", 10
print
print " Radius: ";:textbox #Radius, "100", 10
print
print "Start Angle (degrees): ";:textbox #StartAngle, "15", 10
print
print " End Angle (degrees): ";:textbox #EndAngle, "85", 10
print
dim LineSegments(50)
for x = 1 to 50
LineSegments(x)=x
next x
print " No. Line Segments: ";:listbox #LineSegments, LineSegments(),0
#LineSegments select(20)
print
html "</pre>"
button #clear, "Clear Graphic Box", [clear]
print space$(5);
button #drawArc, "Draw Arc", [draw]
print space$(5);
button #quit, "Quit", [quit]
print

'display graphic box
html "<div style='position: relative; left: 5px; top: 5px; height:0px; width:0px;'>"
graphic #main, 300, 300
#main fill(255,255,100)
render #main
html "</div>"
wait

[clear]
html "<div style='position: relative; left: 5px; top: 5px; height:0px; width:0px;'>"
#main cls(255,255,100)
render #main
html "</div>"
wait

[quit]
cls
html "<b>Goodbye</b>"
end

[draw]
html "<div style='position: relative; left: 5px; top: 5px; height:0px; width:0px;'>"
'create same graphic area with yellow background
graphic #main, 300, 300
#main cls(255,255,100)
#main color("black")
#main size(1)

'get variable values from textboxes
XCenter = #XCenter value()
YCenter = #YCenter value()
Radius = #Radius value()
StartAngleDegs = #StartAngle value()
EndAngleDegs = #EndAngle value()
NLSegs = #LineSegments selection()

'call the sub which converts degrees to radians and generates arc
call GenArc XCenter, YCenter, Radius, StartAngleDegs, EndAngleDegs, NLSegs
render #main
html "</div>"
wait

Sub GenArc Xc, Yc, R, StartD, EndD, NLS
pi = 4*atn(1)
StartR = (StartD/360)*(2*pi)
EndR = (EndD/360)*(2*pi)
ArcElement = (EndR - StartR) / NLS
dim xplot(NLS)
dim yplot(NLS)

xplot(0) = Xc + R * cos(StartR)
yplot(0) = Yc - R * sin(StartR)

For i = 1 to NLS
xplot(i) = Xc + R * cos(StartR + i*ArcElement)
yplot(i) = Yc - R * sin(StartR + i*ArcElement)
Next i

'Draw a small cross at the arc center
#main line(Xc - 5, Yc, Xc + 5, Yc)
#main line(Xc, Yc + 5, Xc, Yc - 5)

'Plot the Arc
For i = 1 to NLS
#main line(xplot(i-1), yplot(i-1), xplot(i), yplot(i))
next i

End Sub


John "Psycho" Siejkowski
Janet
Global Moderator
*****

Janet Avatar

Posts: 276

Post by Janet on Jul 12, 2010 21:16:40 GMT -5

Can you use a thicker pen and simple lines to fill in the pie? This would be inside your sub.

Sub GenArc Xc, Yc, R, StartD, EndD, NLS
#main color(192, 192, 255)
Print "StartD = ";StartD
Print "EndD = ";EndD
Print "Radius = ";R
#main size(3)
for i = StartD to EndD
#main place(Xc, Yc)
#main north()
#main turn(i)
#main go(R)
next i
#main color("black")
pi = 4*atn(1)
StartR = (StartD/360)*(2*pi)
EndR = (EndD/360)*(2*pi)
ArcElement = (EndR - StartR) / NLS
dim xplot(NLS)
dim yplot(NLS)

xplot(0) = Xc + R * cos(StartR)
yplot(0) = Yc - R * sin(StartR)

For i = 1 to NLS
xplot(i) = Xc + R * cos(StartR + i*ArcElement)
yplot(i) = Yc - R * sin(StartR + i*ArcElement)
Next i

'Draw a small cross at the arc center
#main line(Xc - 5, Yc, Xc + 5, Yc)
#main line(Xc, Yc + 5, Xc, Yc - 5)

'Plot the Arc
For i = 1 to NLS
#main line(xplot(i-1), yplot(i-1), xplot(i), yplot(i))
next i
End Sub


I may not be using the right variables as the arc and the filled area aren't lining up.
[br]
Psycho
Full Member
***

Psycho Avatar

Posts: 196

Post by Psycho on Jul 13, 2010 5:58:35 GMT -5

Thanks Janet,

My original try was based on something similar. No arcs, I just drew the lines outward to the radius length using a pen size of 3 to prevent gaps. This still left small gaps on the outside that I filled with a gray circle. The pen size of 3 tends to make the center intersecting point misalign at times depending on the different values. The chart in this code looks kinda "flat" without darker bordering lines. Not sure I'll get all that to work but trying.

I've not yet figured out why your code doesn't line up either ;)

[start]
cls
'determine segment size percentages
dim seg(3)
seg(1)=int((rnd(0)*100)+1)
seg(2)=int((rnd(0)*(100-seg(1)))+1)
seg(3)=100-seg(1)-seg(2)


'print seg(1);"%"
'print seg(2);"%"
'print 100-seg(1)-seg(2);"%"

'create graphic area
graphic #1, 440, 440
'#1 fill(240, 240, 240) 'gray background

'display color legend
#1 size(1)
legend$="darkgreen blue red"
legend2$="Run,Make Ready,Non-Productive"
y=0
for legendcolor = 1 to 3
#1 color(word$(legend,ドルlegendcolor))
for x = 1 to 20
#1 place(0, y)
#1 box(x,x+y)
next x
#1 font("arial",12)
#1 color(black)
#1 place(25,x+y)
#1 "\";word$(legend2,ドルlegendcolor,",")';" ";seg(legendcolor);"%"
y=y+30
next legendcolor


#1 color("darkgreen")
#1 size(3)
seg(1)=int(seg(1)/100*360)
seg(2)=int(seg(2)/100*360)
for x = 0 to seg(1)
#1 place(220, 220)
#1 north()
#1 turn(x)
#1 go(110)
next x
#1 color("blue")
for x = seg(1)+1 to seg(2)+seg(1)
#1 place(220, 220)
#1 north()
#1 turn(x)
#1 go(110)
next x
#1 color("red")
for x = seg(2)+seg(1)+1 to 360
#1 place(220, 220)
#1 north()
#1 turn(x)
#1 go(110)
next x
#1 size(2)
#1 color("lightgray")
#1 place(220, 220)
#1 circle(110)
render #1
print
button #again, "Again", [start]
print
button #quit, "Quit", [quit]
wait

[quit]
cls
print "goodbye"
end


John "Psycho" Siejkowski
StefanPendl
Global Moderator
*****

StefanPendl Avatar

Run for BASIC ...
Posts: 945

[b]Stefan[/b] - [a href=http://stefanpendl.runbasichosting.com/]Homepage[/a][br][br][b]Please give credit if you use code I post, no need to ask for permission.[/b][br][br]Run BASIC 1.01, Fire-/Waterfox (IE11, Edge), Windows 10 Professional x64, Intel Core i7-4710MQ 2.5GHz, 16GB RAM
Psycho
Full Member
***

Psycho Avatar

Posts: 196

Post by Psycho on Jul 14, 2010 18:56:36 GMT -5

Indeed, I think it probably requires some complex coding to get pies filled correctly. I've not been able to do it where I feel it is "right" but I did get a combination of repeated arcs and lines to look somewhat decent. The picture below is from an early test with fixed segment amounts. I'll continue to work on the code to generate random amounts and post it on a new thread when I get it working at least somewhat decently.



John "Psycho" Siejkowski
Janet
Global Moderator
*****

Janet Avatar

Posts: 276

[br]
kokenge
Senior Member
****

kokenge Avatar

Posts: 261

Post by kokenge on Jul 15, 2010 12:37:57 GMT -5

Another possibility is to use html5 <canvas>. There is a huge list of options.

Here is a quick simple example of a pie chart with fill.

' -------------------------------
' Create the canvas
' -------------------------------
html "<canvas id='canvas' width='400' height='400' style='border: 1px #000 solid;'></canvas>"
html "<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
</script>"

' -------------------------------
' create pie for each percent
' -------------------------------
html "<script>
pcnt = '10|20|10|5|15|20|20' // list of percents

ctx.clearRect (0, 0, 400, 400); // clear previous pie
var x = 200; // x coordinate center
var y = 200; // y coordinate center
var radius = 200; // Arc radius
var clockwise = false; // clockwise or anticlockwise
var totPcnt = 0 // accumulated percents

if(pcnt.indexOf('|' != -1))
{
val = pcnt.split('|');
for (key in val)
{
thisPcnt = val[key] * 1; // force numeric
startDeg = (totPcnt / 100) * 360; // Convert pcnt to degrees
totPcnt = totPcnt + thisPcnt;
endDeg = (totPcnt / 100) * 360;
startAngle = (Math.PI/180) * startDeg;
endAngle = (Math.PI/180) * endDeg;
//alert('thisPcnt '+thisPcnt+' totPcnt '+totPcnt+' startDeg '+startDeg+' endDeg '+endDeg);

ctx.beginPath(); // start a pie drawing path
ctx.moveTo(200,200); // move to center
ctx.arc(x,y,radius,startAngle,endAngle, clockwise); // draw the arc
ctx.moveTo(200,200); // move to center
ctx.closePath(); // close the pat
ctx.fillStyle = 'rgb(' + (250 - (startDeg *2)) + ',' + (startDeg * 2) + ','+ startDeg +')'; // set a color
ctx.fill(); // fill the path with color
}
}
</script>"

wait
Psycho
Full Member
***

Psycho Avatar

Posts: 196

Post by Psycho on Jul 15, 2010 18:47:20 GMT -5

Intriguing without a doubt but I haven't been able to get your sample code to run. In IE I get a blank screen with an error symbol at the bottom and if FF I get a black outline squre with nothing else. Anyone else have the same result? Your code has me very curious as the comments make it fairly clear and the code I'm working on takes a long time to render the image.

John "Psycho" Siejkowski
Janet
Global Moderator
*****

Janet Avatar

Posts: 276

[br]
Psycho
Full Member
***

Psycho Avatar

Posts: 196

Post by Psycho on Jul 15, 2010 19:52:03 GMT -5

Thanks for displaying that Janet, it told me something was wrong on my end. I'm using FF 3.6.3 but I copied the code using IE and it lost all the line breaks. I hit enter to recreate to match the code but it wouldn't work in either browser. After seeing yours worked, I copied in FF and it retained the indenting and line feeds and worked just fine.

John "Psycho" Siejkowski
kokenge
Senior Member
****

kokenge Avatar

Posts: 261

Post by kokenge on Jul 15, 2010 20:09:51 GMT -5

I do know IE is behind in HTML5 support. <Canvas> is a very powerful feature. I use it for all my graphics.

I know their later versions of IE support HTML5, but since I never use IE, I'm not sure when they started to support it.

Here is a tutorial on <Canvas> if you are interested.
developer.mozilla.org/en/canvas_tutorial

Hope this Helps..
Dan