Author 
Topic: "Gridlock" Graph Dialog (Read 443 times) 

bplus
Senior Member
member is offline
Gender:
Posts: 1132


"Gridlock" Graph Dialog
« Thread started on: Mar 7^{th}, 2017, 11:29am » 

I would like feedback on this potential general Graphing Dialog so that it may be considered "Community tested".
Code:
' Gridlock Graph Dialog.txt for JB [B+=MGA] 20170307
' from graphing fx.txt finished 20170306
' but want grid to align with axis when possible = gridlock!
' from graphing evalB.txt for JB [B+=MGA] 20170222
' and tsh73 Implicit function, x, y screen functions
global pi, rad, deg, Dflag
global xPs, yPs, xmin, ymin, xmax, ymax 'for xScreen, yScreen functions
xPs = 400 : yPs = 400
pi = acs(1)
rad = pi / 180
deg = 180 / pi
Dflag = 1 'measure angles in degrees else radians
'xmin=2*pi : xmax=pi : ymin =2 : ymax=1 'sin(x)
'xmin=10 : xmax=5 : ymin =50 : ymax=10 'quadradic x^2 + 2*x  35
xmin=2 : xmax=5 : ymin =1 : ymax=100 'exp(x)
call ShowGraph
print "Done, bye!"
sub ShowGraph
WindowWidth = 500
WindowHeight = 500
UpperLeftX = int((DisplayWidth  WindowWidth) / 2)
UpperLeftY = int((DisplayHeight  WindowHeight) / 2)
open "Graph Dialog" for graphics_nsb_nf as #gd
#gd "font arial 8"
#gd "trapclose [quitGraphDialog]"
#gd "down"
'graph box section
#gd "color cyan"
#gd "backcolor lightgray"
#gd "place ";0;" ";0
#gd "boxfilled ";xPs;" ";yPs
#gd "backcolor white"
x0 = xScreen(0) : y0 = yScreen(0)
'xgrid lines
inc = (xmax  xmin) / 20
#gd "color cyan"
if 0 <= x0 and x0 <= xPs then
start = 0
while start <= xmax
scan
#gd "line ";xScreen(start);" ";0;" ";xScreen(start);" ";400
start = start + inc
wend
start = 0
while start >= xmin
scan
#gd "line ";xScreen(start);" ";0;" ";xScreen(start);" ";400
start = start  inc
wend
else
start = xmin
for i = 0 to 20
#gd "line ";i * 20;" ";0;" ";i * 20;" ";400
start = start + inc
next
end if
#gd "color black"
#gd "place "; 2;" ";415;"; x min (left) is ";xmin;"."
#gd "place ";145;" ";430;"; x scale increment is ";inc;"."
#gd "place ";170;" ";445;"; x middle is ";xmin + 10 * inc;"."
#gd "place ";325;" ";460;"; x max (right) is ";xmax;"."
'y grid lines
inc = (ymax  ymin) / 20
if 0 <= y0 and y0 <= yPs then
start = 0
while start <= ymax
scan
#gd "color cyan"
#gd "line ";0;" ";yScreen(start);" ";400;" ";yScreen(start)
#gd "color black"
#gd "place ";405;" ";yScreen(start);";";start
start = start + inc
wend
start = 0
while start >= ymin
scan
#gd "color cyan"
#gd "line ";0;" ";yScreen(start);" ";400;" ";yScreen(start)
#gd "color black"
#gd "place ";405;" ";yScreen(start);";";start
start = start  inc
wend
else
start = ymin
for i = 0 to 20
#gd "color cyan"
#gd "line ";0;" ";i * 20;" ";400;" ";i * 20
#gd "color black"
#gd "place ";405;" ";400 (i*20);";";start
start = start + inc
next
end if
#gd "size 2"
'x, y axis if in graph
#gd "color yellow"
if 0 <= y0 and y0 <= yPs then
#gd "line ";xScreen(xmin);" ";y0;" ";xScreen(xmax);" ";y0
end if
if 0 <= x0 and x0 <= xPs then
#gd "line ";x0;" ";yScreen(ymin);" ";x0;" ";yScreen(ymax)
end if
'fx graph
#gd "color blue"
stepper = (xmax  xmin)/xPs
for xfx = xmin to xmax step stepper
if xfx <= xmin then
lastx = xScreen(xfx) : lasty = yScreen(fx(xfx))
else
x = xScreen(xfx) : y = yScreen(fx(xfx))
if x > 0 and x < xPs and y > 0 and y < yPs then
if lastx > 0 and lastx <= xPs and lasty > 0 and lasty <= yPs then
#gd "line ";lastx;" ";lasty;" ";x;" ";y
end if
end if
end if
lastx = x : lasty = y
next
wait
[quitGraphDialog]
close #gd
end sub
'conversions (logical coords to screen) tsh73 20170304
function xScreen(x)
'global xPs, yPs, xmin, ymin, xmax, ymax 'for xScreen, yScreen functions
xScreen = (x  xmin) / (xmax  xmin) * xPs
end function
function yScreen(y)
'global xPs, yPs, xmin, ymin, xmax, ymax 'for xScreen, yScreen functions
yScreen = (1  (y  ymin) / (ymax  ymin)) * yPs
end function
function fx(x) 'any general function of x
'fx = sin(x) 'xmin=2*pi : xmax=2*pi : ymin =2 : ymax=2
'fx = x^2 +2*x 35 'roots 5, 7 xmin=10 : xmax=10 : ymin =10 : ymax=10
fx = exp(x)
end function
Maybe x, y min and max should be arguments to call with sub?
EDIT: oops! don't want to draw yellow axis if not in gray box area, code updated 12:54 PM EDIT2: 20170307 (again) 1:22 PM fix some color lines that didn't "take" at 1:04 PM edit.

