X-Y Graphics

BlitzPlus Forums/BlitzPlus Programming/X-Y Graphics

Oldefoxx(Posted 2003) [#1]
In working with passive parabolic antenna concepts, I wanted a graphing tool that would graph from equations, not from freehand entries. Not too much out there that will do this, so I ended up borrowing a couple of ideas and writing my own. I included some of the comments and equations that I have been playing with to show how it works, but you can modify the program to plot and display any y=f(x) equation that fits within the bounds. Play with the mouse and keys to figure out how the controls work, or cheat and read the embedded comments.

;Parabolic Antenna Calculator Program

;The speed of light in a vacuum is approximatly 299,792,458 m/s (186282 miles/sec)
;The speed of light in air is approximatly .03% slower (299,702,547.2 m.s)
;The lowest frequency of 802.11g is 2.4GHz, the highest is 2.4835GHz
;A full wave length at 2.4Ghz in air is approximately 12.4876 mm
;basic parabolic equations:

; basic form of equation: y=ax^2
; find value For a above: a=h(w/2)^2 'h=max height, w=max width
; length of parabolic arc: l=1w*(1+2/3*(2d/l)^2-2/5*(2d/l)^4+ ...
; length of parabolic arc: n=h/w:
; l=2w*(Sqr(n^2+1/16)+1/(16n)(ln(n+Sqr(n^2+1/16)+ln4)
; area within parabola: A=2hw/3
; height h(x) at w(x): h(x)=h/w^2*(w^2-w(x)^2)
; width w(x) at h(x): w(x)=w*Sqr((h-h(x)^2)/h)
; Vertex at (h.k), vertical alignment, a is negative (upside down U):
; Distance from Vertex To focus point (p) is = a
; Distance from Vertex To directrix Line = a
; Latus rectum (Line through focus parallel To directrix) = 4a in length


Global xmin=-30 ;lowest value for x to be graphed
Global xmax=30 ;highest value for x to be graphed
Global scale#=5 ;scale the resulting plot by some factor
Global wmax=4620 ;rightmost viewable window pixel reference
Global hmax=4620 ;bottommost viewable window pixel reference
Global wmin=0 ;leftmost viewable window pixel reference
Global hmin=0 ;topmost viewable window pixel reference
Global wmid=wmax/2 ;center of viewable area horizontally
Global hmid=hmax/2 ;center of viewable area vertically
Global zoom=10 ;magnifier for windows viewpoint
Global grid=1 ;distance of displayed grid marks
Global width=800 ;number of pixels horizontally
Global height=600 ;number of pixels vertically
Global woffset=width/2 ;viewpoint width offset, all factors included
Global hoffset=height/2 ;viewpoint height offset, all factors included
Global showscale=0 ;toggles bottom and right scale display
Graphics width,height,16,2 ;pick your windows size and colors
SetBuffer BackBuffer() ;do plotting out of sight
owoffset=woffset
ohoffset=hoffset
ozoom=zoom
Flip
Cls
Goto redraw
While Not KeyHit(1)
If KeyDown(30) Or KeyDown(78) Then ;"A" or "+" zoom in
If zoom<1000 Then
zoom=zoom+1+zoom/50
Goto redraw
EndIf
EndIf
If KeyDown(44) Or KeyDown(74) Then ;"Z" or "-" zoom out
If zoom>1 Then
zoom=zoom-1-zoom/50
Goto redraw
EndIf
EndIf
If KeyDown(75) Or KeyDown(203) Or KeyDown(219) Then ;left arrow (offset right)
woffset=woffset+10
Goto redraw
EndIf
If KeyHit(31) Then ;"S" show/hide scales at bottom and right side
showscale=Not showscale
Goto redraw
EndIf
If KeyDown(71) Then ;left and up (offset down & right)
woffset=woffset+10
hoffset=hoffset+10
Goto redraw
EndIf
If KeyDown(72) Or KeyDown(200) Then ;up arrow (offset down)
hoffset=hoffset+10
Goto redraw
EndIf
If KeyDown(73) Then ;up and right (offset down and left)
woffset=woffset-10
hoffset=hoffset+10
Goto redraw
EndIf
If KeyDown(77) Or KeyDown(205) Or KeyDown(220) Then ;right
woffset=woffset-10
Goto redraw
EndIf
If KeyDown(79) Then ;down and left (offset up and right)
woffset=woffset+10
hoffset=hoffset-10
Goto redraw
EndIf
If KeyDown(81) Then ;down and right (offset up and left)
woffset=woffset-10
hoffset=hoffset-10
Goto redraw
EndIf
If KeyDown(80) Or KeyDown(208) Then ;down (offset up)
hoffset=hoffset-10
Goto redraw
EndIf
If KeyHit(199) Then ;home key (toggle with previous home setting)
h=woffset
woffset=owoffset
owoffset=h
h=hoffset
hoffset=ohoffset
ohoffset=h
h=zoom
zoom=ozoom
ozoom=h
Goto redraw
EndIf
If KeyDown(207) Then ;end key (set previous home setting to current)
owoffset=woffset
ohoffset=hoffset
ozoom=zoom
EndIf
mxs=MouseXSpeed() ;get the mouse x position
mys=MouseYSpeed() ;get the mouse y position
If MouseDown(1) ;check for mouse left button down
woffset=woffset+mxs ;if mouse, update width offset
hoffset=hoffset+mys ;if mouse, update height offset
.redraw ;perform screen redraws when necessary
Cls
drawgraph() ;first, we redraw the grid view in the window

;-------MODIFY THE FOLLOWING SECTION FOR WHATEVER EQUATIONS(S) YOU WANT TO PLOT-------
m$="y=x^2/100" ;this is the equation that we want to show and plot
length#=0 ;begin with a length of zero
For x#=xmin*scale To xmax*scale ;this is the equation plot process
y#=x#*x#/100 ;this is the equation in practice for each value of x
If x#>xmin*scale Then ;Plot line segments between consecutive points
Line ox#*zoom+woffset,hoffset-oy#*zoom,x#*zoom+woffset,hoffset-y#*zoom
lx#=x#-ox# ;remember the previous x coordinate
ly#=y#=oy# ;remember the previous x coordinate
lx#=lx#*lx#+ly#*ly# ;calculate the direct length between consecutive points
If lx#>0 Then length#=length#+Sqr(lx#) ;maintain a sum of the lengths
Else
Plot x#*zoom+woffset,hoffset-y#*zoom ;plot the initial points
EndIf
ox#=x#
oy#=y#
Next
;-----------------------END OF SECTION FOR EQUATION PLOTTING--------------------------

Flip ;display the equation as plotted
Viewport width-Len(m$)*8,height0,width,height0+13 ;pick text area to clear
Cls ;clear text area
Locate width-Len(m$)*8-1,height0 ;position to write text
Write m$ ;write equation plotted
Goto redraw1 ;finish redrawing text
EndIf
xpos=(MouseX()-woffset)/zoom
ypos=(hoffset-MouseY())/zoom
.redraw1 ;redraw text when necessary
n$="("+xpos+","+ypos+") " ;put mouse coordinates into n$
Viewport width0,height0,Len(n$)*8+1,height0+13 ;pick test area to clear
Cls ;clear text area
Locate width0,height0 ;position to write text
Write n$ ;write coordinates om screen
Viewport width0,height0,width,height ;resize to the normal size screen
Wend

Function drawgraph()
sizing=grid*zoom ;set the side of the area to be drawn
Color 50,50,50 ;make the gridlines a low level grey color
x=woffset Mod sizing ;determine the offset for the first grid line
While x<=wmax ;create all vertical grid lines
Line x,hmin,x,hmax
x=x+sizing
Wend
y=hoffset Mod sizing ;determine the offset for the first grid line
While y<=hmax ;create all horizontal grid lines
Line wmin,y,wmax,y
y=y+sizing
Wend
If showscale Then ;determine if the scales are to be drawn
j#=sizing*5 ;scale lines are every fifth grid line
Color 255,255,255
Line width0,height-35,width,height-35 ;the horizontal scale line along the bottom
k#=woffset ;work from the grid center backwards
i=0
While k#>=width0 ;continue while display area remains
If h#<=width Then ;don't display if still out of view area
Line k#,height-45,k#,height-35 ;make a tick mark on the horizontal scale line
Locate k#-5,height-35 ;position to write the tick mark value
Write Str$(i) ;write the tick mark value
EndIf
k#=k#-j# ;decrement the amount to the next tick mark
i=i-10 ;decrement the tick count by ten
Wend
k#=woffset+j# ;start at the tick position right of center
i=10 ;start with a tick count of ten
While k#<=width ;continue across the viewable area
If k#>=width0 Then ;don't bother with line if out of viewable area
Line k#,height-45,k#,height-35 ;draw the tick mark indicated
Locate k#-5,height-35 ;position to write the tick mark value
Write Str$(i) ;write the tick mark value
EndIf
k#=k#+j# ;increment the tick mark offset position
i=i+10 ;increment the tick mark count by 10
Wend
Line width-20,height0+20,width-20,height-35 ;draw the right side vertical scale line
k#=hoffset ;begin at the center crosshairs
i=0 ;set the tick count to zero
While k#>=height0+30 ;don't mess up the equation text area
If k#<height Then ;don't draw line if not in viewable area
Line width-35,k#,width-20,k# ;draw a tick mark against the vertical scale line
n$=Str$(i) ;create the text for the tick count value
Locate width-Len(n$)*8+5*(i<0),k#-5 ;position to write the tick count value
Write n$ ;write the tick count value
EndIf
k#=k#-j# ;decrement the tick mark offset position
i=i-10 ;decrement the tick mark count by 10
Wend
k#=hoffset+j# ;start at one tick mark below crosshairs
i=10 ;start with a count of ten
While k#<=height-30 ;continue until out of viewable area
If k#>=height0 Then ;delay line if not yet in viewable area
Line width-35,k#,width-20,k# ;draw tick mark up to vertical scale line
n$=Str$(i) ;get tick mark count
Locate width-Len(n$)*8+5,k#-5 ;position to write tick mark count
Write Str$(i) ;write tick mark count
EndIf
k#=k#+j# ;increment tick mark position
i=i+10 ;increment tick mark count by 10
Wend
EndIf
xlen=1000*zoom ;we arbitrarily make the cross hairs 1000 long
Color 128,255,128 ;make the crosshairs the color of green
Line woffset-xlen,hoffset,woffset+xlen,hoffset ;paint the horizontal crosshair first
Line woffset,hoffset-xlen,woffset,hoffset+xlen ;paint the vertical crosshair second
Color 255,255,255 ;set the current color to bright white
End Function


Oldefoxx(Posted 2003) [#2]
The program above was a first attempt. I have since made many changes and extended it, and the new version (without the parabolic code) has now been added to the Code Archives under 2D Graphics with the name X-Y 2D Graphs. I put code in it to draw two random straight line segments, fine their equations, then use Cramer's Rule with some limits to find out if the lines segments, as plotted, intersect.

Note that computers do not see things as humans do, and while I could draw a couple of lines on any surface and tell from looking at them if they intersect, computers are not equipped to see and make this type of determination.
For computers, you end up with having to deal with equations, coordinates, bit-maps (such as from scanners), or vectors as a rule.

This program allows you to begin to bridge the gap between what computers can be programmed to do, and what comes naturally to humans, or can be learned in terms of describing the world around us.