« Last Edit: Mar 7^{th}, 2017, 12:23pm by bplus » 
Logged

B+



Facundo
Board Moderator
member is offline
Gender:
Posts: 1286


Re: "Gridlock" Graph Dialog
« Reply #1 on: Mar 7^{th}, 2017, 7:22pm » 

Passing the values will make the SUB more portable. All of them, or are they too many? What about calculating pi in the SUB? So it is not Global. Don't know.


Logged

cundo aka MSlayer



bplus
Senior Member
member is offline
Gender:
Posts: 1132


Re: "Gridlock" Graph Dialog
« Reply #2 on: Mar 7^{th}, 2017, 8:53pm » 

I think I am decided on globals xmin, xmax, ymin, ymax (though they might be called something more unique to where they are applied to avoid variable name conflicts). If showGraph was the only procedure that needed them, I would pass them for portability just as you say. But xScreen and yScreen use them too and they get called allot inside showGraph.
pi also stays global because it is needed or potentially in a couple places I plan to use this graph dialog, it should be a universal constant.
What I can get rid of globally is xPs, yPs the x, y pixel width and height of the #gd window as they are exclusively needed only for the window and remain constant.
Thanks for your thoughts.
I am seeing allot of repetitious code for drawing grids and suspect there exist a clever way to condense the repetitious parts with loops.

« Last Edit: Mar 7^{th}, 2017, 9:02pm by bplus » 
Logged

B+



bplus
Senior Member
member is offline
Gender:
Posts: 1132


Re: "Gridlock" Graph Dialog
« Reply #3 on: Mar 8^{th}, 2017, 9:45pm » 

Oh, now I remember another reason why I wanted a Graph Dialog!
To graph this guy: Code:' Graph Dialog 3.txt for JB [B+=MGA] 20170308
' from gridlock Graph Dialog.txt finished 20170307
' remove globals xPs, yPs as they are constants
' rename xmin, xmax, ymin, ymax globals to something less likely to conflict
' add a Title to the screen on title bar.
' Test new stuff with graph of x^(1/x) which has max at e.
global pi, rad, deg, Dflag
global sminx, sminy, smaxx, smaxy 'for xScreen, yScreen functions
pi = acs(1)
rad = pi / 180
deg = 180 / pi
Dflag = 1 'measure angles in degrees else radians
'sminx=2*pi : smaxx=pi : sminy =2 : smaxy=1 'sin(x)
'sminx=10 : smaxx=5 : sminy =50 : smaxy=10 'quadradic x^2 + 2*x  35
'sminx=2 : smaxx=5 : sminy =1 : smaxy=100 'exp(x)
sminx=1 : smaxx=11 : sminy =1 : smaxy=2 'n^(1/n)
call ShowGraph "This is x ^ (1 / x) where it should max at e constant."
print "Done, bye!"
sub ShowGraph gTitle$
WindowWidth = 500
WindowHeight = 500
UpperLeftX = int((DisplayWidth  WindowWidth) / 2)
UpperLeftY = int((DisplayHeight  WindowHeight) / 2)
open gTitle$ for graphics_nsb_nf as #gd
#gd "font arial 8"
#gd "trapclose [quitGraphDialog]"
#gd "down"
'graph box section
#gd "color cyan"
#gd "backcolor lightgray"
#gd "place ";0;" ";0
#gd "boxfilled ";400;" ";400
#gd "backcolor white"
x0 = xScreen(0) : y0 = yScreen(0)
'xgrid lines
inc = (smaxx  sminx) / 20
#gd "color cyan"
if 0 <= x0 and x0 <= 400 then
start = 0
while start <= smaxx
scan
#gd "line ";xScreen(start);" ";0;" ";xScreen(start);" ";400
start = start + inc
wend
start = 0
while start >= sminx
scan
#gd "line ";xScreen(start);" ";0;" ";xScreen(start);" ";400
start = start  inc
wend
else
start = sminx
for i = 0 to 20
#gd "line ";i * 20;" ";0;" ";i * 20;" ";400
start = start + inc
next
end if
#gd "color black"
#gd "place "; 2;" ";415;"; x min (left) is ";sminx;"."
#gd "place ";145;" ";430;"; x scale increment is ";inc;"."
#gd "place ";170;" ";445;"; x middle is ";sminx + 10 * inc;"."
#gd "place ";325;" ";460;"; x max (right) is ";smaxx;"."
'y grid lines
inc = (smaxy  sminy) / 20
if 0 <= y0 and y0 <= 400 then
start = 0
while start <= smaxy
scan
#gd "color cyan"
#gd "line ";0;" ";yScreen(start);" ";400;" ";yScreen(start)
#gd "color black"
#gd "place ";405;" ";yScreen(start);";";start
start = start + inc
wend
start = 0
while start >= sminy
scan
#gd "color cyan"
#gd "line ";0;" ";yScreen(start);" ";400;" ";yScreen(start)
#gd "color black"
#gd "place ";405;" ";yScreen(start);";";start
start = start  inc
wend
else
start = sminy
for i = 0 to 20
#gd "color cyan"
#gd "line ";0;" ";i * 20;" ";400;" ";i * 20
#gd "color black"
#gd "place ";405;" ";400 (i*20);";";start
start = start + inc
next
end if
#gd "size 2"
'x, y axis if in graph
#gd "color yellow"
if 0 <= y0 and y0 <= 400 then
#gd "line ";xScreen(sminx);" ";y0;" ";xScreen(smaxx);" ";y0
end if
if 0 <= x0 and x0 <= 400 then
#gd "line ";x0;" ";yScreen(sminy);" ";x0;" ";yScreen(smaxy)
end if
'fx graph
#gd "color blue"
stepper = (smaxx  sminx)/400
for xfx = sminx to smaxx step stepper
if xfx <= sminx then
lastx = xScreen(xfx) : lasty = yScreen(fx(xfx))
else
x = xScreen(xfx) : y = yScreen(fx(xfx))
if x > 0 and x < 400 and y > 0 and y < 400 then
if lastx > 0 and lastx <= 400 and lasty > 0 and lasty <= 400 then
#gd "line ";lastx;" ";lasty;" ";x;" ";y
end if
end if
end if
lastx = x : lasty = y
next
wait
[quitGraphDialog]
close #gd
end sub
'conversions (logical coords to screen) tsh73 20170304
function xScreen(x)
'global sminx, sminy, smaxx, smaxy 'for xScreen, yScreen functions
xScreen = (x  sminx) / (smaxx  sminx) * 400
end function
function yScreen(y)
'global sminx, sminy, smaxx, smaxy 'for xScreen, yScreen functions
yScreen = (1  (y  sminy) / (smaxy  sminy)) * 400
end function
function fx(x) 'any general function of x
'fx = sin(x) 'sminx=2*pi : smaxx=2*pi : sminy =2 : smaxy=2
'fx = x^2 +2*x 35 'roots 5, 7 sminx=10 : smaxx=10 : sminy =10 : =10
'fx = exp(x)
if x <> 0 then fx = x^(1/x)
end function
Here is new dialog with the title as parameter to call to showGraph, plus all the changes discussed so far.
It is nice to get a quick snapshot of a function you might be working.
I see now this needs controls to zoom in and out, left and right, up and down.
But this particular function pretty much looks like a flat line between sminx = 2.7 and smaxx = 2.8


Logged

B+



bplus
Senior Member
member is offline
Gender:
Posts: 1132


Re: "Gridlock" Graph Dialog
« Reply #4 on: Mar 9^{th}, 2017, 9:20pm » 

With zoom in and out, left right, up down arrows working:
Code:' Graph Dialog 4.txt for JB [B+=MGA] 201703
' from Graph Dialog 3.txt for JB [B+=MGA] 20170308
' now he wants zoom in/out, shift left/right/up/down, well OK!
' graphing dots instead of lines now
global pi, rad, deg, Dflag
global sminx, sminy, smaxx, smaxy 'for xScreen, yScreen functions
pi = acs(1)
rad = pi / 180
deg = 180 / pi
Dflag = 1 'measure angles in degrees else radians
'sminx=2*pi : smaxx=pi : sminy =2 : smaxy=1 'sin(x)
'sminx=10 : smaxx=5 : sminy =50 : smaxy=10 'quadradic x^2 + 2*x  35
'sminx=2 : smaxx=5 : sminy =1 : smaxy=100 'exp(x)
sminx=1 : smaxx=11 : sminy =1 : smaxy=2 'n^(1/n)
call ShowGraph "This is x ^ (1 / x) where it should max at e constant."
print "Done, bye!"
sub ShowGraph gTitle$
WindowWidth = 510
WindowHeight = 550
UpperLeftX = int((DisplayWidth  WindowWidth) / 2)
UpperLeftY = int((DisplayHeight  WindowHeight) / 2)
textbox #gd.tb 55, 485, 340, 25
open gTitle$ for graphics_nsb_nf as #gd
#gd.tb " Zoom: i = in o = out Arrows: left, right, up down"
#gd "when characterInput [keyHandler]"
#gd "font arial 8"
#gd "trapclose [quitGraphDialog]"
#gd "down"
#gd "setfocus"
[restartGraphDialog]
scan
#gd "cls"
#gd "size 1"
'graph box section
#gd "color cyan"
#gd "backcolor lightgray"
#gd "place ";0;" ";0
#gd "boxfilled ";400;" ";400
#gd "backcolor white"
x0 = xScreen(0) : y0 = yScreen(0)
'xgrid lines
inc = (smaxx  sminx) / 20
#gd "color cyan"
if 0 <= x0 and x0 <= 400 then
start = 0
while start <= smaxx
scan
#gd "line ";xScreen(start);" ";0;" ";xScreen(start);" ";400
start = start + inc
wend
start = 0
while start >= sminx
scan
#gd "line ";xScreen(start);" ";0;" ";xScreen(start);" ";400
start = start  inc
wend
else
start = sminx
for i = 0 to 20
#gd "line ";i * 20;" ";0;" ";i * 20;" ";400
start = start + inc
next
end if
#gd "color black"
#gd "place "; 2;" ";415;"; x min (left) is ";sminx;"."
#gd "place ";145;" ";430;"; x scale increment is ";inc;"."
#gd "place ";170;" ";445;"; x middle is ";sminx + 10 * inc;"."
#gd "place ";325;" ";460;"; x max (right) is ";smaxx;"."
'y grid lines
inc = (smaxy  sminy) / 20
if 0 <= y0 and y0 <= 400 then
start = 0
while start <= smaxy
scan
#gd "color cyan"
#gd "line ";0;" ";yScreen(start);" ";400;" ";yScreen(start)
#gd "color black"
#gd "place ";405;" ";yScreen(start);";";start
start = start + inc
wend
start = 0
while start >= sminy
scan
#gd "color cyan"
#gd "line ";0;" ";yScreen(start);" ";400;" ";yScreen(start)
#gd "color black"
#gd "place ";405;" ";yScreen(start);";";start
start = start  inc
wend
else
start = sminy
for i = 0 to 20
#gd "color cyan"
#gd "line ";0;" ";i * 20;" ";400;" ";i * 20
#gd "color black"
#gd "place ";405;" ";400 (i*20);";";start
start = start + inc
next
end if
#gd "size 2"
'x, y axis if in graph
#gd "color yellow"
if 0 <= y0 and y0 <= 400 then
#gd "line ";xScreen(sminx);" ";y0;" ";xScreen(smaxx);" ";y0
end if
if 0 <= x0 and x0 <= 400 then
#gd "line ";x0;" ";yScreen(sminy);" ";x0;" ";yScreen(smaxy)
end if
'fx graph just dots now
#gd "color blue"
stepper = (smaxx  sminx)/400
for xfx = sminx to smaxx step stepper
x = xScreen(xfx) : y = yScreen(fx(xfx))
if x > 0 and x < 400 and y > 0 and y < 400 then
#gd "set ";x;" ";y
end if
next
#gd "flush"
wait
[keyHandler] 'all these just readjust sminx, smaxx, sminx, sminy
key$ = Inkey$
if len(key$) < 2 then
if key$ = "o" then
diff = (smaxx  sminx) / 2 : sminx = sminx  diff : smaxx = smaxx + diff
diff = (smaxy  sminy) / 2 : sminy = sminy  diff : smaxy = smaxy + diff
end if
if key$ = "i" then
diff = (smaxx  sminx) / 4 : sminx = sminx + diff : smaxx = smaxx  diff
diff = (smaxy  sminy) / 4 : sminy = sminy + diff : smaxy = smaxy  diff
end if
else
select case asc(right$(key$, 1))
case 37 'left
diff = (smaxx  sminx) * .1 : sminx = sminx  diff : smaxx = smaxx  diff
case 38 'up
diff = (smaxy  sminy) * .1 : sminy = sminy + diff : smaxy = smaxy + diff
case 39 'right
diff = (smaxx  sminx) * .1 : sminx = sminx + diff : smaxx = smaxx + diff
case 40 'down
diff = (smaxy  sminy) * .1 : sminy = sminy  diff : smaxy = smaxy  diff
end select
end if
goto [restartGraphDialog]
[quitGraphDialog]
close #gd
end sub
'conversions (logical coords to screen) tsh73 20170304
function xScreen(x)
'global sminx, sminy, smaxx, smaxy 'for xScreen, yScreen functions
xScreen = (x  sminx) / (smaxx  sminx) * 400
end function
function yScreen(y)
'global sminx, sminy, smaxx, smaxy 'for xScreen, yScreen functions
yScreen = (1  (y  sminy) / (smaxy  sminy)) * 400
end function
function fx(x) 'any general function of x
'fx = sin(x) 'sminx=2*pi : smaxx=2*pi : sminy =2 : smaxy=2
'fx = x^2 +2*x 35 'roots 5, 7 sminx=10 : smaxx=10 : sminy =10 : =10
'fx = exp(x)
if not(x < .1) then fx = x^(1/x) 'get float as x goes to 0
end function


Logged

B+



Rod
Administrator
member is offline
Graphics = Goosebumps!
Gender:
Posts: 3070


Graph Dialog/Function
« Reply #5 on: Mar 10^{th}, 2017, 02:50am » 

Interesting since we don't have a native function to chart data. It crops up quite often, people asking how to chart data.
This is a different approach, it will take array data and attempt to chart it, adjusting itself to what it finds in the array.
Code:nomainwin
'set up some dummy x,y data in points() array
dim points(2,1000)
for n= 1 to 1000
degree=degree+1
if degree>359 then degree=0
y=sin(degree/57.29577951)*300
'points(1,n)=y^2/100 'x
'points(1,n)=y 'x
points(1,n)=n 'x
points(2,n)=y 'y
next
'specify our chart format
width=400
height=400
x=(DisplayWidthwidth)/2
y=(DisplayHeightheight)/2
rangestart=0
rangeend=1000
ret=chart(x,y,width,height,rangestart,rangeend)
wait
function chart(x,y,w,h,s,e)
' add a margin of 80 pixels for scale text
WindowWidth = w+80
WindowHeight = h+80
UpperLeftX = x
UpperLeftY = y
'place a charting box centered
cx=40
cy=10
open "Graph" for graphics_nf_nsb as #1
#1 "down ; trapclose [quit] ; font consolas 8"
' fancy shaded background you could equally down ; fill black
' find y increment in color 128 to 256 so 128 steps
incc=0128/h
#1 "place ";cx1;" ";cy1;" ;box ";cx+w+2;" ";cy+h+2
for y=h to 1 step 1
#1 "color ";y*incc+256;" ";y*incc+256;" ";y*incc+256
#1 "line ";cx;" ";cy+y;" ";cx+w+1;" ";cy+y
next y
' how many points to chart
nopoints=es
' find scale min and max
minx=points(1,s)
maxx=points(1,s)
miny=points(2,s)
maxy=points(2,s)
for n= s to e
if minx>points(1,n) then minx=points(1,n)
if maxx<points(1,n) then maxx=points(1,n)
if miny>points(2,n) then miny=points(2,n)
if maxy<points(2,n) then maxy=points(2,n)
next
'calculate scale increase per pixel line
'write text every 20 pixels
'set mid point as 0,0 initially
mx=0
my=0
incx=(maxxminx)/w
incy=(maxyminy)/h
for y=h to 0 step 20
s$=str$(int(maxyy*incy))
if left$(s$,1)=""then
s$=right$(s$,len(s$)1)
#1 "color red"
else
#1 "color black"
end if
sx=len(s$)*6
if int(maxyy*incy)>1 and int(maxyy*incy)<1 then
#1 "place ";cx;" ";cy+y;" ;color yellow ; turn 90 ; go ";w
#1 "color black"
my=y
end if
#1 "place ";cxsx5;" ";cy+y+5;" ;\";s$
next
for x=0 to w step 20
s$=str$(int(minx+x*incx))
if left$(s$,1)=""then
s$=right$(s$,len(s$)1)
#1 "color red"
else
#1 "color black"
end if
if int(minx+x*incx)>1 and int(minx+x*incx)<1 then
#1 "place ";cx+x;" ";cy+h;" ;color yellow ; north ; go ";h
#1 "color black"
mx=x
end if
for l=1 to len(s$)
#1 "place ";cx8+x+l*6;" ";cy+5+h+l*8;" ;\";mid$(s$,l,1)
next
next
'chart the actual data
#1 "color blue"
for n=s to e
#1 "set ";cx+mx+points(1,n)/incx;" ";cy+my+points(2,n)/incy
next
#1 "flush"
end function
[quit]
close #1
end


Logged




bplus
Senior Member
member is offline
Gender:
Posts: 1132


Re: "Gridlock" Graph Dialog
« Reply #6 on: Mar 10^{th}, 2017, 11:23am » 

Well I was going for graphing a function in a dialog but graphing data would probably be more useful for general purposes. Graphing data does not need zooms and pans and might make displaying numbers easier. Graphing data has quite a variety of displays: point charts, line charts, bar charts, pie charts, histograms...
Rod, I like your background and the way you did x value markers but what if you were graphing on a range of x between say 1.1 and 1.2?
That reminds of a problem I had establishing an increment for the graph markers to the nearest power of 10, say for xmin at 1.15 and xmax at 1.23 you would want to mark increments at .01 or if too many, .1 If the the x axis were around the inside of the graph, you'd want to mark up and down from 0... tricky! Well I could test your code and see it handles that!
I suppose I could modify my code to work out of an array be it from data or from a function for more general uses.

« Last Edit: Mar 10^{th}, 2017, 11:41am by bplus » 
Logged

B+



